how to use SymGetSourceFile api for fetching source file in postmortem debugging

0

I want to use SymGetSourceFile to get a source file from source server using info from a dump file. But the first param is a handle to process but during postmortem we dont have a process, so is it meant to be used only for live debugging tools? How can I use it from a postmortem debugging tool?

BOOL IMAGEAPI SymGetSourceFile(
  HANDLE  hProcess,
  ULONG64 Base,
  PCSTR   Params,
  PCSTR   FileSpec,
  PSTR    FilePath,
  DWORD   Size
);

https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-symgetsourcefile

Update: I have tried using IDebugAdvanced3 interface for same but get HR = 0x80004002 for GetSourceFileInformation call.

char buf[1000] = { 0 };
    HRESULT hr = g_ExtAdvanced->GetSourceFileInformation(DEBUG_SRCFILE_SYMBOL_TOKEN,
        "Application.cs",
        0x000000dd6f5f1000, 0, buf, 1000, 0);
    if (SUCCEEDED(hr))
    {
        dprintf("GetSourceFileInformation = %s", buf);
        char buftok[5000] = { 0 };
        hr = g_ExtAdvanced->FindSourceFileAndToken(0, 0x000000dd6f5f1000,
            "Application.cs", DEBUG_FIND_SOURCE_TOKEN_LOOKUP,
            buf, 1000, 0, buftok, 5000, 0);
        if (SUCCEEDED(hr))
        {
            dprintf("FindSourceFileAndToken = %s", buf);
        }
        else
            dprintf("FindSourceFileAndToken HR = %x", hr);
    }
    else
        dprintf("GetSourceFileInformation HR = %x", hr);

I have dump that has this module and pdb loaded. and pass an address within the module - 0x000000dd6f5f1000, to GetSourceFileInformation

windows
debugging
windbg
dump
source-server
asked on Stack Overflow Mar 16, 2021 by devstability • edited Mar 18, 2021 by devstability

1 Answer

0

this was a comment but grew up so addingas answer

GetSourceFileINformation iirc checks the source servers those that start with srv or %srcsrv%
this returns a token for use with findsourcefileandtoken

if you have a known offset (0x1070 == main() in case below )
use GetLineByOffset this has the added advantage of reloading all the modules

hope you have your private pdb for the dump file you open.

this is engext syntax

    Hr = m_Client->OpenDumpFile("criloc.dmp");
    Hr = m_Control->WaitForEvent(0,INFINITE);
    unsigned char Buff[BUFFERSIZE] = {0};
    ULONG Buffused = 0;
    DEBUG_READ_USER_MINIDUMP_STREAM MiniStream ={ModuleListStream,0,0,Buff,BUFFERSIZE,Buffused};    
    Hr = m_Advanced2->Request(DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM,&MiniStream,sizeof(  
    DEBUG_READ_USER_MINIDUMP_STREAM),NULL,NULL,NULL);
    MINIDUMP_MODULE_LIST *modlist = (MINIDUMP_MODULE_LIST *)&Buff;
    Hr = m_Symbols->GetLineByOffset(modlist->Modules[0].BaseOfImage+0x1070,&Line,  
    FileBuffer,0x300,&Filesize,&Displacement);
    Out("getlinebyoff returned %x\nsourcefile is at %s line number is %d\n",Hr,FileBuffer,Line);

this is part src adapt it to your needs.

the result of the extension command is pasted below

0:000> .load .\mydt.dll
0:000> !mydt    
Loading Dump File [C:\Users\xxxx\Desktop\srcfile\criloc.dmp]
User Mini Dump File with Full Memory: Only application data is available

OpenDumpFile Returned 0    
WaitForEvent Returned 0    
Request Returned 0    
Ministream Buffer Used 28c

06 00 00 00 00 00 8d 00 00 00 00 00 00 e0 04 00
f0 9a 05 00 2d 2e a8 5f ba 14 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
43 00 00 00 4a 38 00 00 00 00 00 00 00 00 00 00
40 81 00 00 00 00 00 00 00 00 00 00 00 00 00 00

No of Modules =6
Module[0]
Base = 8d0000
Size = 4e000

getlinebyoff returned 0

sourcefile is at c:\users\xxx\desktop\misc\criloc\criloc.cpp line number is 21 <<<<<<<<<

||1:1:010> lm
start    end        module name
008d0000 0091e000   CRILOC     (private pdb symbols)  C:\Users\xxxx\Desktop\misc\CRILOC\CRILOC.pdb
||1:1:010>

and the actual source file contents on path

:\>grep -i -n main CRILOC.CPP
20:int main(void)  << the curly braces is on line 21

UPDATE:

