#include <Windows.h> #define PULONG_PTR ULONG** #define PULONG ULONG* #define ULONG_PTR ULONG* #include <DbgHelp.h> #include <stdio.h> #include <stdarg.h> #include <stdlib.h> // 添加对dbghelp.lib的编译依赖 // #pragma comment(lib, "dbghelp.lib") const int MAX_ADDRESS_LENGTH = 32; const int MAX_NAME_LENGTH = 1024; // 崩溃信息 // // 安全拷贝字符串函数 // // 得到程序崩溃信息 // // 得到CallStack信息 // #define GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS (0x04) // lpModuleName是模块中的一个地址 typedef BOOL (WINAPI* GetModuleHandleExA_T)( DWORD dwFlags, LPCSTR lpModuleName, HMODULE* phModule ); HMODULE getmodulename(char* buffer,int size,void* addri) { HMODULE hmodule; char FileName[MAX_PATH] = {0}; GetModuleHandleExA_T GetModuleHandleExA=(GetModuleHandleExA_T)GetProcAddress(GetModuleHandle("kernel32.dll"),"GetModuleHandleExA"); GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCSTR)addri, &hmodule); GetModuleFileNameA(hmodule, buffer, size); return hmodule; } char* gettimestring(char* buffer) { SYSTEMTIME systemtime; GetSystemTime( &systemtime); sprintf(buffer,"[%2.2d.%2.2d]",systemtime.wHour,systemtime.wMinute,systemtime.wSecond,systemtime.wMilliseconds); return buffer; } void log(const char*format,...) { va_list v; char buffer[300]; char tbuffer[100]; va_start(v,format); _vsnprintf(buffer,299,format,v); va_end(v); char fname[100]; sprintf(fname,"%d.txt",GetCurrentThreadId()); FILE* fd = fopen(fname,"a+b"); fprintf(fd," %s[%d.%d]%s ",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer); fclose(fd); //OutputDebugStringA(buffer); } void logthread(DWORD threadid,const char*format,...) { va_list v; char buffer[300]; char tbuffer[100]; va_start(v,format); _vsnprintf(buffer,299,format,v); va_end(v); char fname[100]; sprintf(fname,"%d.txt",threadid); FILE* fd = fopen(fname,"a+b"); fprintf(fd," %s[%d.%d]%s ",gettimestring(tbuffer),GetCurrentProcessId(),GetCurrentThreadId(),buffer); fclose(fd); //OutputDebugStringA(buffer); } void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId) ; typedef HANDLE (WINAPI * OPENTHREADFUN)(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwThreadId); DWORD WINAPI __printstack(void* p) { DWORD dwThreadId = (DWORD)p; DWORD error; //1:kernel32 大部分程序都自动加载了kernel32.dll 所以再获得句柄之前不需要Loadlibray HMODULE hKernel32 = ::GetModuleHandle("kernel32.dll"); //2获得函数指针 OPENTHREADFUN pFun = (OPENTHREADFUN)GetProcAddress(hKernel32,"OpenThread"); HANDLE hThread = pFun(THREAD_GET_CONTEXT,0,dwThreadId); if(hThread==0){ error = GetLastError(); ::MessageBox(0,"error1",0,0); return -1; } CONTEXT tagContext; tagContext.ContextFlags = CONTEXT_FULL; if(GetThreadContext(hThread,&tagContext)){ PrintCallStackFromContext(&tagContext,hThread,dwThreadId); }else{ error = GetLastError(); ::MessageBox(0,"error2",0,0); return -2; } return 0; } void PrintCurrentCallStack() { HANDLE hThread = CreateThread(0,0,__printstack,(void*)GetCurrentThreadId(),0,0); WaitForSingleObject(hThread,-1); } void PrintCallStackFromContext(const CONTEXT *pContext,HANDLE hThread,DWORD dwThreadId) { HANDLE hProcess = GetCurrentProcess(); CONTEXT c = *pContext; STACKFRAME64 sf; memset(&sf, 0, sizeof(STACKFRAME64)); DWORD dwImageType = IMAGE_FILE_MACHINE_I386; // 不同的CPU类型,具体信息可查询MSDN // #ifdef _M_IX86 sf.AddrPC.Offset = c.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Ebp; sf.AddrFrame.Mode = AddrModeFlat; #elif _M_X64 dwImageType = IMAGE_FILE_MACHINE_AMD64; sf.AddrPC.Offset = c.Rip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Rsp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Rsp; sf.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 dwImageType = IMAGE_FILE_MACHINE_IA64; sf.AddrPC.Offset = c.StIIP; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.IntSp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrBStore.Offset = c.RsBSP; sf.AddrBStore.Mode = AddrModeFlat; sf.AddrStack.Offset = c.IntSp; sf.AddrStack.Mode = AddrModeFlat; #else #error "Platform not supported!" #endif //HANDLE hThread = GetCurrentThread(); logthread(dwThreadId,"=====stackwalk64====="); while (true) { // 该函数是实现这个功能的最重要的一个函数 // 函数的用法以及参数和返回值的具体解释可以查询MSDN // if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, 0, 0, NULL)) { break; } if (sf.AddrFrame.Offset == 0) { break; } // 得到函数名 // DWORD retaddress = (DWORD)sf.AddrPC.Offset; char buffer[300]; HMODULE hmod = getmodulename(buffer,300,(void*)retaddress); logthread(dwThreadId,"retaddress=%s %x",buffer,retaddress-(DWORD)hmod); } logthread(dwThreadId,"=========="); }