Search code examples
windowsstackreverse-engineeringtrace

How debuggers can trace the stack?


I was trying to implement a stack tracer, using stack pointers; RSP and RBP, but I think debuggers use an entirely different way to grab the return addresses, or maybe I am missing something. I can grab the return address of the last stack frame, but I can't get the others because I don't know the size of other stack frames, so I can't figure out how much bytes should I go back from stack frame, to get the return address. Are there anybody know which way do debuggers use to trace stack?


Solution

  • It is possible to trace the stack when the code uses frame pointers. In this case ebp/rbp is used as the frame pointer and functions begin with prologs and end with epilogs. A typical prolog looks like this:

    push    rbp       ; save previous frame pointer
    mov     rbp, rsp  ; initialize this functions frame pointer
    

    A typical epilog looks like this:

    mov     rsp, rbp  ; restore the value of rsp
    pop     rbp       ; restore previous frame pointer value from stack
    retn
    

    Thus in every place in a function rbp points to the stack position where the previous frame pointer is saved and rbp+8 contains the saved return address. To get the called function a debugger should read [rbp+8] value and find a function to which this address belongs. This can be done by searching in debugging symbols. Next it should read [rbp] value to get the frame pointer of the caller function. Continue this process until you find a toplevel function. This is typically a system library function that starts threads.