Recupero di notifiche

Il codice seguente illustra come ottenere e segnalare informazioni sullo stato dettagliate dal gestore dei simboli sulla ricerca e il caricamento di moduli e dei file di simboli corrispondenti.

Molti familiarità con il debugger WinDbg possono ricordare un comando denominato "!sym noisy". Questo comando viene usato dall'utente per determinare il motivo per cui WinDbg è o non è in grado di caricare i file di simboli. Mostra un elenco dettagliato di tutti i tentativi del gestore dei simboli.

Lo stesso elenco è disponibile anche per chiunque sviluppi un client nel gestore dei simboli DbgHelp.

Prima di tutto, chiama SymSetOptions con SYMOPT_DEBUG. In questo modo DbgHelp attiva le notifiche di debug.

Dopo aver chiamato SymInitialize, usare SymRegisterCallback64 per registrare una funzione di callback che DbgHelp chiamerà ogni volta che si verifica un evento interessante. In questo esempio la funzione di callback è denominata SymRegisterCallbackProc64. Le funzioni di callback dei simboli vengono passate a un assortimento di codici azione che possono gestire in base al tipo. In questo esempio viene gestito solo il codice azione CBA_EVENT . Questa funzione passa una stringa contenente informazioni dettagliate su un evento che si è verificato durante il caricamento di un simbolo. Questo evento può essere qualsiasi elemento da un tentativo di leggere i dati all'interno di un'immagine eseguibile nella posizione corretta di un file di simboli. SymRegisterCallbackProc64 visualizza la stringa e restituisce TRUE.

Importante

Assicurarsi di restituire FAL edizione Standard a ogni codice azione non gestito. In caso contrario, è possibile che si verifichi un comportamento non definito. Per un elenco di tutti i codici azione e le relative implicazioni, vedere SymRegisterCallbackProc64.

 

Ora che il callback è registrato, è il momento di caricare il modulo specificato nella riga di comando chiamando SymLoadModuleEx.

Infine, chiama SymCleanup prima di uscire.

#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;    
}

Se si specifica NULL come secondo parametro di SymInitialize , il gestore dei simboli deve usare il percorso di ricerca predefinito per individuare i file di simboli. Per informazioni dettagliate sul modo in cui il gestore dei simboli individua i file di simboli o su come un'applicazione può specificare un percorso di ricerca dei simboli, vedere Percorsi dei simboli.

L'esecuzione di questo programma mostra come viene elaborato il percorso del simbolo. Quando DbgHelp esamina il percorso del simbolo per trovare il file di simboli, chiama ripetutamente SymRegisterCallbackProc64 che, a sua volta, visualizza le stringhe seguenti passate da DbgHelp.

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