Dela via


Skriva ett plugin-program för analystillägg för att utöka !analysera

Du kan utöka funktionerna i kommandot !analyze debugger genom att skriva ett plugin-program för analystillägget. Genom att tillhandahålla ett plugin-program för analystillägg kan du delta i analysen av en buggkontroll eller ett undantag på ett sätt som är specifikt för din egen komponent eller ditt eget program.

När du skriver ett plugin-program för analystillägg skriver du även en metadatafil som beskriver de situationer där du vill att plugin-programmet ska anropas. När !analyze körs, letar den upp, läser in och kör de lämpliga analystilläggsplugin-programmen.

Följ dessa steg om du vill skriva ett plugin-program för analystillägg och göra det tillgängligt för !analyze.

  • Skapa en DLL som exporterar en _EFN_Analyze funktion.
  • Skapa en metadatafil som har samma namn som din DLL och ett tillägg av .alz. Om din DLL till exempel heter MyAnalyzer.dllmåste metadatafilen ha namnet MyAnalyzer.alz. Information om hur du skapar en metadatafil finns i Metadatafiler för analystillägg. Placera metadatafilen i samma katalog som din DLL.
  • I felsökningsprogrammet använder du kommandot .extpath för att lägga till katalogen i filsökvägen för filnamnstillägget. Om din DLL- och metadatafil till exempel finns i mappen c:\MyAnalyzer anger du kommandot .extpath+ c:\MyAnalyzer.

När kommandot !analyze körs i felsökningsprogrammet letar analysmotorn i filsökvägen för filnamnstillägget efter metadatafiler som har .alz-tillägget. Analysmotorn läser metadatafilerna för att avgöra vilka plugin-program för analystillägg som ska läsas in. Anta till exempel att analysmotorn körs som svar på felkontroll 0xA IRQL_NOT_LESS_OR_EQUAL och läser en metadatafil med namnet MyAnalyzer.alz som innehåller följande poster.

PluginId       MyPlugin
DebuggeeClass  Kernel
BugCheckCode   0xA
BugCheckCode   0xE2

BugCheckCode 0x0A Posten anger att plugin-programmet vill delta i analysen av felkontroll 0xA, så analysmotorn läser in MyAnalyzer.dll (som måste finnas i samma katalog som MyAnalyzer.alz) och anropar dess _EFN_Analyze funktion.

Not Den sista raden i metadatafilen måste sluta med ett nytt radtecken.

Skelettexempel

