Skip to content

Commit

Permalink
Fix missing metadata in Linux core dumps.
Browse files Browse the repository at this point in the history
Issue #dotnet#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.
  • Loading branch information
mikem8361 committed Mar 1, 2019
1 parent 94eab76 commit 50d3731
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 14 deletions.
15 changes: 14 additions & 1 deletion src/SOS/SOS.Hosting/LLDBServicesWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,17 @@ private delegate bool GetLocalVariableNameDelegate(
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,
out uint dataSize);

#endregion

/// <summary>
Expand All @@ -94,6 +105,7 @@ struct SOSNetCoreCallbacks
public ResolveSequencePointDelegate ResolveSequencePointDelegate;
public GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
public GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
public GetMetadataLocatorDelegate GetMetadataLocatorDelegate;
}

static SOSNetCoreCallbacks s_callbacks = new SOSNetCoreCallbacks {
Expand All @@ -105,7 +117,8 @@ struct SOSNetCoreCallbacks
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";
Expand Down
32 changes: 32 additions & 0 deletions src/SOS/Strike/datatarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -250,6 +256,8 @@ DataTarget::Request(
return E_NOTIMPL;
}

// ICorDebugDataTarget4

HRESULT STDMETHODCALLTYPE
DataTarget::VirtualUnwind(
/* [in] */ DWORD threadId,
Expand All @@ -266,3 +274,27 @@ 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)
{
if (g_SOSNetCoreCallbacks.GetMetadataLocatorDelegate == nullptr)
{
return E_FAIL;
}
return g_SOSNetCoreCallbacks.GetMetadataLocatorDelegate(imagePath, imageTimestamp, imageSize, mvid, mdRva, flags, bufferSize, buffer, dataSize);
}


16 changes: 15 additions & 1 deletion src/SOS/Strike/datatarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -87,4 +87,18 @@ class DataTarget : public ICLRDataTarget, ICorDebugDataTarget4
/* [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);
};
21 changes: 11 additions & 10 deletions src/SOS/Strike/hostcoreclr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/SOS/Strike/hostcoreclr.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
15 changes: 14 additions & 1 deletion src/SOS/Strike/soshostservices.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 buffer,
unsigned int* dataSize
);

#define SOSNetCoreCallbacksVersion 2

struct SOSNetCoreCallbacks
{
Expand All @@ -47,6 +59,7 @@ struct SOSNetCoreCallbacks
ResolveSequencePointDelegate ResolveSequencePointDelegate;
GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
GetMetadataLocatorDelegate GetMetadataLocatorDelegate;
};

MIDL_INTERFACE("D13608FB-AD14-4B49-990A-80284F934C41")
Expand Down

0 comments on commit 50d3731

Please sign in to comment.