diff options
Diffstat (limited to 'src/ToolBox/SOS/Strike/exts.cpp')
-rw-r--r-- | src/ToolBox/SOS/Strike/exts.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/src/ToolBox/SOS/Strike/exts.cpp b/src/ToolBox/SOS/Strike/exts.cpp new file mode 100644 index 0000000000..0b1f976cc2 --- /dev/null +++ b/src/ToolBox/SOS/Strike/exts.cpp @@ -0,0 +1,435 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ==++== +// + +// +// ==--== +#include "exts.h" +#include "disasm.h" +#ifndef FEATURE_PAL +#include "EventCallbacks.h" + +#define VER_PRODUCTVERSION_W (0x0100) + +// +// globals +// +EXT_API_VERSION ApiVersion = { (VER_PRODUCTVERSION_W >> 8), (VER_PRODUCTVERSION_W & 0xff), EXT_API_VERSION_NUMBER64, 0 }; +WINDBG_EXTENSION_APIS ExtensionApis; + +ULONG PageSize; + +OnUnloadTask *OnUnloadTask::s_pUnloadTaskList = NULL; + +// +// Valid for the lifetime of the debug session. +// + +ULONG TargetMachine; +BOOL Connected; +ULONG g_TargetClass; +DWORD_PTR g_filterHint = 0; + +PDEBUG_CLIENT g_ExtClient; +PDEBUG_DATA_SPACES2 g_ExtData2; +PDEBUG_SYMBOLS2 g_ExtSymbols2; +PDEBUG_ADVANCED3 g_ExtAdvanced3; +PDEBUG_CLIENT g_pCallbacksClient; + +#else + +DebugClient* g_DebugClient; +ILLDBServices* g_ExtServices; + +#endif // FEATURE_PAL + +IMachine* g_targetMachine = NULL; +BOOL g_bDacBroken = FALSE; + +PDEBUG_CONTROL2 g_ExtControl; +PDEBUG_DATA_SPACES g_ExtData; +PDEBUG_REGISTERS g_ExtRegisters; +PDEBUG_SYMBOLS g_ExtSymbols; +PDEBUG_SYSTEM_OBJECTS g_ExtSystem; + +#define SOS_ExtQueryFailGo(var, riid) \ + var = NULL; \ + if ((Status = client->QueryInterface(__uuidof(riid), \ + (void **)&var)) != S_OK) \ + { \ + goto Fail; \ + } + +// Queries for all debugger interfaces. +#ifndef FEATURE_PAL +extern "C" HRESULT +ExtQuery(PDEBUG_CLIENT client) +{ + g_ExtClient = client; +#else +extern "C" HRESULT +ExtQuery(ILLDBServices* services) +{ + g_ExtServices = services; + DebugClient* client = new DebugClient(services); + g_DebugClient = client; +#endif + HRESULT Status; + SOS_ExtQueryFailGo(g_ExtControl, IDebugControl2); + SOS_ExtQueryFailGo(g_ExtData, IDebugDataSpaces); + SOS_ExtQueryFailGo(g_ExtRegisters, IDebugRegisters); + SOS_ExtQueryFailGo(g_ExtSymbols, IDebugSymbols); + SOS_ExtQueryFailGo(g_ExtSystem, IDebugSystemObjects); +#ifndef FEATURE_PAL + SOS_ExtQueryFailGo(g_ExtData2, IDebugDataSpaces2); + SOS_ExtQueryFailGo(g_ExtSymbols2, IDebugSymbols2); + SOS_ExtQueryFailGo(g_ExtAdvanced3, IDebugAdvanced3); +#endif // FEATURE_PAL + return S_OK; + + Fail: + if (Status == E_OUTOFMEMORY) + ReportOOM(); + + ExtRelease(); + return Status; +} + +extern "C" HRESULT +ArchQuery(void) +{ + ULONG targetArchitecture; + IMachine* targetMachine = NULL; + + g_ExtControl->GetExecutingProcessorType(&targetArchitecture); + +#ifdef SOS_TARGET_AMD64 + if(targetArchitecture == IMAGE_FILE_MACHINE_AMD64) + { + targetMachine = AMD64Machine::GetInstance(); + } +#endif // SOS_TARGET_AMD64 +#ifdef SOS_TARGET_X86 + if (targetArchitecture == IMAGE_FILE_MACHINE_I386) + { + targetMachine = X86Machine::GetInstance(); + } +#endif // SOS_TARGET_X86 +#ifdef SOS_TARGET_ARM + if (targetArchitecture == IMAGE_FILE_MACHINE_ARMNT) + { + targetMachine = ARMMachine::GetInstance(); + } +#endif // SOS_TARGET_ARM +#ifdef SOS_TARGET_ARM64 + if (targetArchitecture == IMAGE_FILE_MACHINE_ARM64) + { + targetMachine = ARM64Machine::GetInstance(); + } +#endif // SOS_TARGET_ARM64 + + if (targetMachine == NULL) + { + g_targetMachine = NULL; + ExtErr("SOS does not support the current target architecture.\n"); + return E_FAIL; + } + + g_targetMachine = targetMachine; + return S_OK; +} + +// Cleans up all debugger interfaces. +void +ExtRelease(void) +{ + EXT_RELEASE(g_ExtControl); + EXT_RELEASE(g_ExtData); + EXT_RELEASE(g_ExtRegisters); + EXT_RELEASE(g_ExtSymbols); + EXT_RELEASE(g_ExtSystem); +#ifndef FEATURE_PAL + EXT_RELEASE(g_ExtData2); + EXT_RELEASE(g_ExtSymbols2); + EXT_RELEASE(g_ExtAdvanced3); + g_ExtClient = NULL; +#else + EXT_RELEASE(g_DebugClient); + g_ExtServices = NULL; +#endif // FEATURE_PAL +} + +#ifndef FEATURE_PAL + +BOOL IsMiniDumpFileNODAC(); +extern HMODULE g_hInstance; + +// This function throws an exception that can be caught by the debugger, +// instead of allowing the default CRT behavior of invoking Watson to failfast. +void __cdecl _SOS_invalid_parameter( + const WCHAR * expression, + const WCHAR * function, + const WCHAR * file, + unsigned int line, + uintptr_t pReserved +) +{ + ExtErr("\nSOS failure!\n"); + throw "SOS failure"; +} + +// Unregisters our windbg event callbacks and releases the client, event callback objects +void CleanupEventCallbacks() +{ + if(g_pCallbacksClient != NULL) + { + g_pCallbacksClient->Release(); + g_pCallbacksClient = NULL; + } +} + +bool g_Initialized = false; + +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 (g_Initialized) + { + return S_OK; + } + g_Initialized = true; + + 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; + } + + // Fixes the "Unable to read dynamic function table entries" error messages by disabling the WinDbg security + // feature that prevents the loading of unknown out of proc tack walkers. + DebugControl->Execute(DEBUG_OUTCTL_IGNORE, ".settings set EngineInitialization.VerifyFunctionTableCallbacks=false", + DEBUG_EXECUTE_NOT_LOGGED | DEBUG_EXECUTE_NO_REPEAT); + + ExtQuery(DebugClient); + if (IsMiniDumpFileNODAC()) + { + ExtOut ( + "----------------------------------------------------------------------------\n" + "The user dump currently examined is a minidump. Consequently, only a subset\n" + "of sos.dll functionality will be available. If needed, attaching to the live\n" + "process or debugging a full dump will allow access to sos.dll's full feature\n" + "set.\n" + "To create a full user dump use the command: .dump /ma <filename>\n" + "----------------------------------------------------------------------------\n"); + } + ExtRelease(); + + OnUnloadTask::Register(CleanupEventCallbacks); + g_pCallbacksClient = DebugClient; + EventCallbacks* pCallbacksObj = new EventCallbacks(DebugClient); + IDebugEventCallbacks* pCallbacks = NULL; + pCallbacksObj->QueryInterface(__uuidof(IDebugEventCallbacks), (void**)&pCallbacks); + pCallbacksObj->Release(); + + if(FAILED(Hr = g_pCallbacksClient->SetEventCallbacks(pCallbacks))) + { + ExtOut ("SOS: Failed to register callback events\n"); + pCallbacks->Release(); + return Hr; + } + pCallbacks->Release(); + +#ifndef _ARM_ + // Make sure we do not tear down the debugger when a security function fails + // Since we link statically against CRT this will only affect the SOS module. + _set_invalid_parameter_handler(_SOS_invalid_parameter); +#endif + + DebugControl->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 page size and PAE enable flag + // + + if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugDataSpaces), + (void **)&DebugDataSpaces)) == S_OK) + { + if ((Hr = DebugDataSpaces->ReadDebuggerData( + DEBUG_DATA_MmPageSize, &Page, + sizeof(Page), NULL)) == S_OK) + { + PageSize = (ULONG)(ULONG_PTR)Page; + } + + 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(&g_TargetClass, &Qualifier)) == S_OK) + { + } + + DebugControl->Release(); + } + + DebugClient->Release(); + } + } + + + if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE) + { + Connected = FALSE; + PageSize = 0; + TargetMachine = 0; + } + + return; +} + +extern "C" +void +CALLBACK +DebugExtensionUninitialize(void) +{ + // execute all registered cleanup tasks + OnUnloadTask::Run(); + return; +} + + +BOOL 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; +} + +BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = (HMODULE) hInstance; + } + return true; +} + +#else // FEATURE_PAL + +HRESULT +DebugClient::QueryInterface( + REFIID InterfaceId, + PVOID* Interface + ) +{ + if (InterfaceId == __uuidof(IUnknown) || + InterfaceId == __uuidof(IDebugControl2) || + InterfaceId == __uuidof(IDebugControl4) || + InterfaceId == __uuidof(IDebugDataSpaces) || + InterfaceId == __uuidof(IDebugSymbols) || + InterfaceId == __uuidof(IDebugSystemObjects) || + InterfaceId == __uuidof(IDebugRegisters)) + { + *Interface = this; + AddRef(); + return S_OK; + } + else + { + *Interface = NULL; + return E_NOINTERFACE; + } +} + +ULONG +DebugClient::AddRef() +{ + LONG ref = InterlockedIncrement(&m_ref); + return ref; +} + +ULONG +DebugClient::Release() +{ + LONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + { + m_lldbservices->Release(); + delete this; + } + return ref; +} + +#endif // FEATURE_PAL |