次の方法で共有


通知を受け取る

次のコードは、モジュールと対応するシンボル ファイルの検索と読み込みに関する詳細なステータス情報をシンボル ハンドラーから取得して報告する方法を示しています。

WinDbg デバッガに詳しい人は、「!sym noisy」というコマンドを覚えているかもしれません。 このコマンドは、WinDbg がシンボル ファイルを読み込むことができない理由を判断するためにユーザーによって使用されます。 シンボル ハンドラーが試行するすべての詳細な一覧が表示されます。

この同じ一覧は、DbgHelp シンボル ハンドラーに対してクライアントを開発するすべてのユーザーにも使用できます。

まず、SYMOPT_DEBUG を使用して SymSetOptions を呼び出します。 これにより、DbgHelp はデバッグ通知を有効にします。

SymInitialize を呼び出した後、SymRegisterCallback64 を使用して、関心のあるイベントが発生するたびに DbgHelp が呼び出すコールバック関数を登録します。 この例では、コールバック関数は SymRegisterCallbackProc64 です。 シンボル コールバック関数には、種類に応じて処理できるさまざまなアクション コードが渡されます。 この例では、CBA_EVENT アクション コードのみを処理しています。 この関数は、シンボルの読み込み中に発生したイベントに関する詳細情報を含む文字列を渡します。 このイベントは、実行可能イメージ内のデータを読み取ろうとしてからシンボル ファイルの正常な場所まで、あらゆるものになる可能性があります。 SymRegisterCallbackProc64 はその文字列を表示し、TRUE を返します。

重要

処理しないすべてのアクション コードに FALSE を返すようにしてください。そうしないと、未定義の動作が発生する可能性があります。 すべてのアクション コードとその影響の一覧については、SymRegisterCallbackProc64 を参照してください。

 

コールバックが登録されたので、SymLoadModuleEx を呼び出して、コマンド ラインで指定されたモジュールを読み込みます。

最後に、終了する前に SymCleanup を呼び出します。

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

SymInitialize の 2 番目のパラメーターとして NULL を指定すると、シンボル ハンドラーは既定の検索パスを使用してシンボル ファイルを検索する必要があることを示します。 シンボル ハンドラーがシンボル ファイルを検索する方法、またはアプリケーションでシンボル検索パスを指定する方法の詳細については、「シンボル パス」を参照してください。

このプログラムを実行すると、シンボル パスの処理方法が示されます。 DbgHelp はシンボル パスを調べてシンボル ファイルを見つけると、SymRegisterCallbackProc64 を繰り返し呼び出します。これにより、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