Här är ett skelettexempel som du kan använda som utgångspunkt.

  1. Skapa en DLL med namnet MyAnalyzer.dll som exporterar funktionen _EFN_Analyze som visas här.

    #include <windows.h>
    #define KDEXT_64BIT
    #include <wdbgexts.h>
    #include <dbgeng.h>
    #include <extsfns.h>
    
    extern "C" __declspec(dllexport) HRESULT _EFN_Analyze(_In_ PDEBUG_CLIENT4 Client, 
       _In_ FA_EXTENSION_PLUGIN_PHASE CallPhase, _In_ PDEBUG_FAILURE_ANALYSIS2 pAnalysis)
    { 
       HRESULT hr = E_FAIL;
    
       PDEBUG_CONTROL pControl = NULL;
       hr = Client->QueryInterface(__uuidof(IDebugControl), (void**)&pControl);
    
       if(S_OK == hr && NULL != pControl)
       {
          IDebugFAEntryTags* pTags = NULL;
          pAnalysis->GetDebugFATagControl(&pTags);
    
          if(NULL != pTags)
          {
             if(FA_PLUGIN_INITILIZATION == CallPhase)
             { 
                pControl->Output(DEBUG_OUTPUT_NORMAL, "My analyzer: initialization\n");  
             }
             else if(FA_PLUGIN_STACK_ANALYSIS == CallPhase)
             {
                pControl->Output(DEBUG_OUTPUT_NORMAL, "My analyzer: stack analysis\n"); 
             }
             else if(FA_PLUGIN_PRE_BUCKETING == CallPhase)
             {
                pControl->Output(DEBUG_OUTPUT_NORMAL, "My analyzer: prebucketing\n");
             }
             else if(FA_PLUGIN_POST_BUCKETING == CallPhase)
             {
                pControl->Output(DEBUG_OUTPUT_NORMAL, "My analyzer: post bucketing\n");    
                FA_ENTRY_TYPE entryType = pTags->GetType(DEBUG_FLR_BUGCHECK_CODE);       
                pControl->Output(DEBUG_OUTPUT_NORMAL, "The data type for the DEBUG_FLR_BUGCHECK_CODE tag is 0x%x.\n\n", entryType);
             }
          }
    
          pControl->Release();
       }
       return hr;
    }
    
  2. Skapa en metadatafil med namnet MyAnalyzer.alz som har följande poster.

    PluginId      MyPlugin
    DebuggeeClass Kernel
    BugCheckCode  0xE2
    

    Notera Den sista raden i metadatafilen ska sluta med ett nytt radtecken.

  3. Upprätta en felsökningssession i kernelläge mellan en värd och måldator.

  4. På värddatorn placerar du MyAnalyzer.dll och MyAnalyzer.alz i mappen c:\MyAnalyzer.

  5. I felsökningsprogrammet på värddatorn anger du dessa kommandon.

    .extpath+ c:\MyAnalyzer

    .krasch

  6. Kommandot .crash genererar felkontroll 0xE2 MANUALLY_INITIATED_CRASH på måldatorn, vilket orsakar ett inbrott i felsökningsprogrammet på värddatorn. Analysmotorn för buggkontroll (körs i felsökningsprogrammet på värddatorn) läser MyAnalyzer.alz och ser att MyAnalyzer.dll kan delta i analys av felkontroll 0xE2. Analysmotorn läser därför in MyAnalyzer.dll och anropar dess _EFN_Analyze funktion.

    Kontrollera att du ser utdata som liknar följande i felsökningsprogrammet.

    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************
    
    Use !analyze -v to get detailed debugging information.
    
    BugCheck E2, {0, 0, 0, 0}
    
    My analyzer: initialization
    My analyzer: stack analysis
    My analyzer: prebucketing
    My analyzer: post bucketing
    The data type for the DEBUG_FLR_BUGCHECK_CODE tag is 0x1.
    

Föregående felsökningsutdata visar att analysmotorn anropade funktionen _EFN_Analyze fyra gånger: en gång för varje fas i analysen. Analysmotorn skickar funktionen _EFN_Analyze till två gränssnittspekare. Klienten är ett IDebugClient4-gränssnitt och pAnalysis är ett IDebugFailureAnalysis2-gränssnitt . Koden i föregående skelettexempel visar hur du hämtar ytterligare två gränssnittspekare. Client->QueryInterface hämtar ett IDebugControl-gränssnitt och pAnalysis->GetDebugFATagControl hämtar ett IDebugFAEntryTags-gränssnitt .

Felanalysposter, taggar och datatyper

Analysmotorn skapar ett DebugFailureAnalysis-objekt för att organisera data relaterade till ett visst kodfel. Ett DebugFailureAnalysis-objekt har en samling felanalysposter (FA-poster), som var och en representeras av en FA_ENTRY struktur. Ett plugin-program för analystillägg använder gränssnittet IDebugFailureAnalysis2 för att få åtkomst till den här samlingen med FA-poster. Varje FA-post har en tagg som identifierar den typ av information som posten innehåller. En FA-post kan till exempel ha taggen DEBUG_FLR_BUGCHECK_CODE, vilket anger att posten innehåller en felkontrollkod. Taggar är värden i DEBUG_FLR_PARAM_TYPE uppräkning (definieras i extsfns.h), som också kallas FA_TAG uppräkning.

typedef enum _DEBUG_FLR_PARAM_TYPE {
    ...
    DEBUG_FLR_BUGCHECK_CODE,
    ...
    DEBUG_FLR_BUILD_VERSION_STRING,
    ...
} DEBUG_FLR_PARAM_TYPE;

typedef DEBUG_FLR_PARAM_TYPE FA_TAG;

De flesta FA-poster har ett associerat datablock. DataSize-medlemmen i FA_ENTRY struktur innehåller storleken på datablocket. Vissa FA-poster har inget associerat datablock; all information förmedlas av taggen. I dessa fall har DataSize-medlemmen värdet 0.

typedef struct _FA_ENTRY
{
    FA_TAG Tag;
    USHORT FullSize;
    USHORT DataSize;
} FA_ENTRY, *PFA_ENTRY;

