Клиент командной строки для разрешения трассировки стека win64 (с доступом к серверу символов) - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть трассировка стека gazillion 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, поэтому любой указатель в правильном направлении был бы очень признателен.

Ответы [ 2 ]

2 голосов
/ 10 февраля 2020

Если у вас есть правильный pdb для вашего MyApplication.exe

, вы можете использовать dbh.exe, который поставляется с пакетом windbg * Код 1003 *

:\>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

:\>

, приведенный ниже, должен вести себя подобно комментарию Джеспера Джуля о 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();
0 голосов
/ 21 февраля 2020

Попробуйте что-то вроде этого:

ln MyApplication + 0n1093618 

Обратите внимание, что для десятичных (не шестнадцатеричных) значений используйте 0n, а затем число. Если у вас есть символы, эта команда даст вам функцию и номер строки исходного кода.

Если это управляемый код, он не будет работать. Вместо этого вы должны использовать SOS:

!ip2md MyApplication + 0n1093618 
...