利用DbgHelp获取线程的栈回溯信息

当线程发生异常时,我们如果可以记录下来异常线程的堆栈信息,那么对于我们后续问题处理将会有极大的帮助。这里记录一个操作方法。

  1 #include <iostream>
  2 #include <Windows.h>
  3 #include <process.h>
  4 #include <DbgHelp.h>
  5 
  6 #pragma comment(lib, "Dbghelp.lib")
  7 
  8 using std::cout;
  9 using std::endl;
 10 
 11 HANDLE g_hThread = INVALID_HANDLE_VALUE;
 12 
 13 void StackTrack()
 14 {
 15     HANDLE hCurProcess = GetCurrentProcess();
 16     if(FALSE == SymInitialize(hCurProcess, NULL, TRUE))
 17     {
 18         cout << "SymInitialize fail. LastError: 0x" << std::hex << GetLastError();
 19         return;
 20     }
 21 
 22     if (0xFFFFFFFF == SuspendThread(g_hThread))
 23     {
 24         cout << "SuspendThread fail. LastError: 0x" << std::hex << GetLastError();
 25         return;
 26     }
 27 
 28     CONTEXT context;
 29     context.ContextFlags = CONTEXT_FULL;
 30     if (FALSE == GetThreadContext(g_hThread, &context))
 31     {
 32         cout << "GetThreadContext fail. LastError: 0x" << std::hex << GetLastError();
 33         return;
 34     }
 35 
 36     DWORD machineType = IMAGE_FILE_MACHINE_I386;    // 机器Cpu类型
 37 
 38     STACKFRAME stackFrame = { 0 };
 39 #ifdef _M_IX86
 40     machineType = IMAGE_FILE_MACHINE_I386;
 41     stackFrame.AddrPC.Offset = context.Eip;
 42     stackFrame.AddrPC.Mode = AddrModeFlat;
 43     stackFrame.AddrStack.Offset = context.Esp;
 44     stackFrame.AddrStack.Mode = AddrModeFlat;
 45     stackFrame.AddrFrame.Offset = context.Ebp;
 46     stackFrame.AddrFrame.Mode = AddrModeFlat;
 47 #elif _M_X64
 48     machineType = IMAGE_FILE_MACHINE_AMD64;
 49     stackFrame.AddrPC.Offset = context->Rip;
 50     stackFrame.AddrPC.Mode = AddrModeFlat;
 51     stackFrame.AddrStack.Offset = context->Rsp;
 52     stackFrame.AddrStack.Mode = AddrModeFlat;
 53     stackFrame.AddrFrame.Offset = context->Rsp;
 54     stackFrame.AddrFrame.Mode = AddrModeFlat;
 55 #elif _M_IA64
 56     machineType = IMAGE_FILE_MACHINE_IA64;
 57     stackFrame.AddrPC.Offset = context->StIIP;
 58     stackFrame.AddrPC.Mode = AddrModeFlat;
 59     stackFrame.AddrStack.Offset = context->IntSp;
 60     stackFrame.AddrStack.Mode = AddrModeFlat;
 61     stackFrame.AddrFrame.Offset = context->IntSp;
 62     stackFrame.AddrFrame.Mode = AddrModeFlat;
 63     stackFrame.AddrBStore.Offset = context->RsBSP;
 64     stackFrame.AddrBStore.Mode = AddrModeFlat;
 65 #else
 66 #error "platform not supported!"
 67 #endif
 68 
 69     typedef struct tag_SYMBOL_INFO
 70     {
 71         IMAGEHLP_SYMBOL symInfo;
 72         TCHAR szBuffer[MAX_PATH];
 73     } SYMBOL_INFO, * LPSYMBOL_INFO;
 74 
 75     decltype(stackFrame.AddrPC.Offset) dwDisplament = 0;
 76     DWORD dwDis32 = 0;
 77     SYMBOL_INFO stack_info = { 0 };
 78     PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&stack_info;
 79     pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
 80     pSym->MaxNameLength = sizeof(SYMBOL_INFO) - offsetof(SYMBOL_INFO, symInfo.Name);
 81     IMAGEHLP_LINE ImageLine = { 0 };
 82     ImageLine.SizeOfStruct = sizeof(IMAGEHLP_LINE);
 83 
 84     while (TRUE == StackWalk(
 85         machineType,
 86         hCurProcess,
 87         g_hThread,
 88         &stackFrame,
 89         &context,
 90         NULL,
 91         SymFunctionTableAccess,
 92         SymGetModuleBase,
 93         NULL)
 94         )
 95     {
 96         if (FALSE == SymGetSymFromAddr(hCurProcess, stackFrame.AddrPC.Offset, &dwDisplament, pSym))
 97         {
 98             cout << "SymGetSymFromAddr fail. LastError: 0x" << std::hex << GetLastError();
 99             //continue;
100         }
101         if (FALSE == SymGetLineFromAddr(hCurProcess, stackFrame.AddrPC.Offset, &dwDis32, &ImageLine))
102         {
103             cout << "SymGetLineFromAddr fail. LastError: 0x" << std::hex << GetLastError();
104             //continue;
105         }
106 
107         printf("当前调用函数 :(FILE[%s]LINE[%d]) %08x + %s \n",
108             ImageLine.FileName, ImageLine.LineNumber, pSym->Address, pSym->Name);
109     }
110 
111     if (0xFFFFFFFF == ResumeThread(g_hThread))
112     {
113         cout << "ResumeThread fail. LastError: 0x" << std::hex << GetLastError();
114         return;
115     }
116 
117     if (FALSE == SymCleanup(hCurProcess))
118     {
119         cout << "SymCleanup fail. LastError: 0x" << std::hex << GetLastError();
120     }
121 
122     return;
123 }
124 
125 
126 void func1()
127 {
128     Sleep(10 * 1000);
129 }
130 
131 void func2()
132 {
133     func1();
134 }
135 
136 void func3()
137 {
138     func2();
139 }
140 
141 unsigned _stdcall ThreadTestStack(void* lpArgList)
142 {
143     func3();
144     return 0;
145 }
146 
147 int main(int argc, char* argv[])
148 {
149     unsigned uThreadID = 0;
150     g_hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadTestStack, NULL, 0, &uThreadID);
151     if (INVALID_HANDLE_VALUE == g_hThread)
152     {
153         cout << "_beginthreadex fail." << endl;
154         return 0;
155     }
156 
157     Sleep(1 * 1000);
158 
159     StackTrack();
160 
161     return 0;
162 }

 

posted on 2022-09-25 16:40  Arthurian  阅读(108)  评论(0编辑  收藏  举报