Stack Trace: Difference between revisions

From OSDev.wiki
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);
    }
}