diff options
Diffstat (limited to 'src/ToolBox/SOS/Strike/dllsext.cpp')
-rw-r--r-- | src/ToolBox/SOS/Strike/dllsext.cpp | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/src/ToolBox/SOS/Strike/dllsext.cpp b/src/ToolBox/SOS/Strike/dllsext.cpp new file mode 100644 index 0000000000..74c382e769 --- /dev/null +++ b/src/ToolBox/SOS/Strike/dllsext.cpp @@ -0,0 +1,279 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// ==++== +// + +// +// ==--== +#include "strike.h" +#include "data.h" +#include "util.h" +#include "platformspecific.h" + +typedef struct _PRIVATE_LDR_DATA_TABLE_ENTRY { + LIST_ENTRY InLoadOrderLinks; + LIST_ENTRY InMemoryOrderLinks; + LIST_ENTRY InInitializationOrderLinks; + PVOID DllBase; + PVOID EntryPoint; + ULONG SizeOfImage; + UNICODE_STRING FullDllName; + UNICODE_STRING BaseDllName; + ULONG Flags; + USHORT LoadCount; + USHORT TlsIndex; + union _LDR_DATA_TABLE_ENTRY_UNION1 { //DevDiv LKG RC Changes: Added union name to avoid warning C4408 + LIST_ENTRY HashLinks; + struct _LDR_DATA_TABLE_ENTRY_STRUCT1 { //DevDiv LKG RC Changes: Added struct name to avoid warning C4201 + PVOID SectionPointer; + ULONG CheckSum; + }; + }; + union _LDR_DATA_TABLE_ENTRY_UNION2 { //DevDiv LKG RC Changes: Added union name to avoid warning C4408 + struct _LDR_DATA_TABLE_ENTRY_STRUCT2 { //DevDiv LKG RC Changes: Added struct name to avoid warning C4201 + ULONG TimeDateStamp; + }; + struct _LDR_DATA_TABLE_ENTRY_STRUCT3 { //DevDiv LKG RC Changes: Added struct name to avoid warning C4201 + PVOID LoadedImports; + }; + }; + struct _ACTIVATION_CONTEXT * EntryPointActivationContext; + + PVOID PatchInformation; + +} PRIVATE_LDR_DATA_TABLE_ENTRY, *PRIVATE_PLDR_DATA_TABLE_ENTRY; + + +#ifndef FEATURE_PAL +static void DllsNameFromPeb( + ULONG_PTR addrContaining, + __out_ecount (MAX_PATH) WCHAR *dllName + ) +{ + ULONG64 ProcessPeb; + g_ExtSystem->GetCurrentProcessPeb (&ProcessPeb); + + ULONG64 pLdrEntry; + ULONG64 PebLdrAddress; + ULONG64 Next; + ULONG64 OrderModuleListStart; + + // + // Capture PebLdrData + // + + static ULONG Offset_Ldr = -1; + if (Offset_Ldr == -1) + { + ULONG TypeId; + ULONG64 NtDllBase; + if (SUCCEEDED(g_ExtSymbols->GetModuleByModuleName ("ntdll",0,NULL, + &NtDllBase)) + && SUCCEEDED(g_ExtSymbols->GetTypeId (NtDllBase, "PEB", &TypeId))) + { + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "Ldr", &Offset_Ldr))) + Offset_Ldr = -1; + } + } + // We can not get it from PDB. Use the fixed one. + if (Offset_Ldr == -1) + Offset_Ldr = offsetof (DT_PEB, Ldr); + + DT_PEB peb = {0}; + if (FAILED(g_ExtData->ReadVirtual(ProcessPeb+Offset_Ldr, &peb.Ldr, + sizeof(peb.Ldr), NULL))) + { + ExtOut ( " Unable to read PEB_LDR_DATA address at %p\n", (ULONG64)(ProcessPeb+Offset_Ldr)); + return; + } + + PebLdrAddress = (ULONG64)peb.Ldr; + + // + // Walk through the loaded module table and display all ldr data + // + + static ULONG Offset_ModuleList = -1; + if (Offset_ModuleList == -1) + { + ULONG TypeId; + ULONG64 NtDllBase; + if (SUCCEEDED(g_ExtSymbols->GetModuleByModuleName ("ntdll",0,NULL, + &NtDllBase)) + && SUCCEEDED(g_ExtSymbols->GetTypeId (NtDllBase, "PEB_LDR_DATA", + &TypeId))) + { + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "InMemoryOrderModuleList", + &Offset_ModuleList))) + Offset_ModuleList = -1; + } + } + // We can not get it from PDB. Use the fixed one. + if (Offset_ModuleList == -1) + Offset_ModuleList = offsetof (DT_PEB_LDR_DATA, InMemoryOrderModuleList); + + OrderModuleListStart = PebLdrAddress + Offset_ModuleList; + DT_PEB_LDR_DATA Ldr = {0}; + if (FAILED(g_ExtData->ReadVirtual(OrderModuleListStart, + &Ldr.InMemoryOrderModuleList, + sizeof(Ldr.InMemoryOrderModuleList), + NULL))) + { + ExtOut ( " Unable to read InMemoryOrderModuleList address at %p\n", OrderModuleListStart); + return; + } + Next = (ULONG64)Ldr.InMemoryOrderModuleList.Flink; + + static ULONG Offset_OrderLinks = -1; + static ULONG Offset_FullDllName = -1; + static ULONG Offset_DllBase = -1; + static ULONG Offset_SizeOfImage = -1; + if (Offset_OrderLinks == -1) + { + ULONG TypeId; + ULONG64 NtDllBase; + if (SUCCEEDED(g_ExtSymbols->GetModuleByModuleName ("ntdll",0,NULL, + &NtDllBase)) + && SUCCEEDED(g_ExtSymbols->GetTypeId (NtDllBase, "LDR_DATA_TABLE_ENTRY", + &TypeId))) + { + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "InMemoryOrderLinks", + &Offset_OrderLinks))) + Offset_OrderLinks = -1; + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "FullDllName", + &Offset_FullDllName))) + Offset_FullDllName = -1; + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "DllBase", + &Offset_DllBase))) + Offset_DllBase = -1; + if (FAILED (g_ExtSymbols->GetFieldOffset(NtDllBase, TypeId, + "SizeOfImage", + &Offset_SizeOfImage))) + Offset_SizeOfImage = -1; + } + } + + // We can not get it from PDB. Use the fixed one. + if (Offset_OrderLinks == -1 || Offset_OrderLinks == 0) + { + Offset_OrderLinks = offsetof (PRIVATE_LDR_DATA_TABLE_ENTRY, + InMemoryOrderLinks); + Offset_FullDllName = offsetof (PRIVATE_LDR_DATA_TABLE_ENTRY, + FullDllName); + Offset_DllBase = offsetof (PRIVATE_LDR_DATA_TABLE_ENTRY, + DllBase); + Offset_SizeOfImage = offsetof (PRIVATE_LDR_DATA_TABLE_ENTRY, + SizeOfImage); + } + + _UNICODE_STRING FullDllName; + __try { + while (Next != OrderModuleListStart) { + if (IsInterrupt()) + return; + + pLdrEntry = Next - Offset_OrderLinks; + + // + // Capture LdrEntry + // + if (FAILED(g_ExtData->ReadVirtual(pLdrEntry + Offset_FullDllName, + &FullDllName, + sizeof(FullDllName), + NULL))) + { + ExtOut ( " Unable to read FullDllName address at %p\n", + pLdrEntry + Offset_FullDllName); + return; + } + ZeroMemory( dllName, MAX_PATH * sizeof (WCHAR) ); + if (FAILED(g_ExtData->ReadVirtual((ULONG64)FullDllName.Buffer, + dllName, + MAX_PATH < FullDllName.Length ? MAX_PATH : FullDllName.Length, + NULL))) + { +#if 0 + ExtOut ( " Unable to read FullDllName.Buffer address at %p\n", + (ULONG64)FullDllName.Buffer); +#endif + ZeroMemory( dllName, MAX_PATH * sizeof (WCHAR) ); + } + + // + // Dump the ldr entry data + // (dump all the entries if no containing address specified) + // + PRIVATE_LDR_DATA_TABLE_ENTRY LdrEntry = {0}; + if (SUCCEEDED(g_ExtData->ReadVirtual(pLdrEntry + Offset_DllBase, + &LdrEntry.DllBase, + sizeof(LdrEntry.DllBase), + NULL)) + && + SUCCEEDED(g_ExtData->ReadVirtual(pLdrEntry + Offset_SizeOfImage, + &LdrEntry.SizeOfImage, + sizeof(LdrEntry.SizeOfImage), + NULL)) + ) + { + if (((ULONG_PTR)LdrEntry.DllBase <= addrContaining) && + (addrContaining <= (ULONG_PTR)LdrEntry.DllBase + (ULONG_PTR)LdrEntry.SizeOfImage)) + break; + } + + ZeroMemory( dllName, MAX_PATH * sizeof (WCHAR) ); + if (FAILED(g_ExtData->ReadVirtual(pLdrEntry + Offset_OrderLinks, + &LdrEntry.InMemoryOrderLinks, + sizeof(LdrEntry.InMemoryOrderLinks), + NULL))) + break; + + Next = (ULONG64)LdrEntry.InMemoryOrderLinks.Flink; + } + } __except (EXCEPTION_EXECUTE_HANDLER) + { + ExtOut ("exception during reading PEB\n"); + return; + } +} +#endif + +HRESULT +DllsName( + ULONG_PTR addrContaining, + __out_ecount (MAX_PATH) WCHAR *dllName + ) +{ + dllName[0] = L'\0'; + + ULONG Index; + ULONG64 base; + HRESULT hr = g_ExtSymbols->GetModuleByOffset(addrContaining, 0, &Index, &base); + if (FAILED(hr)) + return hr; + + CHAR name[MAX_PATH+1]; + ULONG length; + + hr = g_ExtSymbols->GetModuleNames(Index,base,name,MAX_PATH,&length,NULL,0,NULL,NULL,0,NULL); + + if (SUCCEEDED(hr)) + { + MultiByteToWideChar (CP_ACP,0,name,-1,dllName,MAX_PATH); + } + +#ifndef FEATURE_PAL + if (wcsrchr (dllName, '\\') == NULL) { + DllsNameFromPeb (addrContaining,dllName); + } +#endif + + return hr; +} |