用于解决win64堆栈跟踪的命令行客户端(可以访问符号服务器)

问题描述 投票:0回答:1

我有以下格式的专用窗口堆栈跟踪(在文本文件中:]

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之外使用堆栈跟踪,因此,朝正确方向的任何指针将不胜感激。

c++ windbg stack-trace
1个回答
2
投票

假设您的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();
© www.soinside.com 2019 - 2024. All rights reserved.