#include <stdio.h>
#include <windows.h>
#include <Dbghelp.h>
#define JMP_INSTR 0xE9
#define SYM_BUFF_SIZE 512
static BYTE g_stSymbol [ SYM_BUFF_SIZE ] ;
void CallStack(void)
{
int retAddrs;
int saved_ebp;
int callFuncAddrs;
HANDLE hCurProcess;
//Fill the IMAGEHLP_SYMBOL struct
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&g_stSymbol ;
FillMemory ( pSym , NULL , SYM_BUFF_SIZE ) ;
pSym->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL ) ;
pSym->MaxNameLength = SYM_BUFF_SIZE - sizeof ( IMAGEHLP_SYMBOL);
//Initialize & load the symbol table
hCurProcess = (HANDLE)::GetCurrentProcessId();
if(!::SymInitialize(hCurProcess, NULL, TRUE))
{
return;
}
__asm
{
mov eax, dword ptr [ebp+4] //Get the return address
mov retAddrs, eax
mov eax, dword ptr [ebp]
mov saved_ebp, eax
}
printf("CallSatck dump begin... ");
while(saved_ebp > 0)
{
if(retAddrs != 0)
{
callFuncAddrs = *(int *)(retAddrs - 4) + retAddrs;
if((unsigned int)callFuncAddrs > 0x80000000)
{
break;
}
//Jump over the JMP instruction to the real function address
while(JMP_INSTR == *(unsigned char *)callFuncAddrs)
{
int offset = callFuncAddrs + 1;
callFuncAddrs = *(int *)(offset) + (callFuncAddrs + 5);
}
if(!::SymGetSymFromAddr(hCurProcess, (DWORD)callFuncAddrs, NULL, pSym))
{
break;
}
// printf("0x%08X <--", callFuncAddrs);
printf("%s( ) ", pSym->Name);
}
retAddrs = *(int *)(saved_ebp + 4);
saved_ebp = *(int *)saved_ebp;
}
printf(" CallSatck dump end! ");
}
class CTest
{
public:
void Hello()
{
printf("Hello World ");
CallStack();
};
void SetPrivateVal(int nVal)
{
y = nVal;
}
public:
int x;
private:
int y;
};
int Call_C(int a, int b)
{
CallStack();
return (a + b);
}
int Call_B(int a, int b)
{
return Call_C(a, b);
}
int Call_A(int a, int b)
{
return Call_B(a, b);
}
//#include <assert.h>
//#include <BugsLayerUtil.h>
main()
{
// Call_A(10, 20);
CTest test;
test.Hello();
return 0;
}