Example #1
0
// getstacktrace - Traces the stack as far back as possible, or until 'maxdepth'
//   frames have been traced. Populates the CallStack with one entry for each
//   stack frame traced.
//
//   Note: This function uses a documented Windows API to walk the stack. This
//     API is supposed to be the most reliable way to walk the stack. It claims
//     to be able to walk stack frames that do not follow the conventional stack
//     frame layout. However, this robustness comes at a cost: it is *extremely*
//     slow compared to walking frames by following frame (base) pointers.
//
//  - maxdepth (IN): Maximum number of frames to trace back.
//
//  - framepointer (IN): Frame (base) pointer at which to begin the stack trace.
//      If NULL, then the stack trace will begin at this function.
//
//  Return Value:
//
//    None.
//
VOID SafeCallStack::getstacktrace (UINT32 maxdepth, SIZE_T *framepointer)
{
    DWORD        architecture;
    CONTEXT      context;
    UINT32       count = 0;
    STACKFRAME64 frame;
    SIZE_T       programcounter;
    SIZE_T       stackpointer;

    if (framepointer == NULL) {
        // Begin the stack trace with the current frame. Obtain the current
        // frame pointer.
        FRAMEPOINTER(framepointer);
    }

    // Get the required values for initialization of the STACKFRAME64 structure
    // to be passed to StackWalk64(). Required fields are AddrPC and AddrFrame.
#if defined(_M_IX86) || defined(_M_X64)
    architecture   = X86X64ARCHITECTURE;
    programcounter = *(framepointer + 1);
    stackpointer   = *framepointer;  // An approximation.
    context.BPREG  = *framepointer;
    context.IPREG  = programcounter;
    context.SPREG  = stackpointer;
#else
// If you want to retarget Visual Leak Detector to another processor
// architecture then you'll need to provide architecture-specific code to
// obtain the program counter and stack pointer from the given frame pointer.
#error "Visual Leak Detector is not supported on this architecture."
#endif // _M_IX86 || _M_X64

    // Initialize the STACKFRAME64 structure.
    memset(&frame, 0x0, sizeof(frame));
    frame.AddrFrame.Offset = *framepointer;
    frame.AddrFrame.Mode   = AddrModeFlat;
    frame.AddrPC.Offset    = programcounter;
    frame.AddrPC.Mode      = AddrModeFlat;
    frame.AddrStack.Offset = stackpointer;
    frame.AddrStack.Mode   = AddrModeFlat;

    // Walk the stack.
    while (count < maxdepth) {
        count++;
        if (!pStackWalk64(architecture, currentprocess, currentthread, &frame, &context, NULL,
                          pSymFunctionTableAccess64, pSymGetModuleBase64, NULL)) {
            // Couldn't trace back through any more frames.
            break;
        }
        if (frame.AddrFrame.Offset == 0) {
            // End of stack.
            break;
        }

        // Push this frame's program counter onto the CallStack.
        push_back((SIZE_T)frame.AddrPC.Offset);
    }
}
Example #2
0
noreturn snakeBoot(procedure_t *entry, int argc, char* argv[])
{
    setWaterMark(FRAMEPOINTER());

    trap_closure = procClosure(entry);
    trap_argc = 0;
    trap_argv = NULL;
    setjmp(stackreset);
    trap_closure->procedure->proc(trap_closure, trap_argc, trap_argv);
}
Example #3
0
// getstacktrace - Traces the stack as far back as possible, or until 'maxdepth'
//   frames have been traced. Populates the CallStack with one entry for each
//   stack frame traced.
//
//   Note: This function uses a very efficient method to walk the stack from
//     frame to frame, so it is quite fast. However, unconventional stack frames
//     (such as those created when frame pointer omission optimization is used)
//     will not be successfully walked by this function and will cause the
//     stack trace to terminate prematurely.
//
//  - maxdepth (IN): Maximum number of frames to trace back.
//
//  - framepointer (IN): Frame (base) pointer at which to begin the stack trace.
//      If NULL, then the stack trace will begin at this function.
//
//  Return Value:
//
//    None.
//
VOID FastCallStack::getstacktrace (UINT32 maxdepth, SIZE_T *framepointer)
{
    UINT32  count = 0;

    if (framepointer == NULL) {
        // Begin the stack trace with the current frame. Obtain the current
        // frame pointer.
        FRAMEPOINTER(framepointer);
    }

    while (count < maxdepth) {
        if ((SIZE_T*)*framepointer < framepointer) {
            if ((SIZE_T*)*framepointer == NULL) {
                // Looks like we reached the end of the stack.
                break;
            }
            else {
                // Invalid frame pointer. Frame pointer addresses should always
                // increase as we move up the stack.
                m_status |= CALLSTACK_STATUS_INCOMPLETE;
                break;
            }
        }
        if ((SIZE_T)*framepointer & (sizeof(SIZE_T*) - 1)) {
            // Invalid frame pointer. Frame pointer addresses should always
            // be aligned to the size of a pointer. This probably means that
            // we've encountered a frame that was created by a module built with
            // frame pointer omission (FPO) optimization turned on.
            m_status |= CALLSTACK_STATUS_INCOMPLETE;
            break;
        }
        if (IsBadReadPtr((SIZE_T*)*framepointer, sizeof(SIZE_T*))) {
            // Bogus frame pointer. Again, this probably means that we've
            // encountered a frame built with FPO optimization.
            m_status |= CALLSTACK_STATUS_INCOMPLETE;
            break;
        }
        count++;
        push_back(*(framepointer + 1));
        framepointer = (SIZE_T*)*framepointer;
    }
}