Ich versuche, Symbole aus einer DLL aufzulisten, die ich geladen habe. Für Interessierte ist dies ein Teil der CPPCoverage project, und für einige Funktionen brauche ich Symboldaten.SymEnumSymbols gibt ERROR_SUCCESS zurück, gibt aber keine Ergebnisse.
Aufteilung des Problems
Wenn der Prozess gestartet wird oder eine DLL geladen wird, müssen Symbole für einige der neuen Funktionen aufgezählt werden, die geplant wurde.
Grundsätzlich wird ein Prozess erstellt und dbghelp
wird verwendet, um Symbolinformationen zu erhalten. Als nächstes werden Symbole unter Verwendung von SymEnumSymbols
iteriert. Es gibt zwei Momente, in denen dies geschieht:
- Wenn der Prozess gestartet wird (
CREATE_PROCESS_DEBUG_EVENT
) - Wenn eine DLL geladen wird (
LOAD_DLL_DEBUG_EVENT
)
Alles funktioniert gut bei (2). Symbole können jedoch während (1) nicht aufgezählt werden.
Verhalten ist, dass alles gut funktioniert, bis der SymEnumSymbols
Anruf. Der Rückgabewert sagt mir, dass es einen Fehler gibt, aber GetLastError
gibt SUCCESS zurück. Außerdem wird die Callback-Funktion nicht aufgerufen.
Um es noch komischer zu machen, funktioniert ein Anruf SymGetSymFromName
funktioniert tatsächlich.
Minimal Testfall
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
}
Ok. Sie ** rufen 'GetLastError' zu spät auf. Sie müssen es ** sofort ** nennen, nachdem die Bedingung erfüllt wurde, wo dokumentiert wird, dass sinnvolle Werte zurückgegeben werden. Durchstreichen Sie es nicht mit ** anderem ** anderem Code. – IInspectable
@Intensible Testfälle ... normalerweise würde ich nur eine Ausnahme werfen. Wie auch immer, ich habe es geändert, um es sofort anzurufen. Ändert nichts ... – atlaste
Ich nehme an, dass [CREATE_PROCESS_DEBUG_EVENT] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms679302.aspx) ausgelöst wird, bevor irgendwelche Module geladen wurden : * "Das System generiert dieses Debugging-Ereignis, bevor der Prozess im Benutzermodus ausgeführt wird" *. [Warum bekomme ich ERROR_INVALID_HANDLE von GetModuleFileNameEx, wenn ich weiß, dass das Prozesshandle gültig ist?] (Https://blogs.msdn.microsoft.com/oldnewthing/20150716-00/?p=45131) scheint relevant. – IInspectable