-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTzdStackTrace.cpp
More file actions
143 lines (123 loc) · 5.4 KB
/
Copy pathTzdStackTrace.cpp
File metadata and controls
143 lines (123 loc) · 5.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include "Res/TzdStrings.h"
#include "TzdStackTrace.h"
#include <algorithm>
void TzdStackTrace::dumpProcessStack(DWORD processId) {
std::printf(TzdStk::ANALYZING, processId); std::cout << std::endl;
// 1. 获取进程句柄
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
if (!hProcess) {
std::cout << TzdStk::OPEN_FAILED << std::endl;
return;
}
// 2. 初始化符号表
SymInitialize(hProcess, NULL, TRUE);
// 3. 遍历线程
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) {
THREADENTRY32 te32;
te32.dwSize = sizeof(THREADENTRY32);
if (Thread32First(hThreadSnap, &te32)) {
do {
if (te32.th32OwnerProcessID == processId) {
std::printf(TzdStk::THREAD_LABEL, te32.th32ThreadID); std::cout << std::endl;
dumpThreadStack(hProcess, te32.th32ThreadID);
}
} while (Thread32Next(hThreadSnap, &te32));
}
CloseHandle(hThreadSnap);
}
SymCleanup(hProcess);
CloseHandle(hProcess);
}
DWORD TzdStackTrace::getPidByName(const std::string& processName) {
DWORD pid = 0;
// 获取系统进程快照
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot != INVALID_HANDLE_VALUE) {
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnapshot, &pe32)) {
do {
// 转换当前的 pe32.szExeFile 为 std::string 方便比较
// 兼容 Unicode 和 Multi-Byte
#ifdef UNICODE
char mbs[MAX_PATH];
size_t convertedChars = 0;
wcstombs_s(&convertedChars, mbs, MAX_PATH, pe32.szExeFile, _TRUNCATE);
std::string currentProcessName = mbs;
#else
std::string currentProcessName = pe32.szExeFile;
#endif
// 转为小写进行不区分大小写匹配
std::string searchName = processName;
std::transform(searchName.begin(), searchName.end(), searchName.begin(), ::tolower);
std::transform(currentProcessName.begin(), currentProcessName.end(), currentProcessName.begin(), ::tolower);
if (currentProcessName == searchName) {
pid = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnapshot, &pe32));
}
CloseHandle(hSnapshot);
}
return pid;
}
void TzdStackTrace::dumpThreadStack(HANDLE hProcess, DWORD threadId) {
HANDLE hThread = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME, FALSE, threadId);
if (!hThread) return;
// 必须挂起线程才能获取稳定的上下文
SuspendThread(hThread);
CONTEXT context;
memset(&context, 0, sizeof(CONTEXT));
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(hThread, &context)) {
STACKFRAME64 stackFrame;
memset(&stackFrame, 0, sizeof(STACKFRAME64));
DWORD machineType;
#ifdef _M_IX86
machineType = IMAGE_FILE_MACHINE_I386;
stackFrame.AddrPC.Offset = context.Eip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context.Ebp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context.Esp;
stackFrame.AddrStack.Mode = AddrModeFlat;
#else
machineType = IMAGE_FILE_MACHINE_AMD64;
stackFrame.AddrPC.Offset = context.Rip;
stackFrame.AddrPC.Mode = AddrModeFlat;
stackFrame.AddrFrame.Offset = context.Rbp;
stackFrame.AddrFrame.Mode = AddrModeFlat;
stackFrame.AddrStack.Offset = context.Rsp;
stackFrame.AddrStack.Mode = AddrModeFlat;
#endif
while (StackWalk64(machineType, hProcess, hThread, &stackFrame, &context, NULL,
SymFunctionTableAccess64, SymGetModuleBase64, NULL)) {
if (stackFrame.AddrPC.Offset == 0) break;
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
pSymbol->MaxNameLen = MAX_SYM_NAME;
DWORD64 displacement = 0; // 这里的 displacement 就是偏移量
if (SymFromAddr(hProcess, stackFrame.AddrPC.Offset, &displacement, pSymbol)) {
// 关键修改点:输出函数名 + 0x16进制偏移
std::printf(TzdStk::SYMBOL_FMT, (unsigned long long)stackFrame.AddrPC.Offset, pSymbol->Name, (unsigned long long)displacement); std::cout << std::endl;
}
else {
// 如果找不到符号,至少尝试获取模块名
IMAGEHLP_MODULE64 moduleInfo;
moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64);
if (SymGetModuleInfo64(hProcess, stackFrame.AddrPC.Offset, &moduleInfo)) {
// 计算相对于模块基址的偏移
DWORD64 modOffset = stackFrame.AddrPC.Offset - moduleInfo.BaseOfImage;
std::printf(TzdStk::MODULE_FMT, (unsigned long long)stackFrame.AddrPC.Offset, moduleInfo.ModuleName, (unsigned long long)modOffset); std::cout << std::endl;
}
else {
std::printf(TzdStk::UNKNOWN_FMT, (unsigned long long)stackFrame.AddrPC.Offset); std::cout << std::endl;
}
}
}
}
ResumeThread(hThread);
CloseHandle(hThread);
}