253 lines
7.6 KiB
C++
253 lines
7.6 KiB
C++
|
/*-----------------------------------------------------------------------------
|
||
|
Copyright (c) 2000 Microsoft Corporation
|
||
|
|
||
|
Module:
|
||
|
exts.cpp
|
||
|
|
||
|
Sampe file showing couple of extension examples
|
||
|
|
||
|
-----------------------------------------------------------------------------*/
|
||
|
#include "dbgexts.h"
|
||
|
|
||
|
|
||
|
/*
|
||
|
Sample extension to demonstrace ececuting debugger command
|
||
|
|
||
|
*/
|
||
|
HRESULT CALLBACK
|
||
|
cmdsample(PDEBUG_CLIENT Client, PCSTR args)
|
||
|
{
|
||
|
CHAR Input[256];
|
||
|
INIT_API();
|
||
|
|
||
|
UNREFERENCED_PARAMETER(args);
|
||
|
|
||
|
//
|
||
|
// Output a 10 frame stack
|
||
|
//
|
||
|
g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS | // Flags on what to do with output
|
||
|
DEBUG_OUTCTL_OVERRIDE_MASK |
|
||
|
DEBUG_OUTCTL_NOT_LOGGED,
|
||
|
NULL,
|
||
|
10, // number of frames to display
|
||
|
DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES |
|
||
|
DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES);
|
||
|
//
|
||
|
// Engine interface for print
|
||
|
//
|
||
|
g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n");
|
||
|
|
||
|
//
|
||
|
// list all the modules by executing lm command
|
||
|
//
|
||
|
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
|
||
|
DEBUG_OUTCTL_OVERRIDE_MASK |
|
||
|
DEBUG_OUTCTL_NOT_LOGGED,
|
||
|
"lm", // Command to be executed
|
||
|
DEBUG_EXECUTE_DEFAULT );
|
||
|
|
||
|
//
|
||
|
// Ask for user input
|
||
|
//
|
||
|
g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : ");
|
||
|
GetInputLine(NULL, &Input[0], sizeof(Input));
|
||
|
g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
|
||
|
DEBUG_OUTCTL_OVERRIDE_MASK |
|
||
|
DEBUG_OUTCTL_NOT_LOGGED,
|
||
|
Input, // Command to be executed
|
||
|
DEBUG_EXECUTE_DEFAULT );
|
||
|
|
||
|
EXIT_API();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Sample extension to read and dump a struct on target
|
||
|
|
||
|
This reads the struct _EXCEPTION_RECORD which is defined as:
|
||
|
|
||
|
typedef struct _EXCEPTION_RECORD {
|
||
|
NTSTATUS ExceptionCode;
|
||
|
ULONG ExceptionFlags;
|
||
|
struct _EXCEPTION_RECORD *ExceptionRecord;
|
||
|
PVOID ExceptionAddress;
|
||
|
ULONG NumberParameters;
|
||
|
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
|
||
|
} EXCEPTION_RECORD;
|
||
|
*/
|
||
|
HRESULT CALLBACK
|
||
|
structsample(PDEBUG_CLIENT Client, PCSTR args)
|
||
|
{
|
||
|
ULONG64 Address;
|
||
|
INIT_API();
|
||
|
|
||
|
Address = GetExpression(args);
|
||
|
|
||
|
DWORD Buffer[4], cb;
|
||
|
|
||
|
// Read and display first 4 dwords at Address
|
||
|
if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) {
|
||
|
dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address,
|
||
|
Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Method 1 to dump a struct
|
||
|
//
|
||
|
dprintf("Method 1:\n");
|
||
|
// Inititalze type read from the Address
|
||
|
if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) {
|
||
|
dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values
|
||
|
Address);
|
||
|
} else {
|
||
|
// read and dump the fields
|
||
|
dprintf("_EXCEPTION_RECORD @ %p\n", Address);
|
||
|
dprintf("\tExceptionCode : %lx\n", (ULONG) ReadField(ExceptionCode));
|
||
|
dprintf("\tExceptionAddress : %p\n", ReadField(ExceptionAddress));
|
||
|
dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1]));
|
||
|
// And so on...
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Method 2 to read a struct
|
||
|
//
|
||
|
ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode;
|
||
|
dprintf("\n\nMethod 2:\n");
|
||
|
// Read and dump the fields by specifying type and address individually
|
||
|
if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) {
|
||
|
dprintf("Error in reading _EXCEPTION_RECORD at %p\n",
|
||
|
Address);
|
||
|
} else {
|
||
|
// Pointers are read as ULONG64 values
|
||
|
GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress);
|
||
|
GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1);
|
||
|
// And so on..
|
||
|
|
||
|
dprintf("_EXCEPTION_RECORD @ %p\n", Address);
|
||
|
dprintf("\tExceptionCode : %lx\n", ExceptionCode);
|
||
|
dprintf("\tExceptionAddress : %p\n", ExceptionAddress);
|
||
|
dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1);
|
||
|
}
|
||
|
|
||
|
ULONG64 Module;
|
||
|
ULONG i, TypeId;
|
||
|
CHAR Name[MAX_PATH];
|
||
|
//
|
||
|
// To get/list field names
|
||
|
//
|
||
|
g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module);
|
||
|
dprintf("Fields of _EXCEPTION_RECORD\n");
|
||
|
for (i=0; ;i++) {
|
||
|
HRESULT Hr;
|
||
|
ULONG Offset=0;
|
||
|
|
||
|
Hr = g_ExtSymbols2->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL);
|
||
|
if (Hr == S_OK) {
|
||
|
g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset);
|
||
|
dprintf("%lx (+%03lx) %s\n", i, Offset, Name);
|
||
|
} else if (Hr == E_INVALIDARG) {
|
||
|
// All Fields done
|
||
|
break;
|
||
|
} else {
|
||
|
dprintf("GetFieldName Failed %lx\n", Hr);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get name for an enumerate
|
||
|
//
|
||
|
// typedef enum {
|
||
|
// Enum1,
|
||
|
// Enum2,
|
||
|
// Enum3,
|
||
|
// } TEST_ENUM;
|
||
|
//
|
||
|
ULONG ValueOfEnum = 0;
|
||
|
g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module);
|
||
|
g_ExtSymbols2->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL);
|
||
|
dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name);
|
||
|
// This prints out, Testenum 0 == Enum1
|
||
|
|
||
|
//
|
||
|
// Read an array
|
||
|
//
|
||
|
// typedef struct FOO_TYPE {
|
||
|
// ULONG Bar;
|
||
|
// ULONG Bar2;
|
||
|
// } FOO_TYPE;
|
||
|
//
|
||
|
// FOO_TYPE sampleArray[20];
|
||
|
ULONG Bar, Bar2;
|
||
|
CHAR TypeName[100];
|
||
|
for (i=0; i<20; i++) {
|
||
|
sprintf(TypeName, "sampleArray[%lx]", i);
|
||
|
if (GetFieldValue(0, TypeName, "Bar", Bar))
|
||
|
break;
|
||
|
GetFieldValue(0, TypeName, "Bar2", Bar2);
|
||
|
dprintf("%16s - Bar %2ld Bar2 %ld\n", TypeName, Bar, Bar2);
|
||
|
}
|
||
|
|
||
|
EXIT_API();
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
This gets called (by DebugExtensionNotify whentarget is halted and is accessible
|
||
|
*/
|
||
|
HRESULT
|
||
|
NotifyOnTargetAccessible(PDEBUG_CONTROL Control)
|
||
|
{
|
||
|
dprintf("Extension dll detected a break");
|
||
|
if (Connected) {
|
||
|
dprintf(" connected to ");
|
||
|
switch (TargetMachine) {
|
||
|
case IMAGE_FILE_MACHINE_I386:
|
||
|
dprintf("X86");
|
||
|
break;
|
||
|
case IMAGE_FILE_MACHINE_IA64:
|
||
|
dprintf("IA64");
|
||
|
break;
|
||
|
default:
|
||
|
dprintf("Other");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
dprintf("\n");
|
||
|
|
||
|
//
|
||
|
// show the top frame and execute dv to dump the locals here and return
|
||
|
//
|
||
|
Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
|
||
|
DEBUG_OUTCTL_OVERRIDE_MASK |
|
||
|
DEBUG_OUTCTL_NOT_LOGGED,
|
||
|
".frame", // Command to be executed
|
||
|
DEBUG_EXECUTE_DEFAULT );
|
||
|
Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
|
||
|
DEBUG_OUTCTL_OVERRIDE_MASK |
|
||
|
DEBUG_OUTCTL_NOT_LOGGED,
|
||
|
"dv", // Command to be executed
|
||
|
DEBUG_EXECUTE_DEFAULT );
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
A built-in help for the extension dll
|
||
|
*/
|
||
|
HRESULT CALLBACK
|
||
|
help(PDEBUG_CLIENT Client, PCSTR args)
|
||
|
{
|
||
|
INIT_API();
|
||
|
|
||
|
UNREFERENCED_PARAMETER(args);
|
||
|
|
||
|
dprintf("Help for dbgexts.dll\n"
|
||
|
" cmdsample - This does stacktrace and lists\n"
|
||
|
" help = Shows this help\n"
|
||
|
" structsample <addr> - This dumps a struct at given address\n"
|
||
|
);
|
||
|
EXIT_API();
|
||
|
|
||
|
return S_OK;
|
||
|
}
|