Stack Trace: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content added Content deleted
(New page: The article Stack shows the layout of a stack and mentions the usefulness of a stack trace in debugging. Often a stack trace is written in assembly as it involves finding the current ...) |
No edit summary |
||
Line 4: | Line 4: | ||
<pre> |
<pre> |
||
void Debug::TraceStackTrace(unsigned int MaxFrames) |
|||
{ |
|||
// Stack contains: |
|||
// Second function argument |
|||
// First function argument (MaxFrames) |
|||
// Return address in calling function |
|||
// ebp of calling function (pointed to by current ebp) |
|||
unsigned int * ebp = &MaxFrames - 2; |
|||
Trace("Stack trace:\n"); |
|||
for(unsigned int frame = 0; frame < MaxFrames; ++frame) |
|||
{ |
|||
unsigned int ip = ebp[1]; |
|||
if(ip == 0) |
|||
// No caller on stack |
|||
break; |
|||
// Unwind to previous stack frame |
|||
ebp = reinterpret_cast<unsigned int *>(ebp[0]); |
|||
unsigned int * arguments = &ebp[2]; |
|||
Trace(" 0x{0:16} \n", ip); |
|||
} |
|||
} |
|||
</pre> |
</pre> |
Revision as of 12:20, 14 March 2009
The article Stack shows the layout of a stack and mentions the usefulness of a stack trace in debugging.
Often a stack trace is written in assembly as it involves finding the current value of the ebp register. If you wish to write you stack trace routine in a higher-level language then you will need to find ebp. This can be done by finding the address of an object in a known location on the stack. One thing we always know is in a fixed location on the stack is the first argument to the current function. Taking the address of this argument gives us the value of the ebp plus 8 bytes. The following C++ code shows how this can be used to walk up the stack:
void Debug::TraceStackTrace(unsigned int MaxFrames) { // Stack contains: // Second function argument // First function argument (MaxFrames) // Return address in calling function // ebp of calling function (pointed to by current ebp) unsigned int * ebp = &MaxFrames - 2; Trace("Stack trace:\n"); for(unsigned int frame = 0; frame < MaxFrames; ++frame) { unsigned int ip = ebp[1]; if(ip == 0) // No caller on stack break; // Unwind to previous stack frame ebp = reinterpret_cast<unsigned int *>(ebp[0]); unsigned int * arguments = &ebp[2]; Trace(" 0x{0:16} \n", ip); } }