Abrufen von Benachrichtigungen
Der folgende Code zeigt, wie Ausführliche status Informationen zum Suchen und Laden von Modulen und den entsprechenden Symboldateien vom Symbolhandler abgerufen und gemeldet werden.
Viele, die mit dem WinDbg-Debugger vertraut sind, erinnern sich möglicherweise an einen Befehl namens "!sym noisy". Dieser Befehl wird vom Benutzer verwendet, um zu bestimmen, warum WinDbg Symboldateien laden kann oder nicht. Es wird eine ausführliche Liste aller Versuche des Symbolhandlers angezeigt.
Die gleiche Auflistung ist auch für alle Benutzer verfügbar, die einen Client für den DbgHelp-Symbolhandler entwickeln.
Rufen Sie zunächst SymSetOptions mit SYMOPT_DEBUG auf. Dies bewirkt, dass DbgHelp Debugbenachrichtigungen aktiviert.
Nachdem Sie SymInitialize aufgerufen haben, verwenden Sie SymRegisterCallback64 , um eine Rückruffunktion zu registrieren, die DbgHelp aufruft, wenn ein interessantes Ereignis auftritt. In diesem Beispiel heißt die Rückruffunktion SymRegisterCallbackProc64. Symbolrückruffunktionen werden eine Reihe von Aktionscodes übergeben, die sie je nach Typ verarbeiten können. In diesem Beispiel behandeln wir nur den CBA_EVENT Aktionscode. Diese Funktion übergibt eine Zeichenfolge, die ausführliche Informationen zu einem Ereignis enthält, das beim Laden eines Symbols aufgetreten ist. Dieses Ereignis kann vom Versuch, die Daten in einem ausführbaren Bild zu lesen, bis zum erfolgreichen Speicherort einer Symboldatei sein. SymRegisterCallbackProc64 zeigt diese Zeichenfolge an und gibt TRUE zurück.
Wichtig
Stellen Sie sicher, dass Sie false für jeden Aktionscode zurückgeben, den Sie nicht verarbeiten. Andernfalls kann es zu undefiniertem Verhalten kommen. Eine Liste aller Aktionscodes und deren Auswirkungen finden Sie unter SymRegisterCallbackProc64 .
Nachdem der Rückruf registriert wurde, ist es an der Zeit, das in der Befehlszeile angegebene Modul durch Aufrufen von SymLoadModuleEx zu laden.
Rufen Sie schließlich SymCleanup auf, bevor Sie den Vorgang beenden.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#ifdef UNICODE
#define DBGHELP_TRANSLATE_TCHAR
#endif
#include <dbghelp.h>
// Here is an implementation of a Symbol Callback function.
BOOL
CALLBACK
SymRegisterCallbackProc64(
__in HANDLE hProcess,
__in ULONG ActionCode,
__in_opt ULONG64 CallbackData,
__in_opt ULONG64 UserContext
)
{
UNREFERENCED_PARAMETER(hProcess);
UNREFERENCED_PARAMETER(UserContext);
PIMAGEHLP_CBA_EVENT evt;
// If SYMOPT_DEBUG is set, then the symbol handler will pass
// verbose information on its attempt to load symbols.
// This information be delivered as text strings.
switch (ActionCode)
{
case CBA_EVENT:
evt = (PIMAGEHLP_CBA_EVENT)CallbackData;
_tprintf(_T("%s"), (PTSTR)evt->desc);
break;
// CBA_DEBUG_INFO is the old ActionCode for symbol spew.
// It still works, but we use CBA_EVENT in this example.
#if 0
case CBA_DEBUG_INFO:
_tprintf(_T("%s"), (PTSTR)CallbackData);
break;
#endif
default:
// Return false to any ActionCode we don't handle
// or we could generate some undesirable behavior.
return FALSE;
}
return TRUE;
}
// Main code.
int __cdecl
#ifdef UNICODE
_tmain(
#else
main(
#endif
__in int argc,
__in_ecount(argc) PCTSTR argv[]
)
{
BOOL status;
int rc = -1;
HANDLE hProcess;
DWORD64 module;
if (argc < 2)
{
_tprintf(_T("You must specify an executable image to load.\n"));
return rc;
}
// If we want to se debug spew, we need to set this option.
SymSetOptions(SYMOPT_DEBUG);
// We are not debugging an actual process, so lets use a placeholder
// value of 1 for hProcess just to ID these calls from any other
// series we may want to load. For this simple case, anything will do.
hProcess = (HANDLE)1;
// Initialize the symbol handler. No symbol path.
// Just let dbghelp use _NT_SYMBOL_PATH
status = SymInitialize(hProcess, NULL, false);
if (!status)
{
_tprintf(_T("Error 0x%x calling SymInitialize.\n"), GetLastError());
return rc;
}
// Now register our callback.
status = SymRegisterCallback64(hProcess, SymRegisterCallbackProc64, NULL);
if (!status)
{
_tprintf(_T("Error 0x%x calling SymRegisterCallback64.\n"), GetLastError());
goto cleanup;
}
// Go ahead and load a module for testing.
module = SymLoadModuleEx(hProcess, // our unique id
NULL, // no open file handle to image
argv[1], // name of image to load
NULL, // no module name - dbghelp will get it
0, // no base address - dbghelp will get it
0, // no module size - dbghelp will get it
NULL, // no special MODLOAD_DATA structure
0); // flags
if (!module)
{
_tprintf(_T("Error 0x%x calling SymLoadModuleEx.\n"), GetLastError());
goto cleanup;
}
rc = 0;
cleanup:
SymCleanup(hProcess);
return rc;
}
Die Angabe von NULL als zweiten Parameter von SymInitialize gibt an, dass der Symbolhandler den Standardsuchpfad verwenden sollte, um Symboldateien zu suchen. Ausführliche Informationen dazu, wie der Symbolhandler Symboldateien findet oder wie eine Anwendung einen Symbolsuchpfad angeben kann, finden Sie unter Symbolpfade.
Das Ausführen dieses Programms zeigt, wie der Symbolpfad verarbeitet wird. Während DbgHelp den Symbolpfad durchsieht, um die Symboldatei zu finden, ruft es wiederholt SymRegisterCallbackProc64 auf, wodurch wiederum die folgenden Zeichenfolgen angezeigt werden, die von DbgHelp übergeben werden.
d:\load.exe c:\home\dbghelp.dll
DBGHELP: No header for c:\home\dbghelp.dll. Searching for image on disk
DBGHELP: c:\home\dbghelp.dll - OK
DBGHELP: .\dbghelp.pdb - file not found
DBGHELP: .\dll\dbghelp.pdb - file not found
DBGHELP: .\symbols\dll\dbghelp.pdb - file not found
DBGHELP: .\symbols\dll\dbghelp.pdb - file not found
DBGHELP: cache*c:\symbols\dbghelp.pdb - file not found
DBGHELP: cache*c:\symbols\dll\dbghelp.pdb - file not found
DBGHELP: cache*c:\symbols\symbols\dll\dbghelp.pdb - file not found
DBGHELP: d:\nt.binaries.amd64chk\symbols.pri\dbg\dbghelp.pdb - file not found
DBGHELP: dbghelp - private symbols & lines
dbghelp.pdb