yes if the src file is not source indexed (cvs,perforce,... ) GetSourceFileInformation () will not return a token
it checks for a token using the Which parameter
and the returned info can be used in FindSourceFileAndToken();

if your source is not source indexed and you only have a source path
use FindSourceFileandToken() with DEBUG_FIND_SOURCE_FULL_PATH Flag

be aware you need to either use SetSourcePath() or issue .srcpath command or use _NT_SOURCE_PATH environment variable or use -srcpath commandline switch prior to invoking FindSourceFileAndToken()

see below for a walkthrough

sourcefile and contents

:\>ls *.cpp
mydt.cpp

:\>cat mydt.cpp
#include <engextcpp.cpp>
#define BSIZE 0x1000
class EXT_CLASS : public ExtExtension {
public:
    EXT_COMMAND_METHOD(mydt);
};
EXT_DECLARE_GLOBALS();
EXT_COMMAND( mydt, "mydt", "{;e,o,d=0;!mydt;}" ){
    HRESULT Hr = m_Client->OpenDumpFile("criloc.dmp");
    Hr = m_Control->WaitForEvent(0,INFINITE);
    char Buff[BSIZE] = {0};
    ULONG Buffused = 0;
    DEBUG_READ_USER_MINIDUMP_STREAM MiniStream ={ModuleListStream,0,0,
        Buff,BSIZE,Buffused};
    Hr = m_Advanced2->Request(DEBUG_REQUEST_READ_USER_MINIDUMP_STREAM,&MiniStream,
    sizeof(DEBUG_READ_USER_MINIDUMP_STREAM),NULL,NULL,NULL);
    MINIDUMP_MODULE_LIST *modlist = (MINIDUMP_MODULE_LIST *)&Buff;
    //m_Symbols->SetSourcePath("C:\\Users\\xxx\\Desktop\\misc\\CRILOC");
    char srcfilename[BSIZE] ={0};
    ULONG foundsize =0 ;
    Hr = m_Advanced3->FindSourceFileAndToken(0,modlist->Modules[0].BaseOfImage,"criloc.cpp",
    DEBUG_FIND_SOURCE_FULL_PATH,NULL,0,NULL,srcfilename,0x300,&foundsize);
    Out("gsfi returned %x\n" , Hr);
    Out("srcfilename is %s\n",srcfilename);
}

compiled and linked with

:\>cat bld.bat
@echo off
set "INCLUDE= %INCLUDE%;E:\windjs\windbg_18362\inc"
set "LIB=%LIB%;E:\windjs\windbg_18362\lib\x86"
set "LINKLIBS=user32.lib kernel32.lib dbgeng.lib dbghelp.lib"

cl /LD /nologo /W4 /Od  /Zi /EHsc mydt.cpp /link /nologo /EXPORT:DebugExtensionInitialize /Export:mydt /Export:help /RELEASE %linklibs%
:\>bld.bat
mydt.cpp
E:\windjs\windbg_18362\inc\engextcpp.cpp(1849): warning C4245: 'argument': conversion from 'int' to 'ULONG64', signed/unsigned mismatch
   Creating library mydt.lib and object mydt.exp

:\>file mydt.dll
mydt.dll; PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit

executing

:\>cdb cdb

Microsoft (R) Windows Debugger Version 10.0.18362.1 X86
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ntdll!LdrpDoDebuggerBreak+0x2c:
77d805a6 cc              int     3
0:000> .load .\mydt.dll
0:000> .chain

Extension DLL chain:
    .\mydt.dll: API 1.0.0, built Thu Mar 18 20:40:04 2021
        [path: C:\Users\xxxx\Desktop\srcfile\New folder\mydt.dll]

0:000> !mydt

Loading Dump File [C:\Users\xxxx\Desktop\srcfile\New folder\criloc.dmp]
User Mini Dump File with Full Memory: Only application data is available

gsfi returned 80004002
srcfilename is
||1:1:010> .srcpath "c:\\users\\xxxx\\desktop\\misc\\criloc\\"
Source search path is: c:\\users\\xxxx\\desktop\\misc\\criloc\\

************* Path validation summary **************
Response                         Time (ms)     Location
OK                                             c:\\users\\xxxx\\desktop\\misc\\criloc\\
||1:1:010> !mydt

Loading Dump File [C:\Users\xxxx\Desktop\srcfile\New folder\criloc.dmp]

gsfi returned 0
srcfilename is c:\\users\\xxxx\\desktop\\misc\\criloc\\criloc.cpp
||2:2:021>
answered on Stack Overflow Mar 18, 2021 by blabb • edited Mar 18, 2021 by blabb

User contributions licensed under CC BY-SA 3.0