Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Você pode ampliar as capacidades do comando depurador !analyze escrevendo um plug-in de extensão de análise. Ao fornecer um plug-in de extensão de análise, você pode participar da análise de uma verificação de bug ou uma exceção de uma forma específica para seu próprio componente ou aplicativo.
Quando você escreve um plug-in de extensão de análise, você também escreve um arquivo de metadados que descreve as situações para as quais você deseja que seu plug-in seja chamado. Quando !analyze é executado, ele localiza, carrega e executa os plug-ins de extensão de análise apropriados.
Para escrever um plugin de extensão de análise e disponibilizá-lo para !analyze, siga estes passos.
- Crie uma DLL que exporte uma função _EFN_Analyze.
- Crie um arquivo de metadados que tenha o mesmo nome que sua DLL e uma extensão de .alz. Por exemplo, se sua DLL é nomeada MyAnalyzer.dll, seu arquivo de metadados deve ser chamado MyAnalyzer.alz. Para obter informações sobre como criar um arquivo de metadados, consulte Metadata Files for Analysis Extensions. Coloque o arquivo de metadados no mesmo diretório que sua DLL.
- No depurador, use o comando .extpath para adicionar seu diretório ao caminho do arquivo de extensão. Por exemplo, se a DLL e o arquivo de metadados estiverem na pasta chamada c:\MyAnalyzer, digite o comando .extpath+ c:\MyAnalyzer.
Quando o comando !analyze é executado no depurador, o mecanismo de análise procura no caminho do arquivo de extensão por arquivos de metadados que tenham a extensão .alz. O mecanismo de análise lê os arquivos de metadados para determinar quais plug-ins de extensão de análise devem ser carregados. Por exemplo, suponha que o mecanismo de análise esteja sendo executado em resposta ao Bug Check 0xA IRQL_NOT_LESS_OR_EQUAL e leia um arquivo de metadados chamado MyAnalyzer.alz que contém as seguintes entradas.
PluginId MyPlugin
DebuggeeClass Kernel
BugCheckCode 0xA
BugCheckCode 0xE2
A entrada BugCheckCode 0x0A especifica que este plugin deseja participar da análise do Bug Check 0xA, então o mecanismo de análise carrega MyAnalyzer.dll (que deve estar no mesmo diretório que MyAnalyzer.alz) e chama sua função _EFN_Analyze.
Nota A última linha do arquivo de metadados deve terminar com um caractere de nova linha.
Exemplo de esqueleto
Aqui está um exemplo de esqueleto que você pode usar como ponto de partida.
Crie uma DLL chamada MyAnalyzer.dll que exporta a função _EFN_Analyze mostrada aqui.
#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; }Crie um arquivo de metadados chamado MyAnalyzer.alz que tenha as seguintes entradas.
PluginId MyPlugin DebuggeeClass Kernel BugCheckCode 0xE2Nota A última linha do ficheiro de metadados deve terminar com um caractere de nova linha.
Estabeleça uma sessão de depuração em modo kernel entre um host e o computador de destino.
No computador host, coloque MyAnalyzer.dll e MyAnalyzer.alz na pasta c:\MyAnalyzer.
No computador anfitrião, no depurador, insira estes comandos.
.extpath+ c:\MyAnalyzer
.crash
O comando .crash gera o código de verificação de bugs 0xE2 MANUALLY_INITIATED_CRASH no computador de destino, o que provoca uma interrupção no depurador no computador host. O mecanismo de análise de checagem de erros (em execução no depurador no computador host) lê MyAnalyzer.alz e vê que MyAnalyzer.dll é capaz de analisar o erro 0xE2. Portanto, o motor de análise carrega MyAnalyzer.dll e chama a sua função _EFN_Analyze.
Verifique se você vê uma saída semelhante à seguinte no depurador.
* 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.
A saída do depurador anterior mostra que o mecanismo de análise chamou a função _EFN_Analyze quatro vezes: uma vez para cada fase da análise. O motor de análise passa dois ponteiros de interface para a função _EFN_Analyze.
Client é uma interface IDebugClient4 e pAnalysis é uma interface IDebugFailureAnalysis2. O código no exemplo de esqueleto anterior mostra como obter mais dois ponteiros de interface.
Client->QueryInterface obtém uma interface IDebugControl, e pAnalysis->GetDebugFATagControl obtém uma interface IDebugFAEntryTags.
Entradas, tags e tipos de dados de análise de falhas
O mecanismo de análise cria um objeto DebugFailureAnalysis para organizar os dados relacionados a uma falha de código específica. Um objeto DebugFailureAnalysis tem uma coleção de entradas de análise de falha (entradas FA), cada uma das quais é representada por uma estrutura FA_ENTRY. Um plug-in de extensão de análise utiliza a interface IDebugFailureAnalysis2 do para aceder a esta coleção de entradas de FA. Cada entrada FA tem uma tag que identifica o tipo de informação que a entrada contém. Por exemplo, uma entrada FA pode ter a tag DEBUG_FLR_BUGCHECK_CODE, que nos diz que a entrada contém um código de verificação de bug. Tags são valores na enumeração DEBUG_FLR_PARAM_TYPE (definida em extsfns.h), que também é chamada de enumeração FA_TAG.
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;
A maioria das entradas FA têm um bloco de dados associado. O DataSize campo da estrutura FA_ENTRY contém o tamanho do bloco de dados. Algumas entradas FA não têm um bloco de dados associado; Toda a informação é transmitida pela etiqueta. Nesses casos, o DataSize membro tem um valor de 0.
typedef struct _FA_ENTRY
{
FA_TAG Tag;
USHORT FullSize;
USHORT DataSize;
} FA_ENTRY, *PFA_ENTRY;
Cada tag tem um conjunto de propriedades: por exemplo, nome, descrição e tipo de dados. Um objeto DebugFailureAnalysis está associado a um objeto DebugFailureAnalysisTags, que contém uma coleção de propriedades de etiquetas. O diagrama a seguir ilustra essa associação.
Um objeto de DebugFailureAnalysis tem uma coleção de entradas FA que pertencem a uma sessão de análise particular. O objeto associado DebugFailureAnalysisTags tem uma coleção de propriedades de tag que inclui apenas as tags usadas por essa mesma sessão de análise. Como mostra o diagrama anterior, o mecanismo de análise tem uma tabela de tags global que contém informações limitadas sobre um grande conjunto de tags que geralmente estão disponíveis para uso por sessões de análise.
Normalmente, a maioria das tags usadas por uma sessão de análise são tags padrão; ou seja, as tags são valores na enumeração FA_TAG. No entanto, um plug-in de extensão de análise pode criar tags personalizadas. Um plug-in de extensão de análise pode adicionar uma entrada FA a um objeto DebugFailureAnalysis e especificar uma tag personalizada para a entrada. Nesse caso, as propriedades da tag personalizada são adicionadas à coleção de propriedades da tag no objeto associado DebugFailureAnalysisTags.
Você pode acessar um DebugFailureAnalysisTags por meio de uma interface de tags IDebugFAEntry. Para obter um ponteiro para uma interface IDebugFAEntry, chame o método GetDebugFATagControl do da interfaceIDebugFailureAnalysis2 do.
Cada tag tem uma propriedade de tipo de dados que você pode inspecionar para determinar o tipo de dados dos dados em uma entrada de análise de falha. Um tipo de dados é representado por um valor na enumeração FA_ENTRY_TYPE.
A seguinte linha de código obtém o tipo de dados da tag DEBUG_FLR_BUILD_VERSION_STRING. Nesse caso, o tipo de dados é DEBUG_FA_ENTRY_ANSI_STRING. No código, pAnalysis é um ponteiro para um IDebugFailureAnalysis2 interface.
IDebugFAEntryTags* pTags = pAnalysis->GetDebugFATagControl(&pTags);
if(NULL != pTags)
{
FA_ENTRY_TYPE entryType = pTags->GetType(DEBUG_FLR_BUILD_VERSION_STRING);
}
Se uma entrada de análise de falha não tiver nenhum bloco de dados, o tipo de dados da tag associada será DEBUG_FA_ENTRY_NO_TYPE.
Lembre-se de que um objeto DebugFailureAnalysis possui uma coleção de entradas FA. Para inspecionar todas as entradas FA na coleção, use o método NextEntry. O exemplo a seguir mostra como percorrer toda a coleção de entradas de FA. Suponha que pAnalysis é um ponteiro para uma interface IDebugFailureAnalysis2. Observe que obtemos a primeira entrada passando NULL para NextEntry.
PFA_ENTRY entry = pAnalysis->NextEntry(NULL);
while(NULL != entry)
{
// Do something with the entry
entry = pAnalysis->NextEntry(entry);
}
Uma tag pode ter um nome e uma descrição. No código a seguir, pAnalysis é um ponteiro para uma interface IDebugFailureAnalysis, pControl é um ponteiro para uma interface IDebugControl, e pTags é um ponteiro para uma interface IDebugFAEntryTags. O código mostra como usar o método GetProperties para obter o nome e a descrição da tag associada a uma entrada FA .
#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);
Ver também
Escrevendo extensões de depurador de análise personalizada