Varje tagg har en uppsättning egenskaper: till exempel namn, beskrivning och datatyp. Ett DebugFailureAnalysis-objekt är associerat med ett DebugFailureAnalysisTags-objekt som innehåller en samling taggegenskaper. Följande diagram illustrerar den här associationen.

Diagram som visar analysmotorn, debugFailureAnalysis-objektet och objektet DebugFailureAnalysisTags.

Ett DebugFailureAnalysis-objekt har en samling FA-poster som tillhör en viss analyssession. Det associerade debugFailureAnalysisTags-objektet har en samling taggegenskaper som endast innehåller taggarna som används av samma analyssession. Som föregående diagram visar har analysmotorn en global taggtabell som innehåller begränsad information om en stor uppsättning taggar som är allmänt tillgängliga för användning av analyssessioner.

Vanligtvis är de flesta taggar som används av en analyssession standardtaggar. Taggarna är alltså värden i FA_TAG uppräkning. Ett plugin-program för analystillägg kan dock skapa anpassade taggar. Ett plugin-program för analystillägg kan lägga till en FA-post i ett DebugFailureAnalysis-objekt och ange en anpassad tagg för posten. I så fall läggs egenskaper för den anpassade taggen till i samlingen med taggegenskaper i det associerade DebugFailureAnalysisTags-objektet .

Du kan komma åt en DebugFailureAnalysisTags via ett gränssnitt för IDebugFAEntry-taggar. Om du vill hämta en pekare till ett IDebugFAEntry-gränssnitt anropar du metoden GetDebugFATagControl i gränssnittet IDebugFailureAnalysis2 .

Varje tagg har en datatypegenskap som du kan inspektera för att fastställa datatypen för data i en felanalyspost. En datatyp representeras av ett värde i FA_ENTRY_TYPE uppräkning.

Följande kodrad hämtar datatypen för taggen DEBUG_FLR_BUILD_VERSION_STRING. I det här fallet är datatypen DEBUG_FA_ENTRY_ANSI_STRING. I koden pAnalysis är en pekare till ett IDebugFailureAnalysis2-gränssnitt .

IDebugFAEntryTags* pTags = pAnalysis->GetDebugFATagControl(&pTags);

if(NULL != pTags)
{
   FA_ENTRY_TYPE entryType = pTags->GetType(DEBUG_FLR_BUILD_VERSION_STRING);
}

Om en felanalyspost inte har något datablock är datatypen för den associerade taggen DEBUG_FA_ENTRY_NO_TYPE.

Kom ihåg att ett DebugFailureAnalysis-objekt har en samling FA-poster. Om du vill se över alla FA-poster i samlingen använder du metoden NextEntry. I följande exempel visas hur du itererar genom hela samlingen med FA-poster. Anta att pAnalysis är en pekare till ett IDebugFailureAnalysis2-gränssnitt . Observera att vi får den första posten genom att skicka NULL till NextEntry.

PFA_ENTRY entry = pAnalysis->NextEntry(NULL);

while(NULL != entry)
{
   // Do something with the entry

   entry = pAnalysis->NextEntry(entry);
}

En tagg kan ha ett namn och en beskrivning. I följande kod är pAnalysis en pekare till ett IDebugFailureAnalysis-gränssnitt , pControl är en pekare till ett IDebugControl-gränssnitt och pTags är en pekare till ett IDebugFAEntryTags-gränssnitt . Koden visar hur du använder metoden GetProperties för att hämta namnet och beskrivningen av taggen som är associerad med en FA-post.

#define MAX_NAME_LENGTH 64
#define MAX_DESCRIPTION_LENGTH 512

CHAR name[MAX_NAME_LENGTH] = {0};
ULONG nameSize = MAX_NAME_LENGTH;
CHAR desc[MAX_DESCRIPTION_LENGTH] = {0};
ULONG descSize = MAX_DESCRIPTION_LENGTH;
                  
PFA_ENTRY pEntry = pAnalysis->NextEntry(NULL); 
pTags->GetProperties(pEntry->Tag, name, &nameSize, desc, &descSize, NULL);
pControl->Output(DEBUG_OUTPUT_NORMAL, "The name is %s\n", name);
pControl->Output(DEBUG_OUTPUT_NORMAL, "The description is %s\n", desc);

Se även

Skriva tillägg för anpassade analysfelsökare

_EFN_Analyze

Metadatafiler för analys-tilläggsprogram

IDebugFailureAnalysis2

IDebugFAEntryTags