gpt4 book ai didi

c++ - SymEnumSymbols 返回 ERROR_SUCCESS 但没有给出任何结果

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:50:47 28 4
gpt4 key购买 nike

我正在尝试从已加载的 DLL 中枚举符号。对于那些感兴趣的人,这是 CPPCoverage project 的一部分,对于某些功能,我需要符号数据。

问题分解

当启动进程或加载DLL时,需要为一些已规划的新功能枚举符号。

基本上就是创建一个进程,使用dbghelp获取符号信息。接下来,使用 SymEnumSymbols 迭代符号。有两个时刻会发生这种情况:

  1. 进程启动时(CREATE_PROCESS_DEBUG_EVENT)
  2. 加载 DLL 时(LOAD_DLL_DEBUG_EVENT)

在 (2) 期间一切正常。但是,在(1)期间不能枚举符号。

行为是一切正常,直到 SymEnumSymbols 调用。返回值告诉我有错误,但 GetLastError 返回 SUCCESS。此外,不会调用回调函数。

更奇怪的是,对 SymGetSymFromName 的调用 确实 确实有效。

最小测试用例

static BOOL CALLBACK EnumerateSymbols(
PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
{
std::cout << "Symbol: " << pSymInfo->Name << std::endl;
return TRUE;
}

void Test()
{
SymSetOptions(SYMOPT_LOAD_ANYTHING);

STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

auto str = "FullPathToSomeExeWithPDB.exe";
auto result = CreateProcess(str, NULL, NULL, NULL, FALSE,
DEBUG_PROCESS, NULL, NULL, &si, &pi);
if (result == 0)
{
auto err = GetLastError();
std::cout << "Error running process: " << err << std::endl;
return;
}

if (!SymInitialize(pi.hProcess, NULL, FALSE))
{
auto err = GetLastError();
std::cout << "Symbol initialization failed: " << err << std::endl;
return;
}

bool first = false;
DEBUG_EVENT debugEvent = { 0 };
while (!first)
{
if (!WaitForDebugEvent(&debugEvent, INFINITE))
{
auto err = GetLastError();
std::cout << "Wait for debug event failed: " << err << std::endl;
return;
}
if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
{
auto dllBase = SymLoadModuleEx(
pi.hProcess,
debugEvent.u.CreateProcessInfo.hFile,
str,
NULL,
reinterpret_cast<DWORD64>(debugEvent.u.CreateProcessInfo.lpBaseOfImage),
0,
NULL,
0);

if (!dllBase)
{
auto err = GetLastError();
std::cout << "Loading the module failed: " << err << std::endl;
return;
}

if (!SymEnumSymbols(pi.hProcess, dllBase, NULL, EnumerateSymbols, nullptr))
{
auto err = GetLastError();
std::cout << "Error: " << err << std::endl;
}

first = true;
}
}
// cleanup code is omitted
}

最佳答案

Brr,真是个笨蛋。我在 VS2017 中得到了一个重现,使用从 Win32 控制台项目模板构建的简单目标可执行文件。我尝试过的任何事情都无法说服 SymEnumSymbols() 枚举任何符号。接下来我扩展了代码,还捕获了 LOAD_DLL_DEBUG_EVENT 通知:

if (debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT) {
auto base = SymLoadModule64(pi.hProcess, debugEvent.u.LoadDll.hFile, NULL, NULL, NULL, 0);
if (!base) {
auto err = GetLastError();
std::cout << err << std::endl;
}
else {
CloseHandle(debugEvent.u.LoadDll.hFile);
SymEnumSymbols(pi.hProcess, base, NULL, EnumerateSymbols, nullptr);
}
}

除了在 SymInitialize() 中正确设置符号搜索路径外,它工作得很好,并在 ntdll.dll 等中正确列出了符号。

结论:PDB文件有问题

得到了返回。从 VS2015 开始,微软一直在修补 PDB 文件生成。他们添加了 /DEBUG:FASTLINK option .请注意,链接文档具有误导性,它也是 VS2015 中的默认设置。操作系统的 DbgHelp.dll 版本无法正确枚举生成的 PDB 文件。 GetLastError() 代码非常具有误导性,我在上面花费了太多时间,我认为它仅仅表示“我没有成功枚举任何东西”。请注意如何为其他 DbgHelp api 函数(如 SymSetContext 和 SymLoadModuleEx)记录此代码。

在 VS2015 中使用 Project > Properties > Linker > Debug > Generate Debug Info = "Optimize for debugging (/DEBUG)"。

在 VS2017 中使用 Project > Properties > Linker > Debug > Generate Debug Info = "Generate Debug Information optimized for sharing and publishing (/DEBUG:FULL)".

强调这些设置对目标项目很重要,而不是调试器项目。理想情况下,应该有一个 DbgHelp.dll 版本也可以从 PDB 的快速链接版本读取调试信息。我找不到一个,SDK 8.1 和 SDK 10 附带的那些都没有解决问题。 DevDiv 和 Windows 组无法协同工作的又一案例。

关于c++ - SymEnumSymbols 返回 ERROR_SUCCESS 但没有给出任何结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44842328/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com