|
|
/*++
Copyright (c) 1993-2000 Microsoft Corporation
Module Name:
kdexts.cxx
Abstract:
This file contains the generic routines and initialization code for the kernel debugger extensions dll.
Author:
Wesley Witt (wesw) 26-Aug-1993
Environment:
User Mode
--*/
#include "precomp.hxx"
//
// globals
//
HINSTANCE ghDllInst; WINDBG_EXTENSION_APIS64 ExtensionApis; BOOL gbVerbose = FALSE;
DBGKD_GET_VERSION64 KernelVersionPacket;
ULONG64 EXPRLastDump = 0;
//
// Valid for the lifetime of the debug session.
//
ULONG PageSize; ULONG PageShift; ULONG64 PaeEnabled; ULONG TargetMachine; ULONG TargetClass; ULONG PlatformId = -1; ULONG MajorVer = 0; ULONG MinorVer = 0; ULONG SrvPack = 0; ULONG BuildNo = 0; BOOL NewPool = FALSE; ULONG PoolBlockShift;
BOOL Connected = FALSE; BOOL Remote = FALSE; CHAR RemoteID[MAX_PATH];
ModuleParameters GDIKM_Module = { 0, DEBUG_ANY_ID, "win32k", "sys" }; ModuleParameters GDIUM_Module = { 0, DEBUG_ANY_ID, "gdi32", "dll" }; ModuleParameters Type_Module;
HRESULT SymbolInit(PDEBUG_CLIENT);
BOOLEAN WINAPI DllMain( HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved ) { switch (fdwReason) { case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
case DLL_PROCESS_DETACH: break;
case DLL_PROCESS_ATTACH: DbgPrint("DllMain: DLL_PROCESS_ATTACH: hInstance = %lx => ghDllInit(%lx)\n", hInstDll, ghDllInst); ghDllInst = hInstDll; break; }
return TRUE; }
extern "C" HRESULT CALLBACK DebugExtensionSetClient( LPCSTR RemoteArgs ) { if (RemoteArgs != NULL) { Remote = TRUE; strncpy(RemoteID, RemoteArgs, sizeof(RemoteID)); } else { Remote = FALSE; }
return S_OK; }
HRESULT GetDebugClient( PDEBUG_CLIENT *pClient ) { HRESULT Hr = S_FALSE; PDEBUG_CLIENT Client;
if (pClient == NULL) { return S_FALSE; }
*pClient = NULL;
if (Remote) { Hr = DebugConnect(RemoteID, __uuidof(IDebugClient), (void **)&Client); if (Hr == S_OK) { Hr = Client->ConnectSession(DEBUG_CONNECT_SESSION_NO_VERSION | DEBUG_CONNECT_SESSION_NO_ANNOUNCE, 0); if (Hr != S_OK) { Client->Release(); } } } else { Hr = DebugCreate(__uuidof(IDebugClient), (void **)&Client); }
if (Hr == S_OK) { *pClient = Client; }
return Hr; }
void GetLabIdFromBuildString( PSTR BuildString, PULONG pLabId ) { PCHAR pstr;
*pLabId = 0; _strlwr(BuildString); pstr = strstr(BuildString, "lab"); if (pstr) { sscanf(pstr+3, "%ld", pLabId); } }
//PDEBUG_EXTENSION_INITIALIZE
extern "C" HRESULT CALLBACK DebugExtensionInitialize( PULONG Version, PULONG Flags ) { IDebugClient *DebugClient; PDEBUG_CONTROL DebugControl; HRESULT Hr;
DbgPrint("DebugExtensionInitialize called.\n");
*Version = DEBUG_EXTENSION_VERSION(1, 0); *Flags = 0; if ((Hr = GetDebugClient(&DebugClient)) != S_OK) { return Hr; }
if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl), (void **)&DebugControl)) != S_OK) { DebugClient->Release(); return Hr; }
ExtensionApis.nSize = sizeof(ExtensionApis); if ((Hr = DebugControl->GetWindbgExtensionApis64(&ExtensionApis)) != S_OK) { GetRemoteWindbgExtApis(&ExtensionApis); }
Hr = SetEventCallbacks(DebugClient); DbgPrint("EventCallbacks set for 0x%p returned %s.\n", DebugClient, pszHRESULT(Hr));
ViewerInit();
DebugControl->Release(); DebugClient->Release(); return S_OK; }
//PDEBUG_EXTENSION_NOTIFY
extern "C" void CALLBACK DebugExtensionNotify( ULONG Notify, ULONG64 Argument ) { switch (Notify) { case DEBUG_NOTIFY_SESSION_ACTIVE: DbgPrint("DebugExtensionNotify recieved DEBUG_NOTIFY_SESSION_ACTIVE\n"); break; case DEBUG_NOTIFY_SESSION_INACTIVE: DbgPrint("DebugExtensionNotify recieved DEBUG_NOTIFY_SESSION_INACTIVE\n"); break; case DEBUG_NOTIFY_SESSION_ACCESSIBLE: DbgPrint("DebugExtensionNotify recieved DEBUG_NOTIFY_SESSION_ACCESSIBLE\n"); break; case DEBUG_NOTIFY_SESSION_INACCESSIBLE: DbgPrint("DebugExtensionNotify recieved DEBUG_NOTIFY_SESSION_INACCESSIBLE\n"); break; default: DbgPrint("DebugExtensionNotify recieved unknown notification %u\n", Notify); break; }
//
// The first time we actually connect to a target, get the architecture
//
if ((Notify == DEBUG_NOTIFY_SESSION_ACCESSIBLE) && (!Connected)) { IDebugClient *DebugClient; PDEBUG_CONTROL DebugControl; PDEBUG_DATA_SPACES DebugDataSpaces; HRESULT Hr; ULONG64 Page;
if ((Hr = GetDebugClient(&DebugClient)) == S_OK) { //
// Get the page size and PAE enable flag
//
if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugDataSpaces), (void **)&DebugDataSpaces)) == S_OK) { if ((Hr = DebugDataSpaces->ReadDebuggerData( DEBUG_DATA_PaeEnabled, &PaeEnabled, sizeof(PaeEnabled), NULL)) == S_OK) { if ((Hr = DebugDataSpaces->ReadDebuggerData( DEBUG_DATA_MmPageSize, &Page, sizeof(Page), NULL)) == S_OK) { PageSize = (ULONG)(ULONG_PTR)Page; for (PageShift = 0; Page >>= 1; PageShift++) ; } }
DebugDataSpaces->Release(); }
//
// 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(&TargetClass, &Qualifier)) != S_OK) { TargetClass = DEBUG_CLASS_UNINITIALIZED; }
ULONG StringUsed; CHAR BuildString[100]; if ((Hr = DebugControl->GetSystemVersion(&PlatformId, &MajorVer, &MinorVer, NULL, 0, NULL, &SrvPack, BuildString, sizeof(BuildString), &StringUsed)) == S_OK) { PCHAR pstr; ULONG LabId = 0; BuildNo = MinorVer;
_strlwr(BuildString); pstr = strstr(BuildString, "lab"); if (pstr != NULL) { sscanf(pstr+3, "%ld", &LabId); }
NewPool = ((BuildNo > 2407) || (LabId == 1 && BuildNo >= 2402)); PoolBlockShift = NewPool ? POOL_BLOCK_SHIFT_LAB1_2402 : POOL_BLOCK_SHIFT_OLD; } else { PlatformId = -1; MajorVer = 0; MinorVer = 0; SrvPack = 0; BuildNo = 0;
NewPool = FALSE; PoolBlockShift = PageShift - 8; }
DebugControl->Release(); }
// Try to initialize symbols only if the event monitor
// hasn't fully registered. This indicates that the
// extension is just being loaded as opposed to being
// loaded at system boot and reconnect (when GDI modules
// won't even be loaded yet).
if (UniqueTargetState == INVALID_UNIQUE_STATE) { SymbolInit(DebugClient); }
DebugClient->Release(); } }
if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE) { Connected = FALSE; TargetMachine = 0; PlatformId = -1; MajorVer = 0; MinorVer = 0; SrvPack = 0; }
return; }
//PDEBUG_EXTENSION_UNINITIALIZE
extern "C" void CALLBACK DebugExtensionUninitialize(void) { DbgPrint("DebugExtensionUninitialize called.\n");
SessionExit(); HmgrExit(); ViewerExit(); BasicTypesExit();
ReleaseEventCallbacks(NULL);
ExtRelease(TRUE);
return; }
BOOLEAN IsCheckedBuild( PBOOLEAN Checked ) { if (MajorVer == 0) return FALSE;
//
// 0xC for checked, 0xF for free.
//
*Checked = ((MajorVer & 0xFF) == 0xc) ; return TRUE; }
HRESULT GetModuleParameters( PDEBUG_CLIENT Client, ModuleParameters *Module, BOOL TryReload ) { HRESULT hr; PDEBUG_SYMBOLS Symbols; OutputControl OutCtl(Client);
if (Client == NULL) return E_POINTER;
if ((hr = Client->QueryInterface(__uuidof(IDebugSymbols), (void **)&Symbols)) != S_OK) { return hr; }
hr = Symbols->GetModuleByModuleName(Module->Name, 0, &Module->Index, &Module->Base);
Client->FlushCallbacks();
if (hr != S_OK && TryReload) { CHAR ReloadArgs[MAX_PATH];
OutCtl.OutVerb("GetModuleByModuleName returned %s.\n", pszHRESULT(hr));
sprintf(ReloadArgs, (Module->Base != 0) ? "%s.%s=0x%I64x" : "%s.%s", Module->Name, Module->Ext, Module->Base);
OutCtl.OutWarn("Trying %s reload.\n", ReloadArgs);
hr = Symbols->Reload(ReloadArgs);
Client->FlushCallbacks();
if (hr == S_OK) { hr = Symbols->GetModuleByModuleName(Module->Name, 0, &Module->Index, &Module->Base); OutCtl.OutVerb("Module %s @ 0x%p; HRESULT %s\n", Module->Name, Module->Base, pszHRESULT(hr));
Client->FlushCallbacks(); } else { OutCtl.OutWarn("Reload(\"%s\") returned %s\n", ReloadArgs, pszHRESULT(hr)); } } else { OutCtl.OutVerb("Module %s @ 0x%p.\n", Module->Name, Module->Base); }
if (hr == S_OK) { hr = Symbols->GetModuleParameters(1, NULL, Module->Index, &Module->DbgModParams);
OutCtl.OutVerb("SymbolType for %s: ", Module->Name); switch (Module->DbgModParams.SymbolType) { case DEBUG_SYMTYPE_NONE: OutCtl.OutVerb("NONE"); break; case DEBUG_SYMTYPE_COFF: OutCtl.OutVerb("COFF"); break; case DEBUG_SYMTYPE_CODEVIEW: OutCtl.OutVerb("CODEVIEW"); break; case DEBUG_SYMTYPE_PDB: OutCtl.OutVerb("PDB"); break; case DEBUG_SYMTYPE_EXPORT: OutCtl.OutVerb("EXPORT"); break; case DEBUG_SYMTYPE_DEFERRED: OutCtl.OutVerb("DEFERRED"); break; case DEBUG_SYMTYPE_SYM: OutCtl.OutVerb("SYM"); break; case DEBUG_SYMTYPE_DIA: OutCtl.OutVerb("DIA"); break; default: OutCtl.OutVerb("unknown %ld", Module->DbgModParams.SymbolType); break; } OutCtl.OutVerb(" (HRESULT %s)\n", pszHRESULT(hr));
Client->FlushCallbacks(); }
Symbols->Release();
return hr; }
HRESULT SymbolLoad( PDEBUG_CLIENT Client ) { HRESULT hr; ULONG Class; ULONG Qualifier;
if (TargetClass != DEBUG_CLASS_USER_WINDOWS) { GetModuleParameters(Client, &GDIUM_Module, FALSE);
if ((hr = GetModuleParameters(Client, &GDIKM_Module, TRUE)) == S_OK && GDIKM_Module.Base != 0) { Type_Module = GDIKM_Module; } } else { hr = GetModuleParameters(Client, &GDIUM_Module, TRUE); }
if (hr == S_OK) { gbSymbolsNotLoaded = FALSE; }
if (Type_Module.Base == 0) { Type_Module = GDIUM_Module; }
DbgPrint("Using %s for type module.\n", Type_Module.Name);
return hr; }
HRESULT SymbolInit(PDEBUG_CLIENT Client) { HRESULT hr;
GDIKM_Module.Base = 0; GDIUM_Module.Base = 0; Type_Module.Base = 0;
hr = SymbolLoad(Client);
BasicTypesInit(Client); HmgrInit(Client); SessionInit(Client);
return hr; }
HRESULT InitAPI(PDEBUG_CLIENT Client, PCSTR ExtName) { static BOOL SecondaryCall = FALSE;
HRESULT hr;
hr = EventCallbacksReady(Client);
if (hr != S_OK) { OutputControl OutCtl(Client);
OutCtl.OutWarn(" Warning: Event callbacks have not been registered.\n");
if (SecondaryCall) { OutCtl.OutWarn(" All extension caching is disabled.\n"); } else { OutCtl.OutWarn(" If %s is the first extension used, use .load or !load in the future.\n" " Caching is disabled for this use of !%s.\n", ExtName, ExtName); } }
SecondaryCall = TRUE;
if (gbSymbolsNotLoaded) { SymbolInit(Client); }
return hr; }
DECLARE_API(reinit) { HRESULT hr; hr = SymbolInit(Client); return hr; }
DECLARE_API(verbose) { INIT_API();
gbVerbose = !gbVerbose; ExtOut(" GDIKDX Verbose mode is now %s.\n", gbVerbose ? "ON" : "OFF");
EXIT_API(S_OK); }
|