Fix missing metadata in Linux core dumps. (#229)
authorMike McLaughlin <mikem@microsoft.com>
Wed, 1 May 2019 21:54:52 +0000 (14:54 -0700)
committerGitHub <noreply@github.com>
Wed, 1 May 2019 21:54:52 +0000 (14:54 -0700)
* Fix missing metadata in Linux core dumps.

Issue #https://github.com/dotnet/diagnostics/issues/56

Both Windows and Linux minidumps don't save all the assemblies' metadata which can cause
stack traces to display !Unknown. On Windows most debuggers like Windbg and VS can load
the module from file for this kind of dumps. On Linux lldb/SOS doesn't load the native
modules and really doesn't know anything about the managed assemblies.

Add metadata callback to datatarget and it's implementation in SOS.NETCore.

Add IsMetadataMemory() and the metadata region list. This is because lldb on core dumps
returns 0's on missing metadata memory reads instead of an error.

16 files changed:
src/SOS/SOS.Hosting/LLDBServicesWrapper.cs
src/SOS/SOS.NETCore/MetadataHelper.cs [new file with mode: 0644]
src/SOS/SOS.NETCore/SymbolReader.cs
src/SOS/Strike/datatarget.cpp
src/SOS/Strike/datatarget.h
src/SOS/Strike/disasmARM64.cpp
src/SOS/Strike/dllsext.cpp
src/SOS/Strike/gchist.cpp
src/SOS/Strike/hostcoreclr.cpp
src/SOS/Strike/hostcoreclr.h
src/SOS/Strike/sos.cpp
src/SOS/Strike/soshostservices.h
src/SOS/Strike/strike.cpp
src/SOS/Strike/util.cpp
src/SOS/Strike/util.h
src/SOS/lldbplugin/services.cpp

index a733335d58da92a651cff03e3ff24f1527f40268..7704a9baa9d3b9fb1dd67c51e3a35d19e356fa3a 100644 (file)
@@ -77,6 +77,17 @@ namespace SOS
             int localIndex,
             out IntPtr localVarName);
 
+        private delegate int GetMetadataLocatorDelegate(
+            [MarshalAs(UnmanagedType.LPWStr)] string imagePath,
+            uint imageTimestamp,
+            uint imageSize,
+            [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] mvid,
+            uint mdRva,
+            uint flags,
+            uint bufferSize,
+            IntPtr buffer,
+            IntPtr dataSize);
+
         #endregion
 
         /// <summary>
@@ -94,6 +105,7 @@ namespace SOS
             public ResolveSequencePointDelegate ResolveSequencePointDelegate;
             public GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
             public GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
+            public GetMetadataLocatorDelegate GetMetadataLocatorDelegate;
         }
 
         static SOSNetCoreCallbacks s_callbacks = new SOSNetCoreCallbacks {
@@ -105,7 +117,8 @@ namespace SOS
             DisposeDelegate  = SymbolReader.Dispose,
             ResolveSequencePointDelegate = SymbolReader.ResolveSequencePoint,
             GetLineByILOffsetDelegate = SymbolReader.GetLineByILOffset,
-            GetLocalVariableNameDelegate  = SymbolReader.GetLocalVariableName,
+            GetLocalVariableNameDelegate = SymbolReader.GetLocalVariableName,
+            GetMetadataLocatorDelegate = MetadataHelper.GetMetadataLocator
         };
 
         static readonly string s_coreclrModuleName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "coreclr" : "libcoreclr.so";
