# Confirm that Windows SDK is present
if(NOT DEFINED CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION OR CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION STREQUAL "" )
- message(FATAL_ERROR "Windows SDK is required for the Arm32 build.")
+ message(FATAL_ERROR "Windows SDK is required for the Arm32 build.")
else()
- message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
+ message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
endif()
# Explicitly specify the assembler to be used for Arm32 compile
First try enabling the symbol downloading with `setsymbolserver -ms`. This is already enabled for `dotnet-dump analyze` and if SOS for lldb was installed with `dotnet-sos install`.
If that doesn't work, try using the `setclrpath <directory>` command with a directory that contains the matching version of the DAC module. This is useful for private runtimes or debug builds that haven't been published to our symbol servers.
+
+* If you receive this error message executing a SOS command:
+ ```
+ Failed to find runtime module (libcoreclr.so), 0x80004005
+ Extension commands need it in order to have something to do.
+ ClrStack failed
+ ```
+ The following could be the problem:
+ * The process or core dump hasn't loaded the .NET Core runtime yet.
+ * The coredump was loaded under lldb without specifying the host (i.e `dotnet`). `target modules list` doesn't display `libcoreclr.so` or `libcoreclr.dylib`. Start lldb with the host as the target program and the core file, for example `lldb --core coredump /usr/share/dotnet/dotnet`. In case you don't have the host available, `dotnet symbol` is will be able to download them.
+ * If a coredump was loaded under lldb, a host was specified, and `target modules list` displays the runtime module but you still get that message lldb needs the correct version of libcoreclr.so/dylib next to the coredump. You can use `dotnet-symbol --modules <coredump>` to download the needed binaries.
The dotnet-dump CLI global tool is way to collect and analyze Windows and Linux dumps all without any native debugger involved like lldb on Linux. This is important on platforms like Alpine Linux or Linux ARM32/ARM64 where a fully working lldb isn't available. The dotnet-dump tool will allow you to run SOS commands to analyze crashes and the GC, but it isn't a native debugger so things like displaying the native stack frames isn't supported.
-Currently not supported on macOS.
+The dotnet-dump tool is only supported on the same OS and architecture the dump was taken. Currently not supported on macOS.
## Installing dotnet-dump
## Using dotnet-dump
-The next step is to collect a dump. This can be skipped if a core dump has already been generated by the operating system or [createdump](https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy) on Linux.
+The next step is to collect a dump. This can be skipped if a core dump has already been generated by the operating system or [createdump](https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy) on Linux. The default dump type (--type option) is currently "full".
On Linux, the runtime version must be 3.0 or greater. On Windows, dotnet-dump collect will work with any version of the runtime.
ThreadInfo threadInfo = _threadService.GetThreadInfoFromIndex(unchecked((int)id));
AnalyzeContext.CurrentThreadId = threadInfo.ThreadId;
}
- catch (InvalidOperationException)
+ catch (DiagnosticsException)
{
return E_FAIL;
}
id = (uint)threadInfo.ThreadIndex;
return S_OK;
}
- catch (InvalidOperationException)
+ catch (DiagnosticsException)
{
}
}
IntPtr self,
ulong* offset)
{
- if (!AnalyzeContext.CurrentThreadId.HasValue)
- {
- return E_FAIL;
- }
- uint threadId = AnalyzeContext.CurrentThreadId.Value;
- try
+ if (AnalyzeContext.CurrentThreadId.HasValue)
{
- ulong teb = _threadService.GetThreadInfoFromId(threadId).ThreadTeb;
- Write(offset, teb);
- return S_OK;
- }
- catch (InvalidOperationException)
- {
- return E_FAIL;
+ uint threadId = AnalyzeContext.CurrentThreadId.Value;
+ try
+ {
+ ulong teb = _threadService.GetThreadInfoFromId(threadId).ThreadTeb;
+ Write(offset, teb);
+ return S_OK;
+ }
+ catch (DiagnosticsException)
+ {
+ }
}
+ Write(offset, 0);
+ return E_FAIL;
}
internal int GetInstructionOffset(
string name,
out uint index)
{
- if (_threadService.GetRegisterIndexByName(name, out int value)) {
+ if (!_threadService.GetRegisterIndexByName(name, out int value)) {
index = 0;
return E_INVALIDARG;
}
string register,
out ulong value)
{
- value = 0;
if (!_threadService.GetRegisterIndexByName(register, out int index)) {
+ value = 0;
return E_INVALIDARG;
}
return GetRegister(index, out value);
int index,
out ulong value)
{
- if (!AnalyzeContext.CurrentThreadId.HasValue)
+ if (AnalyzeContext.CurrentThreadId.HasValue)
{
- value = 0;
- return E_FAIL;
- }
- uint threadId = AnalyzeContext.CurrentThreadId.Value;
- if (!_threadService.GetRegisterValue(threadId, index, out value)) {
- return E_FAIL;
+ uint threadId = AnalyzeContext.CurrentThreadId.Value;
+ if (_threadService.GetRegisterValue(threadId, index, out value)) {
+ return S_OK;
+ }
}
- return S_OK;
+ value = 0;
+ return E_FAIL;
}
internal static bool IsCoreClrRuntimeModule(ModuleInfo module)
<LoadTriggers>
<TriggerSet>
<ModuleTrigger Name="coreclr.dll" />
+ </TriggerSet>
+ <TriggerSet>
<ModuleTrigger Name="libcoreclr.so" />
+ <OSTrigger Name="Linux" />
</TriggerSet>
</LoadTriggers>
<EngineCommands>
#endif // FEATURE_PAL
+extern bool g_dotnetDumpHost;
+
HRESULT
ExtQuery(PDEBUG_CLIENT client);
ExtOut("Failed to find runtime module (%s or %s or %s), 0x%08x\n", GetRuntimeDllName(IRuntime::Core), GetRuntimeDllName(IRuntime::WindowsDesktop), GetRuntimeDllName(IRuntime::UnixCore), Status);
#endif
ExtOut("Extension commands need it in order to have something to do.\n");
+ ExtOut("For more information see https://aka.ms/sos_faq\n");
}
inline void DACMessage(HRESULT Status)
{
ExtOut("Failed to load data access module, 0x%08x\n", Status);
-#ifndef FEATURE_PAL
- ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
- ExtOut(" 2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
- ExtOut(" in the version directory or on the symbol path\n");
- ExtOut(" 3) or, if you are debugging a dump file, verify that the file \n");
- ExtOut(" %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
- ExtOut(" 4) you are debugging on supported cross platform architecture as \n");
- ExtOut(" the dump file. For example, an ARM dump file must be debugged\n");
- ExtOut(" on an X86 or an ARM machine; an AMD64 dump file must be\n");
- ExtOut(" debugged on an AMD64 machine.\n");
- ExtOut("\n");
- ExtOut("You can also run the debugger command .cordll to control the debugger's\n");
- ExtOut("load of %s.dll. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
- ExtOut("If that succeeds, the SOS command should work on retry.\n");
- ExtOut("\n");
- ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
- ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
-#else // FEATURE_PAL
- if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+#ifdef FEATURE_PAL
+ if (true)
+#else
+ if (g_dotnetDumpHost)
+#endif
{
- ExtOut("You can run the debugger command 'setclrpath' to control the load of %s.\n", GetDacDllName());
- ExtOut("If that succeeds, the SOS command should work on retry.\n");
+ if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+ {
+ ExtOut("You can run the debugger command 'setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+ ExtOut("If that succeeds, the SOS command should work on retry.\n");
+ }
+ else
+ {
+ ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+ }
}
else
{
- ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+ ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
+ ExtOut(" 2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
+ ExtOut(" in the version directory or on the symbol path\n");
+ ExtOut(" 3) or, if you are debugging a dump file, verify that the file\n");
+ ExtOut(" %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
+ ExtOut(" 4) you are debugging on a platform and architecture that supports this\n");
+ ExtOut(" the dump file. For example, an ARM dump file must be debugged\n");
+ ExtOut(" on an X86 or an ARM machine; an AMD64 dump file must be\n");
+ ExtOut(" debugged on an AMD64 machine.\n");
+ ExtOut("\n");
+ ExtOut("You can run the command '!setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+ ExtOut("\n");
+ ExtOut("Or you can also run the debugger command .cordll to control the debugger's\n");
+ ExtOut("load of %s. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
+ ExtOut("If that succeeds, the SOS command should work on retry.\n");
+ ExtOut("\n");
+ ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
+ ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
}
-#endif // FEATURE_PAL
+ ExtOut("\n");
+ ExtOut("For more information see https://aka.ms/sos_faq\n");
}
HRESULT CheckEEDll();
#define IfFailRet(EXPR) do { Status = (EXPR); if(FAILED(Status)) { return (Status); } } while (0)
#endif
+bool g_dotnetDumpHost = false;
static bool g_hostingInitialized = false;
bool g_symbolStoreInitialized = false;
LPCSTR g_hostRuntimeDirectory = nullptr;
#endif
g_symbolStoreInitialized = symbolStoreEnabled;
g_hostingInitialized = true;
+ g_dotnetDumpHost = true;
return S_OK;
}
const bool hosted = (ThreadStore.fHostConfig & CLRTASKHOSTED) != 0;
table.ReInit(hosted ? 12 : 11, POINTERSIZE_HEX);
- table.SetWidths(10, 4, 4, 4, _max(9, POINTERSIZE_HEX),
- 8, 11, 1+POINTERSIZE_HEX*2, POINTERSIZE_HEX,
- 5, 3, POINTERSIZE_HEX);
+ table.SetWidths(10, 4, 4, 8, _max(9, POINTERSIZE_HEX), 8, 11, 1+POINTERSIZE_HEX*2, POINTERSIZE_HEX, 5, 3, POINTERSIZE_HEX);
table.SetColAlignment(0, AlignRight);
table.SetColAlignment(1, AlignRight);
STDMETHOD(CanUnloadNow(HMODULE hModule));
- //IUnknown methods:
- STDMETHOD(QueryInterface(
+ //IUnknown methods:
+ STDMETHOD(QueryInterface(
REFIID riid,
void **ppvObject));
- // Standard AddRef implementation
- STDMETHOD_(ULONG, AddRef());
+ // Standard AddRef implementation
+ STDMETHOD_(ULONG, AddRef());
- // Standard Release implementation.
- STDMETHOD_(ULONG, Release());
+ // Standard Release implementation.
+ STDMETHOD_(ULONG, Release());
DWORD targetImageFileMachine,
VS_FIXEDFILEINFO * pVersion);
- volatile LONG m_cRef;
+ volatile LONG m_cRef;
GUID m_skuId;
bool m_isWindowsTarget;
}
ppReg = &pRD->pCurrentContextPointers->R4;
-
+
return (OBJECTREF*)*(ppReg + regNum-4);
}
}
ppReg = &pRD->pCurrentContextPointers->X19;
-
+
return (OBJECTREF*)*(ppReg + regNum-19);
}
except:
pass
- logfile = os.path.join(logfiledir, command)
+ logfile = os.path.join(logfiledir, command)
cmd = (('%s -b ' % lldb) +
("-k \"script open('%s', 'a').close()\" " % fail_flag_lldb) +
/// Source line to locate.
///
/// @param[in] function
- /// Optional filter function. Addresses within this function will be
+ /// Optional filter function. Addresses within this function will be
/// added to the 'local' list. All others will be added to the 'extern'
/// list.
///
using EditLineCharType = char;
#endif
-#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */
+#ifdef EL_CLIENTDATA /* editline with wide support + wide char read function */
using EditLineGetCharType = wchar_t;
#else
using EditLineGetCharType = char;
using Microsoft.Diagnostics.DebugServices;
using Microsoft.Diagnostics.Repl;
+using System;
namespace Microsoft.Diagnostics.Tools.Dump
{
}
else
{
- threadId = AnalyzeContext.CurrentThreadId.Value;
+ if (AnalyzeContext.CurrentThreadId.HasValue)
+ {
+ threadId = AnalyzeContext.CurrentThreadId.Value;
+ }
+ else
+ {
+ throw new InvalidOperationException($"No current thread");
+ }
}
foreach (RegisterInfo register in ThreadService.Registers)
{
}
else
{
+ uint currentThreadId = AnalyzeContext.CurrentThreadId.GetValueOrDefault(uint.MaxValue);
foreach (ThreadInfo thread in ThreadService.EnumerateThreads())
{
- WriteLine("{0}{1} 0x{2:X4} ({2})", thread.ThreadId == AnalyzeContext.CurrentThreadId.Value ? "*" : " ", thread.ThreadIndex, thread.ThreadId);
+ WriteLine("{0}{1} 0x{2:X4} ({2})", thread.ThreadId == currentThreadId ? "*" : " ", thread.ThreadIndex, thread.ThreadId);
}
}
}
public:
- typedef void (*printfFtn)(const char* fmt, ...);
- printfFtn gcPrintf;
+ typedef void (*printfFtn)(const char* fmt, ...);
+ printfFtn gcPrintf;
UINT32 gcInfoVersion;
//-------------------------------------------------------------------------
protected: