Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I obtain a stack trace on Windows without using dbghelp.dll?

How do I obtain a stack trace of addresses on Windows without using dbghelp.dll?

I don't need to know what the symbols or function names associated with the addresses, I just want the list of addresses -- something similar to backtrace of *nix systems.

Thanks!

like image 348
Uhall Avatar asked Dec 24 '08 23:12

Uhall


3 Answers

Check out the CaptureStackBackTrace() function, which is in Kernel32.dll. This should do all that you need.

Captures a stack back trace by walking up the stack and recording the information for each frame.

USHORT WINAPI CaptureStackBackTrace(
  __in       ULONG FramesToSkip,
  __in       ULONG FramesToCapture,
  __out      PVOID *BackTrace,
  __out_opt  PULONG BackTraceHash
);
like image 88
Kris Kumler Avatar answered Sep 27 '22 18:09

Kris Kumler


If you want to do this extremely non-portably, you can just read the EBP register and walk the stack yourself. This will only work for the x86 architecture, and it also assumes that the C runtime you're using properly initializes EBP to 0 before calling the first function.

uint32_t read_ebp(void)
{
    uint32_t my_ebp;
    __asm
    {
        mov ebp, my_ebp
    }

    return my_ebp;
}

void backtrace(void)
{
    uint32_t ebp = read_ebp();

    printf("backtrace:\n");

    while(ebp != 0)
    {
        printf("0x%08x\n", ebp);
        ebp = ((uint32_t *)ebp)[1];
    }
}
like image 29
Adam Rosenfield Avatar answered Sep 27 '22 17:09

Adam Rosenfield


Previous variant doesn't work for me(msvc 6), so:

unsigned long prev;
unsigned long addr;
__asm { mov prev, ebp }
while(addr!=0) { 
  addr = ((unsigned long *)prev)[1]; 
  printf("0x%08x\n", addr); 
  prev = ((unsigned long *)prev)[0]; 
}
Adam, thanks for highlighting the way!
like image 25
user80143 Avatar answered Sep 27 '22 16:09

user80143