Exemple #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);
    }
}
Exemple #2
0
static void
dump_thread(void *arg)
{
    HANDLE dbghelp;
    BOOL (WINAPI *pSymInitialize)(HANDLE, const char *, BOOL);
    BOOL (WINAPI *pSymCleanup)(HANDLE);
    BOOL (WINAPI *pStackWalk64)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64);
    DWORD64 (WINAPI *pSymGetModuleBase64)(HANDLE, DWORD64);
    BOOL (WINAPI *pSymFromAddr)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *);
    BOOL (WINAPI *pSymGetLineFromAddr64)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *);
    HANDLE (WINAPI *pOpenThread)(DWORD, BOOL, DWORD);
    DWORD tid = *(DWORD *)arg;
    HANDLE ph;
    HANDLE th;

    dbghelp = LoadLibrary("dbghelp.dll");
    if (!dbghelp) return;
    pSymInitialize = (BOOL (WINAPI *)(HANDLE, const char *, BOOL))GetProcAddress(dbghelp, "SymInitialize");
    pSymCleanup = (BOOL (WINAPI *)(HANDLE))GetProcAddress(dbghelp, "SymCleanup");
    pStackWalk64 = (BOOL (WINAPI *)(DWORD, HANDLE, HANDLE, STACKFRAME64 *, void *, PREAD_PROCESS_MEMORY_ROUTINE64, PFUNCTION_TABLE_ACCESS_ROUTINE64, PGET_MODULE_BASE_ROUTINE64, PTRANSLATE_ADDRESS_ROUTINE64))GetProcAddress(dbghelp, "StackWalk64");
    pSymGetModuleBase64 = (DWORD64 (WINAPI *)(HANDLE, DWORD64))GetProcAddress(dbghelp, "SymGetModuleBase64");
    pSymFromAddr = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD64 *, SYMBOL_INFO *))GetProcAddress(dbghelp, "SymFromAddr");
    pSymGetLineFromAddr64 = (BOOL (WINAPI *)(HANDLE, DWORD64, DWORD *, IMAGEHLP_LINE64 *))GetProcAddress(dbghelp, "SymGetLineFromAddr64");
    pOpenThread = (HANDLE (WINAPI *)(DWORD, BOOL, DWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "OpenThread");
    if (pSymInitialize && pSymCleanup && pStackWalk64 && pSymGetModuleBase64 &&
	pSymFromAddr && pSymGetLineFromAddr64 && pOpenThread) {
	SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES);
	ph = GetCurrentProcess();
	pSymInitialize(ph, NULL, TRUE);
	th = pOpenThread(THREAD_SUSPEND_RESUME|THREAD_GET_CONTEXT, FALSE, tid);
	if (th) {
	    if (SuspendThread(th) != (DWORD)-1) {
		CONTEXT context;
		memset(&context, 0, sizeof(context));
		context.ContextFlags = CONTEXT_FULL;
		if (GetThreadContext(th, &context)) {
		    char libpath[MAX_PATH];
		    char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
		    SYMBOL_INFO *info = (SYMBOL_INFO *)buf;
		    DWORD mac;
		    STACKFRAME64 frame;
		    memset(&frame, 0, sizeof(frame));
#if defined(_M_AMD64) || defined(__x86_64__)
		    mac = IMAGE_FILE_MACHINE_AMD64;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.Rip;
		    frame.AddrFrame.Mode = AddrModeFlat;
		    frame.AddrFrame.Offset = context.Rbp;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.Rsp;
#elif defined(_M_IA64) || defined(__ia64__)
		    mac = IMAGE_FILE_MACHINE_IA64;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.StIIP;
		    frame.AddrBStore.Mode = AddrModeFlat;
		    frame.AddrBStore.Offset = context.RsBSP;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.IntSp;
#else	/* i386 */
		    mac = IMAGE_FILE_MACHINE_I386;
		    frame.AddrPC.Mode = AddrModeFlat;
		    frame.AddrPC.Offset = context.Eip;
		    frame.AddrFrame.Mode = AddrModeFlat;
		    frame.AddrFrame.Offset = context.Ebp;
		    frame.AddrStack.Mode = AddrModeFlat;
		    frame.AddrStack.Offset = context.Esp;
#endif

		    while (pStackWalk64(mac, ph, th, &frame, &context, NULL,
					NULL, NULL, NULL)) {
			DWORD64 addr = frame.AddrPC.Offset;
			IMAGEHLP_LINE64 line;
			DWORD64 displacement;
			DWORD tmp;

			if (addr == frame.AddrReturn.Offset || addr == 0 ||
			    frame.AddrReturn.Offset == 0)
			    break;

			memset(buf, 0, sizeof(buf));
			info->SizeOfStruct = sizeof(SYMBOL_INFO);
			info->MaxNameLen = MAX_SYM_NAME;
			if (pSymFromAddr(ph, addr, &displacement, info)) {
			    if (GetModuleFileName((HANDLE)(uintptr_t)pSymGetModuleBase64(ph, addr), libpath, sizeof(libpath)))
				fprintf(stderr, "%s", libpath);
			    fprintf(stderr, "(%s+0x%I64x)",
				    info->Name, displacement);
			}
			fprintf(stderr, " [0x%p]", (void *)(VALUE)addr);
			memset(&line, 0, sizeof(line));
			line.SizeOfStruct = sizeof(line);
			if (pSymGetLineFromAddr64(ph, addr, &tmp, &line))
			    fprintf(stderr, " %s:%lu", line.FileName, line.LineNumber);
			fprintf(stderr, "\n");
		    }
		}

		ResumeThread(th);
	    }
	    CloseHandle(th);
	}
	pSymCleanup(ph);
    }
    FreeLibrary(dbghelp);
}
void stackDump::dumpStack(){


	int maxtrace=100;
	DWORD64 trace[100];

	HANDLE curproc   = GetCurrentProcess();
	HANDLE curthread = GetCurrentThread();

	CONTEXT context;
	::memset(&context, 0, sizeof(context));
	/*
	__asm
	{
	call GetEIP
	jmp Done
	GetEIP:
	pop eax
	mov context.Eip, eax
	mov context.Ebp, ebp
	push eax
	ret
	Done:
	}
	*/
	context.ContextFlags = CONTEXT_FULL;
	BOOL ok_context =  GetThreadContext(curthread, &context);
	FATAL_ERROR(!ok_context,mT("!ok_context"));

	STACKFRAME64 sf;
	::memset(&sf, 0, sizeof(sf));
	sf.AddrPC.Offset    = context.Eip;
	sf.AddrPC.Mode      = AddrModeFlat;
	sf.AddrFrame.Offset = context.Ebp;
	sf.AddrFrame.Mode   = AddrModeFlat;

	int frame = -2;

	for( ; frame < maxtrace; ++frame )
	{
		if( pStackWalk64(
			0,//PIXEL_FILE_MACHINE_I386,
			curproc, 
			curthread,
			&sf,
			&context,
			0,
			pSymFunctionTableAccess64,
			pSymGetModuleBase64,
			0) )
		{
			if(frame >= 0)
			{
				trace[frame] = (DWORD64)sf.AddrPC.Offset;
			}
		}
		else
		{
			break;
		}
	}

	inner_dumpStack(trace,frame);
}