windows-nt/Source/XPSP1/NT/sdktools/debuggers/exts/kextdll/kext.cpp
2020-09-26 16:20:57 +08:00

589 lines
12 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
exts.c
Abstract:
This file contains the generic routines and initialization code
for the kernel debugger extensions dll.
Environment:
User Mode
--*/
#include "precomp.h"
#pragma hdrstop
#include <ntverp.h>
//
// Valid for the lifetime of the debug session.
//
WINDBG_EXTENSION_APIS ExtensionApis;
ULONG TargetMachine;
BOOL Connected;
ULONG g_TargetClass, g_TargetQual;
//
// Valid only during an extension API call
//
PDEBUG_ADVANCED g_ExtAdvanced;
PDEBUG_CLIENT g_ExtClient;
PDEBUG_CONTROL g_ExtControl;
PDEBUG_DATA_SPACES g_ExtData;
PDEBUG_REGISTERS g_ExtRegisters;
PDEBUG_SYMBOLS2 g_ExtSymbols;
PDEBUG_SYSTEM_OBJECTS g_ExtSystem;
// Queries for all debugger interfaces.
extern "C" HRESULT
ExtQuery(PDEBUG_CLIENT Client)
{
HRESULT Status;
if ((Status = Client->QueryInterface(__uuidof(IDebugAdvanced),
(void **)&g_ExtAdvanced)) != S_OK)
{
goto Fail;
}
if ((Status = Client->QueryInterface(__uuidof(IDebugControl),
(void **)&g_ExtControl)) != S_OK)
{
goto Fail;
}
if ((Status = Client->QueryInterface(__uuidof(IDebugDataSpaces),
(void **)&g_ExtData)) != S_OK)
{
goto Fail;
}
if ((Status = Client->QueryInterface(__uuidof(IDebugRegisters),
(void **)&g_ExtRegisters)) != S_OK)
{
goto Fail;
}
if ((Status = Client->QueryInterface(__uuidof(IDebugSymbols),
(void **)&g_ExtSymbols)) != S_OK)
{
goto Fail;
}
if ((Status = Client->QueryInterface(__uuidof(IDebugSystemObjects),
(void **)&g_ExtSystem)) != S_OK)
{
goto Fail;
}
g_ExtClient = Client;
return S_OK;
Fail:
ExtRelease();
return Status;
}
// Cleans up all debugger interfaces.
void
ExtRelease(void)
{
g_ExtClient = NULL;
EXT_RELEASE(g_ExtAdvanced);
EXT_RELEASE(g_ExtControl);
EXT_RELEASE(g_ExtData);
EXT_RELEASE(g_ExtRegisters);
EXT_RELEASE(g_ExtSymbols);
EXT_RELEASE(g_ExtSystem);
}
// Normal output.
void __cdecl
ExtOut(PCSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args);
va_end(Args);
}
// Error output.
void __cdecl
ExtErr(PCSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args);
va_end(Args);
}
// Warning output.
void __cdecl
ExtWarn(PCSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args);
va_end(Args);
}
// Verbose output.
void __cdecl
ExtVerb(PCSTR Format, ...)
{
va_list Args;
va_start(Args, Format);
g_ExtControl->OutputVaList(DEBUG_OUTPUT_VERBOSE, Format, Args);
va_end(Args);
}
extern "C"
HRESULT
CALLBACK
DebugExtensionInitialize(PULONG Version, PULONG Flags)
{
IDebugClient *DebugClient;
PDEBUG_CONTROL DebugControl;
HRESULT Hr;
*Version = DEBUG_EXTENSION_VERSION(1, 0);
*Flags = 0;
if ((Hr = DebugCreate(__uuidof(IDebugClient),
(void **)&DebugClient)) != S_OK)
{
return Hr;
}
if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
(void **)&DebugControl)) != S_OK)
{
return Hr;
}
ExtensionApis.nSize = sizeof (ExtensionApis);
if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) {
return Hr;
}
DebugControl->Release();
DebugClient->Release();
return S_OK;
}
extern "C"
void
CALLBACK
DebugExtensionNotify(ULONG Notify, ULONG64 Argument)
{
//
// The first time we actually connect to a target, get the page size
//
if ((Notify == DEBUG_NOTIFY_SESSION_ACCESSIBLE) && (!Connected))
{
IDebugClient *DebugClient;
PDEBUG_DATA_SPACES DebugDataSpaces;
PDEBUG_CONTROL DebugControl;
HRESULT Hr;
ULONG64 Page;
if ((Hr = DebugCreate(__uuidof(IDebugClient),
(void **)&DebugClient)) == S_OK)
{
//
// Get the architecture type.
//
if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
(void **)&DebugControl)) == S_OK)
{
if ((Hr = DebugControl->GetActualProcessorType(
&TargetMachine)) == S_OK)
{
Connected = TRUE;
}
ULONG Qualifier;
if ((Hr = DebugControl->GetDebuggeeType(&g_TargetClass, &g_TargetQual)) == S_OK)
{
}
DebugControl->Release();
}
DebugClient->Release();
}
}
if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE)
{
Connected = FALSE;
TargetMachine = 0;
}
return;
}
extern "C"
void
CALLBACK
DebugExtensionUninitialize(void)
{
return;
}
DllInit(
HANDLE hModule,
DWORD dwReason,
DWORD dwReserved
)
{
switch (dwReason) {
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_PROCESS_ATTACH:
break;
}
return TRUE;
}
DECLARE_API ( time )
{
dprintf("*** !time is obsolete: Use '.time'\n");
return S_OK;
}
HRESULT
PrintString(
BOOL Unicode,
PDEBUG_CLIENT Client,
LPCSTR args
)
{
ULONG64 AddrString;
ULONG64 Displacement;
STRING32 String;
UNICODE_STRING UnicodeString;
ULONG64 AddrBuffer;
CHAR Symbol[1024];
LPSTR StringData;
HRESULT hResult;
BOOL b;
AddrString = GetExpression(args);
if (!AddrString)
{
return E_FAIL;
}
//
// Get the symbolic name of the string
//
GetSymbol(AddrString, Symbol, &Displacement);
//
// Read the string from the debuggees address space into our
// own.
b = ReadMemory(AddrString, &String, sizeof(String), NULL);
if ( !b )
{
return E_FAIL;
}
INIT_API();
if (IsPtr64())
{
hResult = g_ExtData->ReadPointersVirtual(1,
AddrString + FIELD_OFFSET(STRING64, Buffer),
&AddrBuffer);
}
else
{
hResult = g_ExtData->ReadPointersVirtual(1,
AddrString + FIELD_OFFSET(STRING32, Buffer),
&AddrBuffer);
}
EXIT_API();
if (hResult != S_OK)
{
return E_FAIL;
}
StringData = (LPSTR) LocalAlloc(LMEM_ZEROINIT,
String.Length + sizeof(UNICODE_NULL));
if (!StringData)
{
return E_FAIL;
}
dprintf("String(%d,%d)", String.Length, String.MaximumLength);
if (Symbol[0])
{
dprintf(" %s+%p", Symbol, Displacement);
}
b = ReadMemory(AddrBuffer, StringData, String.Length, NULL);
if ( b )
{
if (Unicode)
{
ANSI_STRING AnsiString;
UnicodeString.Buffer = (PWSTR)StringData;
UnicodeString.Length = String.Length;
UnicodeString.MaximumLength = String.Length+sizeof(UNICODE_NULL);
RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString,TRUE);
dprintf(" at %p: %s\n", AddrString, AnsiString.Buffer);
RtlFreeAnsiString(&AnsiString);
}
else
{
dprintf(" at %p: %s\n", AddrString, StringData);
}
LocalFree(StringData);
return S_OK;
}
else
{
LocalFree(StringData);
return E_FAIL;
}
}
DECLARE_API( str )
/*++
Routine Description:
This function is called to format and dump counted (ansi) string.
Arguments:
args - Address
Return Value:
None.
--*/
{
return PrintString(FALSE, Client, args);
}
DECLARE_API( ustr )
/*++
Routine Description:
This function is called to format and dump counted (unicode) string.
Arguments:
args - Address
Return Value:
None.
--*/
{
return PrintString(TRUE, Client, args);
}
DECLARE_API( obja )
/*++
Routine Description:
This function is called to format and dump an object attributes structure.
Arguments:
args - Address
Return Value:
None.
--*/
{
ULONG64 AddrObja;
ULONG64 Displacement;
ULONG64 AddrString;
STRING32 String;
ULONG64 StrAddr = NULL;
CHAR Symbol[1024];
LPSTR StringData;
BOOL b;
ULONG Attr;
HRESULT hResult;
ULONG ObjectNameOffset;
ULONG AttrOffset;
ULONG StringOffset;
if (IsPtr64())
{
ObjectNameOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES64, ObjectName);
AttrOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES64, Attributes);
StringOffset = FIELD_OFFSET(STRING64, Buffer);
}
else
{
ObjectNameOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES32, ObjectName);
AttrOffset = FIELD_OFFSET(OBJECT_ATTRIBUTES32, Attributes);
StringOffset = FIELD_OFFSET(STRING32, Buffer);
}
AddrObja = GetExpression(args);
if (!AddrObja)
{
return E_FAIL;
}
//
// Get the symbolic name of the Obja
//
GetSymbol(AddrObja, Symbol, &Displacement);
dprintf("Obja %s+%p at %p:\n", Symbol, Displacement, AddrObja);
INIT_API();
hResult = g_ExtData->ReadPointersVirtual(1,
AddrObja + ObjectNameOffset,
&AddrString);
if (hResult != S_OK)
{
return E_FAIL;
}
if (AddrString)
{
b = ReadMemory(AddrString, &String, sizeof(String), NULL);
hResult = g_ExtData->ReadPointersVirtual(1,
AddrString + StringOffset,
&StrAddr);
}
EXIT_API();
if (StrAddr)
{
StringData = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
String.Length+sizeof(UNICODE_NULL));
if (StringData)
{
b = ReadMemory(StrAddr, StringData, String.Length, NULL);
if (b)
{
dprintf("\tName is %ws\n", StringData);
}
LocalFree(StringData);
}
}
b = ReadMemory(AddrObja + AttrOffset, &Attr, sizeof(Attr), NULL);
if (!b)
{
return E_FAIL;
}
if (Attr & OBJ_INHERIT )
{
dprintf("\tOBJ_INHERIT\n");
}
if (Attr & OBJ_PERMANENT )
{
dprintf("\tOBJ_PERMANENT\n");
}
if (Attr & OBJ_EXCLUSIVE )
{
dprintf("\tOBJ_EXCLUSIVE\n");
}
if (Attr & OBJ_CASE_INSENSITIVE )
{
dprintf("\tOBJ_CASE_INSENSITIVE\n");
}
if (Attr & OBJ_OPENIF )
{
dprintf("\tOBJ_OPENIF\n");
}
return S_OK;
}
DECLARE_API( help )
{
dprintf("analyzebugcheck - Perform bugcheck analysis\n");
dprintf("ecb - Edit PCI ConfigSpace byte\n");
dprintf("ecd - Edit PCI ConfigSpace dword\n");
dprintf("ecw - Edit PCI ConfigSpace word\n");
dprintf("exca <BasePort>.<SktNum> - Dump ExCA registers\n");
dprintf("help - Show this help\n");
dprintf("pci [flag] [bus] [device] [function] [rawdump:minaddr] [maxaddr] - Dumps pci type1 config\n");
dprintf(" flag: 0x01 - verbose\n");
dprintf(" 0x02 - from bus 0 to 'bus'\n");
dprintf(" 0x04 - dump raw bytes\n");
dprintf(" 0x08 - dump raw dwords\n");
dprintf(" 0x10 - do not skip invalid devices\n");
dprintf(" 0x20 - do not skip invalid functions\n");
dprintf(" 0x40 - dump Capabilities if found\n");
dprintf(" 0x80 - dump device specific on VendorID:8086\n");
dprintf(" 0x100 - dump config space\n");
return S_OK;
}