用于解析 win64 堆栈跟踪的命令行客户端(可以访问符号服务器)
Command line client to resolve win64 stack trace (with access to a symbol server)
我有大量 windows 堆栈跟踪,格式如下(在文本文件中):
MyApplication 0x00000000678d0000 + 1093618
MyApplication 0x00000000678d0000 + 106e1fd
MyApplication 0x00000000678d0000 + 1089314
MyApplication 0x00000000678d0000 + 149554e
MyApplication 0x00000000678d0000 + 3a5e57
MyApplication 0x00000000678d0000 + 1cec589
MyApplication 0x00000000678d0000 + 149fd17
MyApplication 0x00000000678d0000 + c7e557
KERNEL32 0x00000000152e0000 + 17bd4
ntdll 0x00000000153e0000 + 6ced1
而且我还设置了一个带有(压缩的)符号信息的符号服务器。
有没有办法让一些脚本(可能利用 windbg 的一些命令行命令?)将地址转换为源代码行?我从未在 Visual Studio 之外使用过堆栈跟踪,因此非常感谢任何指向正确方向的指针。
假设您的 MyApplication.exe
有正确的 pdb
可以使用windbg包自带的dbh.exe
:\>dbh dumpfuncs.exe laddr 1001000
file : c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp
line : 5
addr : 1001000
key : 00000000
disp : 0
:\>tail -n+5 dumpfuncs.cpp |head -1
__declspec ( noinline ) LPSTR CmdLn(void) {
:\>dbh dumpfuncs.exe m 1001000
index address name
148 1001000 : CmdLn
:\>
下面的代码应该类似于 Jesper Juhl 关于 addr2line 的评论
#include <windows.h>
#include <dbghelp.h>
#include <stdio.h>
#include <fstream>
#include <string>
#pragma comment(lib,"dbghelp.lib")
int main(int argc,char* argv[]){
if( argc != 3) {
printf("usage %s \"Module/Path\" \"Offset as hex 0x1010\"\n",argv[0]);
return FALSE;
}
DWORD64 offset = _strtoui64(argv[2], NULL, 16);
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS |SYMOPT_LOAD_LINES);
HANDLE hProcess = GetCurrentProcess();
if (!SymInitialize(hProcess, NULL, FALSE)) {
printf("SymInitialize returned error : %u\n", GetLastError());
return FALSE;
}
DWORD64 ModBase = SymLoadModuleEx (hProcess,NULL, argv[1], NULL,0,0,NULL,0);
if( (ModBase == 0) && (GetLastError() != ERROR_SUCCESS) ) {
printf("SymLoadModuleEx returned error : %u\n", GetLastError());
return FALSE;
}
DWORD64 SymAddr = ModBase + offset;
printf("Module %s Loaded At 0x%I64x SymAddr = 0x%I64x\n",argv[1],ModBase ,SymAddr);
IMAGEHLP_LINE64 line ={0};
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD dwDisplacement =0;
if(!SymGetLineFromAddr64(hProcess, SymAddr, &dwDisplacement, &line)){
printf("SymGetLineFromAddr64 returned error : %u\n", GetLastError());
return FALSE;
}
printf("Source= %s # %u @ %I64x\n",line.FileName,line.LineNumber,line.Address);
std::ifstream fs;
fs.open(line.FileName);
if(fs.is_open()){
std::string buff;
unsigned int lineno = 0;
while (lineno != line.LineNumber && getline(fs, buff)){
++lineno;
}
printf("%s\n",buff.c_str());
fs.close();
}else{
printf("cannot open %s\n",line.FileName);
}
}
编译并执行
:\>bld.bat AddrToLineWin
:\>cl /Zi /W4 /analyze /EHsc /nologo /Od AddrToLineWin.cpp /link /nologo /release
AddrToLineWin.cpp
:\>AddrToLineWin.exe ..\dumpfuncs\dumpfuncs.exe 0x1010
Module ..\dumpfuncs\dumpfuncs.exe Loaded At 0x400000 SymAddr = 0x401010
Source= c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp # 8 @ 401010
__declspec ( noinline ) LPSTR FileName (void) {
:\>AddrToLineWin.exe ..\dumpfuncs\dumpfuncs.exe 0x1008
Module ..\dumpfuncs\dumpfuncs.exe Loaded At 0x400000 SymAddr = 0x401008
Source= c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp # 6 @ 401003
return GetCommandLineA();
尝试这样的事情:
ln MyApplication + 0n1093618
请注意,对于十进制(非十六进制)值,请使用 0n 后跟数字。
如果您有符号,此命令将为您提供函数和源代码行号。
如果它是托管代码,它将无法工作。
您必须改用 SOS:
!ip2md MyApplication + 0n1093618
我有大量 windows 堆栈跟踪,格式如下(在文本文件中):
MyApplication 0x00000000678d0000 + 1093618
MyApplication 0x00000000678d0000 + 106e1fd
MyApplication 0x00000000678d0000 + 1089314
MyApplication 0x00000000678d0000 + 149554e
MyApplication 0x00000000678d0000 + 3a5e57
MyApplication 0x00000000678d0000 + 1cec589
MyApplication 0x00000000678d0000 + 149fd17
MyApplication 0x00000000678d0000 + c7e557
KERNEL32 0x00000000152e0000 + 17bd4
ntdll 0x00000000153e0000 + 6ced1
而且我还设置了一个带有(压缩的)符号信息的符号服务器。
有没有办法让一些脚本(可能利用 windbg 的一些命令行命令?)将地址转换为源代码行?我从未在 Visual Studio 之外使用过堆栈跟踪,因此非常感谢任何指向正确方向的指针。
假设您的 MyApplication.exe
有正确的 pdb可以使用windbg包自带的dbh.exe
:\>dbh dumpfuncs.exe laddr 1001000
file : c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp
line : 5
addr : 1001000
key : 00000000
disp : 0
:\>tail -n+5 dumpfuncs.cpp |head -1
__declspec ( noinline ) LPSTR CmdLn(void) {
:\>dbh dumpfuncs.exe m 1001000
index address name
148 1001000 : CmdLn
:\>
下面的代码应该类似于 Jesper Juhl 关于 addr2line 的评论
#include <windows.h>
#include <dbghelp.h>
#include <stdio.h>
#include <fstream>
#include <string>
#pragma comment(lib,"dbghelp.lib")
int main(int argc,char* argv[]){
if( argc != 3) {
printf("usage %s \"Module/Path\" \"Offset as hex 0x1010\"\n",argv[0]);
return FALSE;
}
DWORD64 offset = _strtoui64(argv[2], NULL, 16);
SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS |SYMOPT_LOAD_LINES);
HANDLE hProcess = GetCurrentProcess();
if (!SymInitialize(hProcess, NULL, FALSE)) {
printf("SymInitialize returned error : %u\n", GetLastError());
return FALSE;
}
DWORD64 ModBase = SymLoadModuleEx (hProcess,NULL, argv[1], NULL,0,0,NULL,0);
if( (ModBase == 0) && (GetLastError() != ERROR_SUCCESS) ) {
printf("SymLoadModuleEx returned error : %u\n", GetLastError());
return FALSE;
}
DWORD64 SymAddr = ModBase + offset;
printf("Module %s Loaded At 0x%I64x SymAddr = 0x%I64x\n",argv[1],ModBase ,SymAddr);
IMAGEHLP_LINE64 line ={0};
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD dwDisplacement =0;
if(!SymGetLineFromAddr64(hProcess, SymAddr, &dwDisplacement, &line)){
printf("SymGetLineFromAddr64 returned error : %u\n", GetLastError());
return FALSE;
}
printf("Source= %s # %u @ %I64x\n",line.FileName,line.LineNumber,line.Address);
std::ifstream fs;
fs.open(line.FileName);
if(fs.is_open()){
std::string buff;
unsigned int lineno = 0;
while (lineno != line.LineNumber && getline(fs, buff)){
++lineno;
}
printf("%s\n",buff.c_str());
fs.close();
}else{
printf("cannot open %s\n",line.FileName);
}
}
编译并执行
:\>bld.bat AddrToLineWin
:\>cl /Zi /W4 /analyze /EHsc /nologo /Od AddrToLineWin.cpp /link /nologo /release
AddrToLineWin.cpp
:\>AddrToLineWin.exe ..\dumpfuncs\dumpfuncs.exe 0x1010
Module ..\dumpfuncs\dumpfuncs.exe Loaded At 0x400000 SymAddr = 0x401010
Source= c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp # 8 @ 401010
__declspec ( noinline ) LPSTR FileName (void) {
:\>AddrToLineWin.exe ..\dumpfuncs\dumpfuncs.exe 0x1008
Module ..\dumpfuncs\dumpfuncs.exe Loaded At 0x400000 SymAddr = 0x401008
Source= c:\users\xx\source\repos\dumpfuncs\dumpfuncs.cpp # 6 @ 401003
return GetCommandLineA();
尝试这样的事情:
ln MyApplication + 0n1093618
请注意,对于十进制(非十六进制)值,请使用 0n 后跟数字。 如果您有符号,此命令将为您提供函数和源代码行号。
如果它是托管代码,它将无法工作。 您必须改用 SOS:
!ip2md MyApplication + 0n1093618