diff --git a/src/SOS/SOS.NETCore/MetadataHelper.cs b/src/SOS/SOS.NETCore/MetadataHelper.cs
new file mode 100644 (file)
index 0000000..cb99152
--- /dev/null
@@ -0,0 +1,70 @@
+// 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.
+
+using Microsoft.SymbolStore;
+using Microsoft.SymbolStore.KeyGenerators;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Reflection.Metadata.Ecma335;
+using System.Reflection.PortableExecutable;
+using System.Runtime.InteropServices;
+
+namespace SOS
+{
+    public class MetadataHelper
+    {
+        public static int GetMetadataLocator(
+            [MarshalAs(UnmanagedType.LPWStr)] string imagePath,
+            uint imageTimestamp,
+            uint imageSize, 
+            [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)] byte[] mvid, 
+            uint mdRva,
+            uint flags,
+            uint bufferSize,
+            IntPtr pMetadata,
+            IntPtr pMetadataSize)
+        {
+            int hr = unchecked((int)0x80004005);
+            int dataSize = 0;
+
+            Debug.Assert(pMetadata != IntPtr.Zero);
+
+            Stream peStream = null;
+            if (imagePath != null && File.Exists(imagePath))
+            {
+                peStream = SymbolReader.TryOpenFile(imagePath);
+            }
+            else if (SymbolReader.IsSymbolStoreEnabled())
+            {
+                SymbolStoreKey key = PEFileKeyGenerator.GetKey(imagePath, imageTimestamp, imageSize);
+                peStream = SymbolReader.GetSymbolStoreFile(key)?.Stream;
+            }
+            if (peStream != null)
+            {
+                using (var peReader = new PEReader(peStream, PEStreamOptions.Default))
+                {
+                    if (peReader.HasMetadata)
+                    {
+                        PEMemoryBlock metadataInfo = peReader.GetMetadata();
+                        unsafe
+                        {
+                            int size = Math.Min((int)bufferSize, metadataInfo.Length);
+                            Marshal.Copy(metadataInfo.GetContent().ToArray(), 0, pMetadata, size);
+                        }
+                        dataSize = metadataInfo.Length;
+                        hr = 0;
+                    }
+                }
+            }
+
+            if (pMetadataSize != IntPtr.Zero)
+            {
+                Marshal.WriteInt32(pMetadataSize, dataSize);
+            }
+            return hr;
+        }
+    }
+}
index 1c128fc7aef4cdf1b329e80fc8098869d0058f28..f80a4febbaeb9bab8082fc2356d51a47495af91f 100644 (file)
@@ -244,7 +244,7 @@ namespace SOS
         /// <param name="readMemory">read memory callback delegate</param>
         public static void LoadNativeSymbols(SymbolFileCallback callback, IntPtr parameter, string tempDirectory, string moduleFilePath, ulong address, int size, ReadMemoryDelegate readMemory)
         {
-            if (s_symbolStore != null)
+            if (IsSymbolStoreEnabled())
             {
                 Debug.Assert(s_tracer != null);
                 Stream stream = new TargetStream(address, size, readMemory);
@@ -874,13 +874,12 @@ namespace SOS
 
                 if (pdbStream == null)
                 {
-                    if (s_symbolStore == null)
+                    if (IsSymbolStoreEnabled())
                     {
-                        return null;
+                        Debug.Assert(codeViewEntry.MinorVersion == ImageDebugDirectory.PortablePDBMinorVersion);
+                        SymbolStoreKey key = PortablePDBFileKeyGenerator.GetKey(pdbPath, data.Guid);
+                        pdbStream = GetSymbolStoreFile(key)?.Stream;
                     }
-                    Debug.Assert(codeViewEntry.MinorVersion == ImageDebugDirectory.PortablePDBMinorVersion);
-                    SymbolStoreKey key = PortablePDBFileKeyGenerator.GetKey(pdbPath, data.Guid);
-                    pdbStream = GetSymbolStoreFile(key)?.Stream;
                     if (pdbStream == null)
                     {
                         return null;
@@ -938,12 +937,20 @@ namespace SOS
             return result;
         }
 
+        /// <summary>
+        /// Returns true if symbol download has been enabled.
+        /// </summary>
+        internal static bool IsSymbolStoreEnabled()
+        {
+            return s_symbolStore != null;
+        }
+
         /// <summary>
         /// Attempts to download/retrieve from cache the key.
         /// </summary>
         /// <param name="key">index of the file to retrieve</param>
         /// <returns>stream or null</returns>
-        private static SymbolStoreFile GetSymbolStoreFile(SymbolStoreKey key)
+        internal static SymbolStoreFile GetSymbolStoreFile(SymbolStoreKey key)
         {
             try
             {
@@ -1104,7 +1111,7 @@ namespace SOS
         /// </summary>
         /// <param name="path">file path</param>
         /// <returns>stream or null if doesn't exist or error</returns>
-        private static Stream TryOpenFile(string path)
+        internal static Stream TryOpenFile(string path)
         {
             if (!File.Exists(path))
             {
index 049faa7fd0abe5359785dad3120ac2b386687ca9..54334011487b80586d3447a8ab42d2d74945dc89 100644 (file)
@@ -37,6 +37,12 @@ DataTarget::QueryInterface(
         AddRef();
         return S_OK;
     }
+    else if (InterfaceId == IID_ICLRMetadataLocator)
+    {
+        *Interface = (ICLRMetadataLocator*)this;
+        AddRef();
+        return S_OK;
+    }
     else
     {
         *Interface = NULL;
@@ -129,6 +135,19 @@ DataTarget::ReadVirtual(
     {
         return E_UNEXPECTED;
     }
+#ifdef FEATURE_PAL
+    if (g_sos != nullptr)
+    {
+        // LLDB synthesizes memory (returns 0's) for missing pages (in this case the missing metadata 
+        // pages) in core dumps. This functions creates a list of the metadata regions and returns true
+        // if the read would be in the metadata of a loaded assembly. This allows an error to be returned 
+        // instead of 0's so the DAC will call the GetMetadataLocator datatarget callback.
+        if (IsMetadataMemory(address, request))
+        {
+            return E_ACCESSDENIED;
+        }
+    }
+#endif
     return g_ExtData->ReadVirtual(address, (PVOID)buffer, request, (PULONG)done);
 }
 
@@ -250,6 +269,8 @@ DataTarget::Request(
     return E_NOTIMPL;
 }
 
+// ICorDebugDataTarget4
+
 HRESULT STDMETHODCALLTYPE 
 DataTarget::VirtualUnwind(
     /* [in] */ DWORD threadId,
@@ -266,3 +287,30 @@ DataTarget::VirtualUnwind(
     return E_NOTIMPL;
 #endif
 }
+
+// ICLRMetadataLocator
+
+HRESULT STDMETHODCALLTYPE
+DataTarget::GetMetadata(
+    /* [in] */ LPCWSTR imagePath,
+    /* [in] */ ULONG32 imageTimestamp,
+    /* [in] */ ULONG32 imageSize,
+    /* [in] */ GUID* mvid,
+    /* [in] */ ULONG32 mdRva,
+    /* [in] */ ULONG32 flags,
+    /* [in] */ ULONG32 bufferSize,
+    /* [out, size_is(bufferSize), length_is(*dataSize)] */
+    BYTE* buffer,
+    /* [out] */ ULONG32* dataSize)
+{
+    HRESULT hr = InitializeHosting();
+    if (FAILED(hr))
+    {
+        return hr;
+    }
+    InitializeSymbolStore();
+    _ASSERTE(g_SOSNetCoreCallbacks.GetMetadataLocatorDelegate != nullptr);
+    return g_SOSNetCoreCallbacks.GetMetadataLocatorDelegate(imagePath, imageTimestamp, imageSize, mvid, mdRva, flags, bufferSize, buffer, dataSize);
+}
+
+
index 0293bc668b22fe7686d2f09d26a62b15793e1340..f3ec9d14e8bdeae4ad05e632ae59604cca85dc79 100644 (file)
@@ -2,7 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-class DataTarget : public ICLRDataTarget, ICorDebugDataTarget4
+class DataTarget : public ICLRDataTarget, ICorDebugDataTarget4, ICLRMetadataLocator
 {
 private:
     LONG m_ref;                         // Reference count.
@@ -87,4 +87,18 @@ public:
         /* [in] */ DWORD threadId,
         /* [in] */ ULONG32 contextSize,
         /* [in, out, size_is(contextSize)] */ PBYTE context);
+
+    // ICLRMetadataLocator
+
+    virtual HRESULT STDMETHODCALLTYPE GetMetadata(
+        /* [in] */ LPCWSTR imagePath,
+        /* [in] */ ULONG32 imageTimestamp,
+        /* [in] */ ULONG32 imageSize,
+        /* [in] */ GUID* mvid,
+        /* [in] */ ULONG32 mdRva,
+        /* [in] */ ULONG32 flags,
+        /* [in] */ ULONG32 bufferSize,
+        /* [out, size_is(bufferSize), length_is(*dataSize)] */
+        BYTE* buffer,
+        /* [out] */ ULONG32* dataSize);
 };
\ No newline at end of file
index 6a19fc9377e8659301fcf4ca8ec1692ea8164fb8..7f8accdcab6a83645258fa459db38bc02cd4a68c 100644 (file)
@@ -294,7 +294,7 @@ void ARM64Machine::Unassembly (
             // Print out real code address in place of the copy address
             //
 
-                       ExtOut("%08x`%08x ", (ULONG)(InstrAddr >> 32), (ULONG)InstrAddr);
+            ExtOut("%08x`%08x ", (ULONG)(InstrAddr >> 32), (ULONG)InstrAddr);
 
             ptr = line;
             NextTerm (ptr);
index 757a04c91fc564cf4764063761a309bfa6d1ab2f..390044f5896eeeeb59d050b4b055ce5c2152d14e 100644 (file)
@@ -50,7 +50,7 @@ typedef struct _PRIVATE_LDR_DATA_TABLE_ENTRY {
 static void DllsNameFromPeb(
     ULONG_PTR addrContaining,
     __out_ecount (MAX_LONGPATH) WCHAR *dllName
-       )
+    )
 {
     ULONG64 ProcessPeb;
     g_ExtSystem->GetCurrentProcessPeb (&ProcessPeb);
index e2ca1a92438df433b31056daacc02ff214873b82..8fa4062a6c9f76e04809cab859778b29883cb4e5 100644 (file)
@@ -56,7 +56,7 @@
 
 #ifndef _ASSERTE
 #ifdef _DEBUG
-#define _ASSERTE(expr)                 \
+#define _ASSERTE(expr) \
         do { if (!(expr) ) { ExtOut(#expr); DebugBreak(); } } while (0)
 #else // _DEBUG
 #define _ASSERTE(expr)
index 462134846463542b4b2693b639b0605b598104b3..d8ee2412e65e05a611f43214ccce6641645a8437 100644 (file)
@@ -66,7 +66,7 @@ static void AddFilesFromDirectoryToTpaList(const char* directory, std::string& t
     std::set<std::string> addedAssemblies;
 
     // Don't add this file to the list because we don't want to the one from the hosting runtime
-    addedAssemblies.insert(SymbolReaderDllName);
+    addedAssemblies.insert(SOSManagedDllName);
 
     // Walk the directory for each extension separately so that we first get files with .ni.dll extension,
     // then files with .dll extension, etc.
@@ -679,15 +679,16 @@ HRESULT InitializeHosting()
         return Status;
     }
 
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "InitializeSymbolStore", (void **)&g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "DisplaySymbolStore", (void **)&g_SOSNetCoreCallbacks.DisplaySymbolStoreDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "DisableSymbolStore", (void **)&g_SOSNetCoreCallbacks.DisableSymbolStoreDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "LoadNativeSymbols", (void **)&g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "LoadSymbolsForModule", (void **)&g_SOSNetCoreCallbacks.LoadSymbolsForModuleDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "Dispose", (void **)&g_SOSNetCoreCallbacks.DisposeDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "ResolveSequencePoint", (void **)&g_SOSNetCoreCallbacks.ResolveSequencePointDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetLocalVariableName", (void **)&g_SOSNetCoreCallbacks.GetLocalVariableNameDelegate));
-    IfFailRet(createDelegate(hostHandle, domainId, SymbolReaderDllName, SymbolReaderClassName, "GetLineByILOffset", (void **)&g_SOSNetCoreCallbacks.GetLineByILOffsetDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "InitializeSymbolStore", (void **)&g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "DisplaySymbolStore", (void **)&g_SOSNetCoreCallbacks.DisplaySymbolStoreDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "DisableSymbolStore", (void **)&g_SOSNetCoreCallbacks.DisableSymbolStoreDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "LoadNativeSymbols", (void **)&g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "LoadSymbolsForModule", (void **)&g_SOSNetCoreCallbacks.LoadSymbolsForModuleDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "Dispose", (void **)&g_SOSNetCoreCallbacks.DisposeDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "ResolveSequencePoint", (void **)&g_SOSNetCoreCallbacks.ResolveSequencePointDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "GetLocalVariableName", (void **)&g_SOSNetCoreCallbacks.GetLocalVariableNameDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, SymbolReaderClassName, "GetLineByILOffset", (void **)&g_SOSNetCoreCallbacks.GetLineByILOffsetDelegate));
+    IfFailRet(createDelegate(hostHandle, domainId, SOSManagedDllName, MetadataHelperClassName, "GetMetadataLocator", (void **)&g_SOSNetCoreCallbacks.GetMetadataLocatorDelegate));
 
     g_hostingInitialized = true;
     return Status;
@@ -767,6 +768,33 @@ HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char*
     return S_OK;
 }
 
+/**********************************************************************\
+ * Setup and initialize the symbol server support using the .sympath
+\**********************************************************************/
+void InitializeSymbolStore()
+{
+    _ASSERTE(g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr);
+
+#ifndef FEATURE_PAL
+    if (!g_symbolStoreInitialized)
+    {
+        g_symbolStoreInitialized = true;
+
+        ArrayHolder<char> symbolPath = new char[MAX_LONGPATH];
+        if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(symbolPath, MAX_LONGPATH, nullptr)))
+        {
+            if (strlen(symbolPath) > 0)
+            {
+                if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, nullptr, nullptr, symbolPath))
+                {
+                    ExtErr("Windows symbol path parsing FAILED\n");
+                }
+            }
+        }
+    }
+#endif
+}
+
 /**********************************************************************\
  * Enumerate the native modules and attempt to download the symbols
  * for them. Depends on the lldb callback to enumerate modules. Not
@@ -979,28 +1007,9 @@ HRESULT SymbolReader::LoadSymbolsForPortablePDB(__in_z WCHAR* pModuleName, ___in
     HRESULT Status = S_OK;
 
     IfFailRet(InitializeHosting());
+    InitializeSymbolStore();
 
     _ASSERTE(g_SOSNetCoreCallbacks.LoadSymbolsForModuleDelegate != nullptr);
-    _ASSERTE(g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate != nullptr);
-
-#ifndef FEATURE_PAL
-    if (!g_symbolStoreInitialized)
-    {
-        g_symbolStoreInitialized = true;
-
-        ArrayHolder<char> symbolPath = new char[MAX_LONGPATH];
-        if (SUCCEEDED(g_ExtSymbols->GetSymbolPath(symbolPath, MAX_LONGPATH, nullptr)))
-        {
-            if (strlen(symbolPath) > 0)
-            {
-                if (!g_SOSNetCoreCallbacks.InitializeSymbolStoreDelegate(false, false, false, nullptr, nullptr, symbolPath))
-                {
-                    ExtErr("Windows symbol path parsing FAILED\n");
-                }
-            }
-        }
-    }
-#endif
 
     // The module name needs to be null for in-memory PE's.
     ArrayHolder<char> szModuleName = nullptr;
index 88ce27abd8f23649ae3452b1b98b5fa9c402e576..13c04b072cfbf1027ccf85181a238bc0e13aea6f 100644 (file)
@@ -12,8 +12,9 @@
 
 #include <soshostservices.h>
 
-static const char *SymbolReaderDllName = "SOS.NETCore";
+static const char *SOSManagedDllName = "SOS.NETCore";
 static const char *SymbolReaderClassName = "SOS.SymbolReader";
+static const char *MetadataHelperClassName = "SOS.MetadataHelper";
 
 extern HMODULE g_hInstance;
 extern LPCSTR g_hostRuntimeDirectory;
@@ -24,6 +25,7 @@ extern LPCSTR GetDbiFilePath();
 extern BOOL IsHostingInitialized();
 extern HRESULT InitializeHosting();
 extern HRESULT InitializeSymbolStore(BOOL logging, BOOL msdl, BOOL symweb, const char* symbolServer, const char* cacheDirectory);
+extern void InitializeSymbolStore();
 extern HRESULT LoadNativeSymbols(bool runtimeOnly = false);
 extern void DisplaySymbolStore();
 extern void DisableSymbolStore();
index 4aacc2a2e774ccbebb4189e909776ef0238311cf..2a160f9d369fbb6222ab8f3979b5678c99b82fc8 100644 (file)
@@ -171,7 +171,7 @@ namespace sos
     {
         TADDR mt = GetMT();
         MethodTableInfo* info = g_special_mtCache.Lookup((DWORD_PTR)mt);
-        if (!info->IsInitialized())    
+        if (!info->IsInitialized())
         {
             // this is the first time we see this method table, so we need to get the information
             // from the target
index 619a2e49a73d570251a1c9ed3388d4b4f947709f..d16c71cf3fa653ff93449baf9473ac983687f04d 100644 (file)
@@ -34,7 +34,19 @@ typedef  BOOL (*ResolveSequencePointDelegate)(PVOID, const char*, unsigned int,
 typedef  BOOL (*GetLocalVariableNameDelegate)(PVOID, int, int, BSTR*);
 typedef  BOOL (*GetLineByILOffsetDelegate)(PVOID, mdMethodDef, ULONG64, ULONG *, BSTR*);
 
-#define SOSNetCoreCallbacksVersion 1
+typedef  BOOL (*GetMetadataLocatorDelegate)(
+    LPCWSTR imagePath,
+    unsigned int imageTimestamp,
+    unsigned int imageSize,
+    GUID* mvid,
+    unsigned int mdRva,
+    unsigned int flags,
+    unsigned int bufferSize,
+    PVOID pMetadata,
+    unsigned int* pMetadataSize
+);
+
+#define SOSNetCoreCallbacksVersion 2
 
 struct SOSNetCoreCallbacks
 {
@@ -47,6 +59,7 @@ struct SOSNetCoreCallbacks
     ResolveSequencePointDelegate ResolveSequencePointDelegate;
     GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
     GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
+    GetMetadataLocatorDelegate GetMetadataLocatorDelegate;
 };
 
 MIDL_INTERFACE("D13608FB-AD14-4B49-990A-80284F934C41")
index 43bc0eeb9b4434bb8f4144b920e9b60e7bfc0259..c9e72d3e3369d75b1615c542ddb16fcf5442551a 100644 (file)
@@ -13757,6 +13757,9 @@ DECLARE_API( SOSFlush )
     INIT_API();
 
     g_clrData->Flush();
+#ifdef FEATURE_PAL
+    FlushMetadataRegions();
+#endif
     
     return Status;
 }   // DECLARE_API( SOSFlush )
index 13aacac11d45da9360041fcd411fa245412bbbc0..dbe4b12b2999ac24975201663fd2695c9f8bdf7b 100644 (file)
@@ -6197,3 +6197,127 @@ HRESULT InternalFrameManager::PrintCurrentInternalFrame()
 
     return S_OK;
 }
+
+#ifdef FEATURE_PAL
+
+struct MemoryRegion 
+{
+private:
+    uint64_t m_startAddress;
+    uint64_t m_endAddress;
+
+public:
+    MemoryRegion(uint64_t start, uint64_t end) : 
+        m_startAddress(start),
+        m_endAddress(end)
+    {
+    }
+
+    // copy constructor
+    MemoryRegion(const MemoryRegion& region) : 
+        m_startAddress(region.m_startAddress),
+        m_endAddress(region.m_endAddress)
+    {
+    }
+
+    uint64_t StartAddress() const { return m_startAddress; }
+    uint64_t EndAddress() const { return m_endAddress; }
+    uint64_t Size() const { return m_endAddress - m_startAddress; }
+
+    bool operator<(const MemoryRegion& rhs) const
+    {
+        return (m_startAddress < rhs.m_startAddress) && (m_endAddress <= rhs.m_startAddress);
+    }
+
+    // Returns true if "rhs" is wholly contained in this one
+    bool Contains(const MemoryRegion& rhs) const
+    {
+        return (m_startAddress <= rhs.m_startAddress) && (m_endAddress >= rhs.m_endAddress);
+    }
+};
+
+std::set<MemoryRegion> g_metadataRegions;
+bool g_metadataRegionsPopulated = false;
+
+void FlushMetadataRegions()
+{
+    g_metadataRegionsPopulated = false;
+}
+
+//-------------------------------------------------------------------------------
+// Lifted from "..\md\inc\mdfileformat.h"
+#define STORAGE_MAGIC_SIG   0x424A5342  // BSJB
+struct STORAGESIGNATURE
+{
+    ULONG       lSignature;             // "Magic" signature.
+    USHORT      iMajorVer;              // Major file version.
+    USHORT      iMinorVer;              // Minor file version.
+    ULONG       iExtraData;             // Offset to next structure of information
+    ULONG       iVersionString;         // Length of version string
+};
+
+void PopulateMetadataRegions()
+{
+    g_metadataRegions.clear();
+
+    // Only populate the metadata regions if core dump
+    if (IsDumpFile())
+    {
+        int numModule;
+        ArrayHolder<DWORD_PTR> moduleList = ModuleFromName(NULL, &numModule);
+        if (moduleList != nullptr)
+        {
+            for (int i = 0; i < numModule; i++)
+            {
+                DacpModuleData moduleData;
+                if (SUCCEEDED(moduleData.Request(g_sos, moduleList[i])))
+                {
+                    if (moduleData.metadataStart != 0)
+                    {
+                        bool add = false;
+                        STORAGESIGNATURE header;
+                        if (SUCCEEDED(g_ExtData->ReadVirtual(moduleData.metadataStart, (PVOID)&header, sizeof(header), NULL)))
+                        {
+                            add = header.lSignature != STORAGE_MAGIC_SIG;
+                        }
+                        else {
+                            add = true;
+                        }
+                        if (add)
+                        {
+                            MemoryRegion region(moduleData.metadataStart, moduleData.metadataStart + moduleData.metadataSize);
+                            g_metadataRegions.insert(region);
+                        }
+#ifdef METADATA_REGION_LOGGING
+                        ArrayHolder<WCHAR> name = new WCHAR[MAX_LONGPATH];
+                        name[0] = '\0';
+                        if (moduleData.File != 0)
+                        {
+                            g_sos->GetPEFileName(moduleData.File, MAX_LONGPATH, name.GetPtr(), NULL);
+                        }
+                        ExtOut("%c%016x %016x %016x %S\n", add ? '*' : ' ', moduleData.metadataStart, moduleData.metadataStart + moduleData.metadataSize, moduleData.metadataSize, name.GetPtr());
+#endif // METADATA_REGION_LOGGING
+                    }
+                }
+            }
+        }
+    }
+}
+
+bool IsMetadataMemory(CLRDATA_ADDRESS address, ULONG32 size)
+{
+    if (!g_metadataRegionsPopulated)
+    {
+        g_metadataRegionsPopulated = true;
+        PopulateMetadataRegions();
+    }
+    MemoryRegion region(address, address + size);
+    const auto& found = g_metadataRegions.find(region);
+    if (found != g_metadataRegions.end())
+    {
+        return found->Contains(region);
+    }
+    return false;
+}
+
+#endif // FEATURE_PAL
\ No newline at end of file
index 625a02298ccef5e4339ff3c787a95a0c95f398f8..4677d694208f246ec9ece319cb4817e14bdd861e 100644 (file)
@@ -1852,6 +1852,11 @@ BOOL IsObjectArray (DacpObjectData *pData);
 BOOL IsDerivedFrom(CLRDATA_ADDRESS mtObj, __in_z LPCWSTR baseString);
 BOOL TryGetMethodDescriptorForDelegate(CLRDATA_ADDRESS delegateAddr, CLRDATA_ADDRESS* pMD);
 
+#ifdef FEATURE_PAL
+void FlushMetadataRegions();
+bool IsMetadataMemory(CLRDATA_ADDRESS address, ULONG32 size);
+#endif
+
 /* Returns a list of all modules in the process.
  * Params:
  *      name - The name of the module you would like.  If mName is NULL the all modules are returned.
@@ -2896,7 +2901,7 @@ private:
                 if (curr_next)
                     curr_next->Prev = Prev;
             }
-        }      
+        }
     };
 
 public:
index 668b69473932d83610b21441c5057c5b5d5a36d6..22eb1cda53263a74747228d69d01ff770602062e 100644 (file)
@@ -420,6 +420,17 @@ LLDBServices::GetDebuggeeType(
 {
     *debugClass = DEBUG_CLASS_USER_WINDOWS; 
     *qualifier = 0;
+
+    lldb::SBProcess process = GetCurrentProcess();
+    if (process.IsValid())
+    {
+        const char* pluginName = process.GetPluginName();
+        if ((strcmp(pluginName, "elf-core") == 0) || (strcmp(pluginName, "mach-o-core") == 0))
+        {
+            *qualifier = DEBUG_DUMP_FULL;
+        }
+    }
+
     return S_OK;
 }