Partager via


Réception de notifications

Le code suivant montre comment obtenir et signaler des informations détaillées status à partir du gestionnaire de symboles sur la recherche et le chargement des modules et des fichiers de symboles correspondants.

Beaucoup connaissent le débogueur WinDbg peuvent se souvenir d’une commande appelée « !sym noisy ». Cette commande est utilisée par l’utilisateur pour déterminer pourquoi WinDbg est ou n’est pas en mesure de charger des fichiers de symboles. Il affiche une liste détaillée de tout ce que le gestionnaire de symboles essaie.

Cette même liste est également disponible pour toute personne qui développe un client sur le gestionnaire de symboles DbgHelp.

Tout d’abord, appelez SymSetOptions avec SYMOPT_DEBUG. DbgHelp active alors les notifications de débogage.

Après avoir appelé SymInitialize, utilisez SymRegisterCallback64 pour inscrire une fonction de rappel que DbgHelp appellera chaque fois qu’un événement intéressant se produit. Dans cet exemple, la fonction de rappel est appelée SymRegisterCallbackProc64. Les fonctions de rappel de symboles sont transmises à un assortiment de codes d’action qu’elles peuvent gérer en fonction du type. Dans cet exemple, nous gérons uniquement le code d’action CBA_EVENT . Cette fonction transmet une chaîne contenant des informations détaillées sur un événement qui s’est produit lors du chargement d’un symbole. Cet événement peut aller d’une tentative de lecture des données dans une image exécutable à l’emplacement réussi d’un fichier de symboles. SymRegisterCallbackProc64 affiche cette chaîne et retourne TRUE.

Important

Veillez à retourner FALSE à chaque code d’action que vous ne gérez pas, sinon vous risquez de rencontrer un comportement non défini. Reportez-vous à SymRegisterCallbackProc64 pour obtenir la liste de tous les codes d’action et leurs implications.

 

Maintenant que le rappel est inscrit, il est temps de charger le module spécifié sur la ligne de commande en appelant SymLoadModuleEx.

Enfin, appelez SymCleanup avant de quitter.

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

La spécification de NULL comme deuxième paramètre de SymInitialize indique que le gestionnaire de symboles doit utiliser le chemin de recherche par défaut pour localiser les fichiers de symboles. Pour plus d’informations sur la façon dont le gestionnaire de symboles localise les fichiers de symboles ou sur la façon dont une application peut spécifier un chemin de recherche de symboles, consultez Chemins d’accès aux symboles.

L’exécution de ce programme montre comment le chemin du symbole est traité. Lorsque DbgHelp recherche le fichier de symboles, il appelle à plusieurs reprises SymRegisterCallbackProc64 qui, à son tour, affiche les chaînes suivantes transmises par 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