windows - 如何使用 SymGetSourceFile api 在事后调试中获取源文件
问题描述
我想使用 SymGetSourceFile 使用转储文件中的信息从源服务器获取源文件。但是第一个参数是处理的句柄,但在事后我们没有进程,所以它是否意味着仅用于实时调试工具?如何从事后调试工具中使用它?
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
更新:我尝试使用 IDebugAdvanced3 接口,但获取 HR = 0x80004002 用于 GetSourceFileInformation 调用。
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);
我有已加载此模块和 pdb 的转储。并将模块内的地址 - 0x000000dd6f5f1000 传递给 GetSourceFileInformation
解决方案
这是一条评论,但长大了,所以添加了答案
GetSourceFileINformation iirc 检查以 srv 或 %srcsrv% 开头的源服务器,
这将返回与 findsourcefileandtoken 一起使用的令牌
如果你有一个已知的偏移量(0x1070 == main() 在下面的情况下)
使用 GetLineByOffset 这具有重新加载所有模块的额外优势
希望你有你打开的转储文件的私人 pdb。
这是 engext 语法
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);
这是部分 src 使其适应您的需求。
扩展命令的结果粘贴在下面
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>
和路径上的实际源文件内容
:\>grep -i -n main CRILOC.CPP
20:int main(void) << the curly braces is on line 21
更新:
是的,如果 src 文件不是源索引 (cvs,perforce,...) GetSourceFileInformation () 将不会返回令牌
,它使用 Who 参数检查令牌,
并且返回的信息可以在 FindSourceFileAndToken() 中使用;
如果您的源不是源索引并且您只有一个源路径,请
使用带有 DEBUG_FIND_SOURCE_FULL_PATH 标志的 FindSourceFileandToken()
请注意,在调用 FindSourceFileAndToken() 之前,您需要使用SetSourcePath()或发出.srcpath命令或使用_NT_SOURCE_PATH环境变量或使用-srcpath命令行开关
请参阅下面的演练
源文件和内容
:\>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);
}
编译并链接到
:\>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
执行
:\>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>
推荐阅读
- python - 在 Python 文档字符串中记录复杂的嵌套字典参数的最佳实践?
- python - 了解如何使用 tf.nn.conv2d 函数
- acumatica - Acumatica 未在 DAC 生成器中显示表格列
- node.js - 链接获取、获取、映射、过滤、获取、获取
- javascript - 使用 css 或 js 强制适合字体高度
- typescript - 有没有办法在 TypeScript 中实例化受约束的泛型类型的实例?
- javascript - 重构 JSON 数据
- sql-server - 从 SQL Server 2008 中删除 XML 节点
- c++ - 变量用作C中的函数参数后出错?
- python - 为什么我会收到此 DCPError?