<XUnitAbstractionsVersion>2.0.3</XUnitAbstractionsVersion>
<MicrosoftDotNetRemoteExecutorVersion>7.0.0-beta.21453.2</MicrosoftDotNetRemoteExecutorVersion>
<cdbsosversion>10.0.18362</cdbsosversion>
+ <NewtonSoftJsonVersion>12.0.2</NewtonSoftJsonVersion>
</PropertyGroup>
</Project>
if ((rva + size) <= block.Length)
{
data = block.GetReader(rva, size).ReadBytes(size);
- ApplyRelocations(module, reader, rva, data);
+ ApplyRelocations(module, reader, (int)(address - module.ImageBase), data);
}
else
{
Debug.Assert(rva >= 0);
try
{
+#if TRACE_VERBOSE
Trace.TraceInformation($"ReadMemoryFromModule: address {address:X16} rva {rva:X16} size {bytesRequested:X8} in ELF or MachO file {module.FileName}");
+#endif
byte[] data = new byte[bytesRequested];
uint read = virtualAddressReader.Read(rva, data, 0, (uint)bytesRequested);
if (read == 0)
if (versionString != null)
{
int spaceIndex = versionString.IndexOf(' ');
+ if (spaceIndex < 0)
+ {
+ // It is probably a private build version that doesn't end with a space (no commit id after)
+ spaceIndex = versionString.Length;
+ }
if (spaceIndex > 0)
{
if (versionString[spaceIndex - 1] == '.')
protected void WriteLine(string message)
{
Console.Write(message + Environment.NewLine);
+ Console.CancellationToken.ThrowIfCancellationRequested();
}
/// <summary>
protected void WriteLine(string format, params object[] args)
{
Console.Write(string.Format(format, args) + Environment.NewLine);
+ Console.CancellationToken.ThrowIfCancellationRequested();
}
/// <summary>
protected void WriteLineWarning(string format, params object[] args)
{
Console.WriteWarning(string.Format(format, args) + Environment.NewLine);
+ Console.CancellationToken.ThrowIfCancellationRequested();
}
/// <summary>
protected void WriteLineError(string format, params object[] args)
{
Console.WriteError(string.Format(format, args) + Environment.NewLine);
+ Console.CancellationToken.ThrowIfCancellationRequested();
}
/// <summary>
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<PackageReference Include="Microsoft.SymbolStore" Version="$(MicrosoftSymbolStoreVersion)" />
</ItemGroup>
</Project>
var heap = Runtime.Heap;
var type = heap.GetObjectType(address);
- if (type == null)
+ if (type?.Name is null)
{
WriteLine($"{Address:x16} is not referencing an object...");
return;
private static bool IsTypeNameMatching(string typeName, string typeNameFilter)
{
- return typeName.IndexOf(typeNameFilter, StringComparison.OrdinalIgnoreCase) >= 0;
+ return typeName != null && typeName.IndexOf(typeNameFilter, StringComparison.OrdinalIgnoreCase) >= 0;
}
}
}
private void OnException(Exception ex, InvocationContext context)
{
+ if (ex is TargetInvocationException)
+ {
+ ex = ex.InnerException;
+ }
if (ex is NullReferenceException ||
ex is ArgumentException ||
ex is ArgumentNullException ||
ex is ArgumentOutOfRangeException ||
- ex is NotImplementedException) {
+ ex is NotImplementedException)
+ {
context.Console.Error.WriteLine(ex.ToString());
}
- else {
+ else
+ {
context.Console.Error.WriteLine(ex.Message);
}
Trace.TraceError(ex.ToString());
private void Invoke(MethodInfo methodInfo, InvocationContext context, Parser parser, IServiceProvider services)
{
- try
- {
- object instance = _factory(services);
- SetProperties(context, parser, services, instance);
+ object instance = _factory(services);
+ SetProperties(context, parser, services, instance);
- object[] arguments = BuildArguments(methodInfo, services);
- methodInfo.Invoke(instance, arguments);
- }
- catch (TargetInvocationException ex)
- {
- throw ex.InnerException;
- }
+ object[] arguments = BuildArguments(methodInfo, services);
+ methodInfo.Invoke(instance, arguments);
}
private void SetProperties(InvocationContext context, Parser parser, IServiceProvider services, object instance)
// This is a workaround for the Microsoft SDK docker images. Can fail when LoadLibrary uses libdl.so to load the SOS module.
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
- throw new DllNotFoundException("Problem loading SOS module. Try installing libc6-dev (apt-get install libc6-dev) to work around this problem.", ex);
+ throw new DllNotFoundException($"Problem loading SOS module from {sosPath}. Try installing libc6-dev (apt-get install libc6-dev) to work around this problem.", ex);
}
else
{
- throw;
+ throw new DllNotFoundException($"Problem loading SOS module from {sosPath}", ex);
}
}
if (_sosLibrary == IntPtr.Zero)
</ItemGroup>
<ItemGroup>
+ <PackageReference Include="NewtonSoft.Json" Version="$(NewtonSoftJsonVersion)" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="$(MicrosoftWin32PrimitivesVersion)" />
<PackageReference Include="cdb-sos" Version="$(cdbsosversion)" Condition="'$(OS)' == 'Windows_NT'" />
</ItemGroup>
// See the LICENSE file in the project root for more information.
using Microsoft.Diagnostics.TestHelpers;
+using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
{
information.OutputHelper = Output;
- // TODO: enable either when bpmd is fixed on Alpine or the bpmd tests are ifdef'ed out of the scripts for Alpine
if (testLive)
{
// Live
if (testDump)
{
+ string dumpName = null;
+
// Create and test dumps on OSX or Alpine only if the runtime is 6.0 or greater
if (!(OS.Kind == OSKind.OSX || SOSRunner.IsAlpine()) || information.TestConfiguration.RuntimeFrameworkVersionMajor > 5)
{
// Generate a crash dump.
if (information.TestConfiguration.DebuggeeDumpOutputRootDir() != null)
{
- await SOSRunner.CreateDump(information);
+ dumpName = await SOSRunner.CreateDump(information);
}
// Test against a crash dump.
}
}
}
+
+ // Test the crash report json file
+ if (dumpName != null && information.TestCrashReport)
+ {
+ TestCrashReport(dumpName, information);
+ }
+ }
+ }
+ }
+
+ private void TestCrashReport(string dumpName, SOSRunner.TestInformation information)
+ {
+ string crashReportPath = dumpName + ".crashreport.json";
+ TestRunner.OutputHelper outputHelper = TestRunner.ConfigureLogging(information.TestConfiguration, information.OutputHelper, information.TestName + ".CrashReportTest");
+ try
+ {
+ outputHelper.WriteLine("CrashReportTest for {0}", crashReportPath);
+ outputHelper.WriteLine("{");
+
+ AssertX.FileExists("CrashReport", crashReportPath, outputHelper.IndentedOutput);
+
+ dynamic crashReport = JsonConvert.DeserializeObject(File.ReadAllText(crashReportPath));
+ Assert.NotNull(crashReport);
+
+ dynamic payload = crashReport.payload;
+ Assert.NotNull(payload);
+ Version protocol_version = Version.Parse((string)payload.protocol_version);
+ Assert.True(protocol_version >= new Version("1.0.0"));
+ outputHelper.IndentedOutput.WriteLine($"protocol_version {protocol_version}");
+
+ string process_name = (string)payload.process_name;
+ Assert.NotNull(process_name);
+ outputHelper.IndentedOutput.WriteLine($"process_name {process_name}");
+
+ Assert.NotNull(payload.threads);
+ IEnumerable<dynamic> threads = payload.threads;
+ Assert.True(threads.Any());
+ outputHelper.IndentedOutput.WriteLine($"threads # {threads.Count()}");
+
+ if (OS.Kind == OSKind.OSX)
+ {
+ dynamic parameters = crashReport.parameters;
+ Assert.NotNull(parameters);
+ Assert.NotNull(parameters.ExceptionType);
+ Assert.NotNull(parameters.OSVersion);
+ Assert.Equal(parameters.SystemManufacturer, "apple");
}
}
+ catch (Exception ex)
+ {
+ // Log the exception
+ outputHelper.IndentedOutput.WriteLine(ex.ToString());
+ }
+ finally
+ {
+ outputHelper.WriteLine("}");
+ outputHelper.Dispose();
+ }
}
private async Task RunTest(TestConfiguration config, string debuggeeName, string scriptName, string testName = null, bool testLive = true, bool testDump = true, bool testTriage = false)
[SkippableTheory, MemberData(nameof(Configurations))]
public async Task GCPOHTests(TestConfiguration config)
{
- if (!config.IsNETCore || config.RuntimeFrameworkVersionMajor < 5)
+ if (config.IsDesktop || config.RuntimeFrameworkVersionMajor < 5)
{
throw new SkipTestException("This test validates POH behavior, which was introduced in .net 5");
}
TestConfiguration = config,
DebuggeeName = "Overflow",
// Generating the logging for overflow test causes so much output from createdump that it hangs/timesout the test run
- DumpDiagnostics = false,
+ DumpDiagnostics = config.IsNETCore && config.RuntimeFrameworkVersionMajor >= 6,
DumpGenerator = config.StackOverflowCreatesDump ? SOSRunner.DumpGenerator.CreateDump : SOSRunner.DumpGenerator.NativeDebugger
});
}
public class TestInformation
{
private string _testName;
+ private bool _testCrashReport = true;
+ private DumpGenerator _dumpGenerator = DumpGenerator.CreateDump;
public TestConfiguration TestConfiguration { get; set; }
public string DebuggeeArguments { get; set; }
- public DumpGenerator DumpGenerator { get; set; } = DumpGenerator.CreateDump;
+ public DumpGenerator DumpGenerator
+ {
+ get {
+ DumpGenerator dumpGeneration = _dumpGenerator;
+ if (dumpGeneration == DumpGenerator.CreateDump)
+ {
+ if (!TestConfiguration.CreateDumpExists || TestConfiguration.GenerateDumpWithLLDB() || TestConfiguration.GenerateDumpWithGDB())
+ {
+ dumpGeneration = DumpGenerator.NativeDebugger;
+ }
+ }
+ return dumpGeneration;
+ }
+ set { _dumpGenerator = value; }
+ }
public DumpType DumpType { get; set; } = DumpType.Heap;
public string DumpNameSuffix { get; set; }
+ public bool TestCrashReport
+ {
+ get { return _testCrashReport && DumpGenerator == DumpGenerator.CreateDump && OS.Kind != OSKind.Windows && TestConfiguration.RuntimeFrameworkVersionMajor >= 6; }
+ set { _testCrashReport = value; }
+ }
+
public bool IsValid()
{
return TestConfiguration != null && OutputHelper != null && DebuggeeName != null;
/// Run a debuggee and create a dump.
/// </summary>
/// <param name="information">test info</param>
- public static async Task CreateDump(TestInformation information)
+ /// <returns>full dump name</returns>
+ public static async Task<string> CreateDump(TestInformation information)
{
if (!information.IsValid()) {
throw new ArgumentException("Invalid TestInformation");
}
TestConfiguration config = information.TestConfiguration;
DumpGenerator dumpGeneration = information.DumpGenerator;
+ string dumpName = null;
Directory.CreateDirectory(config.DebuggeeDumpOutputRootDir());
- if (dumpGeneration == DumpGenerator.CreateDump)
- {
- if (!config.CreateDumpExists || config.GenerateDumpWithLLDB() || config.GenerateDumpWithGDB())
- {
- dumpGeneration = DumpGenerator.NativeDebugger;
- }
- }
-
if (dumpGeneration == DumpGenerator.NativeDebugger)
{
// Force the dump type to full for .NET Core 1.1 because the heap dumps are broken (can't read ThreadStore).
information.DumpType = DumpType.Full;
}
using SOSRunner runner = await SOSRunner.StartDebugger(information, DebuggerAction.GenerateDump);
+ dumpName = runner.ReplaceVariables("%DUMP_NAME%");
try
{
await runner.LoadSosExtension();
// source directory name has been lowercased by the build system.
DebuggeeConfiguration debuggeeConfig = await DebuggeeCompiler.Execute(config, information.DebuggeeName, outputHelper);
Dictionary<string, string> variables = GenerateVariables(information, debuggeeConfig, DebuggerAction.GenerateDump);
+ dumpName = ReplaceVariables(variables, "%DUMP_NAME%");
outputHelper.WriteLine("Starting {0}", information.TestName);
outputHelper.WriteLine("{");
// Run the debuggee with the createdump environment variables set to generate a coredump on unhandled exception
processRunner.
WithEnvironmentVariable("COMPlus_DbgEnableMiniDump", "1").
- WithEnvironmentVariable("COMPlus_DbgMiniDumpName", ReplaceVariables(variables, "%DUMP_NAME%"));
+ WithEnvironmentVariable("COMPlus_DbgMiniDumpName", dumpName);
if (information.DumpDiagnostics)
{
processRunner.WithEnvironmentVariable("COMPlus_CreateDumpDiagnostics", "1");
}
-
- // TODO: temporary hack to disable using createdump for triage type until the failures can be fixed
+ if (information.TestCrashReport)
+ {
+ processRunner.WithEnvironmentVariable("COMPlus_EnableCrashReport", "1");
+ }
+ // Windows createdump's triage MiniDumpWriteDump flags for .NET 5.0 are broken
+ // Disable testing triage dumps on 6.0 until the DAC signing issue is resolved - issue https://github.com/dotnet/diagnostics/issues/2542
+ // if (OS.Kind == OSKind.Windows && dumpType == DumpType.Triage && config.IsNETCore && config.RuntimeFrameworkVersionMajor < 6)
DumpType dumpType = information.DumpType;
if (OS.Kind == OSKind.Windows && dumpType == DumpType.Triage)
{
}
// Start dotnet-dump collect
+ DumpType dumpType = information.DumpType;
+ if (config.IsDesktop || config.RuntimeFrameworkVersionMajor < 6)
+ {
+ dumpType = DumpType.Full;
+ }
var dotnetDumpArguments = new StringBuilder();
dotnetDumpArguments.Append(config.DotNetDumpPath());
- dotnetDumpArguments.AppendFormat(" collect --process-id {0} --output %DUMP_NAME%", processRunner.ProcessId);
+ dotnetDumpArguments.AppendFormat($" collect --process-id {processRunner.ProcessId} --output {dumpName} --type {dumpType}");
if (information.DumpDiagnostics)
{
dotnetDumpArguments.Append(" --diag");
pipeServer?.Dispose();
}
}
+ return dumpName;
}
/// <summary>
{
commands.Add($"!SetHostRuntime {setHostRuntime}");
}
+ // Add the path to runtime so SOS can find DAC/DBI for triage dumps
+ if (_dumpType.HasValue && _dumpType == DumpType.Triage)
+ {
+ string runtimeSymbolsPath = _config.RuntimeSymbolsPath;
+ if (runtimeSymbolsPath != null)
+ {
+ commands.Add("!SetClrPath " + runtimeSymbolsPath);
+ }
+ }
break;
case NativeDebugger.Lldb:
commands.Add($"plugin load {sosPath}");
{
if (((Argument & DEBUG_STATUS_MASK) == DEBUG_STATUS_BREAK) && ((Argument & DEBUG_STATUS_INSIDE_WAIT) == 0))
{
- m_control->Output(DEBUG_OUTPUT_NORMAL, "ChangeEngineState\n");
-
// Flush the target when the debugger target breaks
Extensions::GetInstance()->FlushTarget();
}
{
return E_UNEXPECTED;
}
+ address = CONVERT_FROM_SIGN_EXTENDED(address);
#ifdef FEATURE_PAL
if (g_sos != nullptr)
{
{
return E_UNEXPECTED;
}
+ address = CONVERT_FROM_SIGN_EXTENDED(address);
#ifdef FEATURE_PAL
if (g_sos != nullptr)
{
#define LIMITED_METHOD_CONTRACT
+#define CONVERT_FROM_SIGN_EXTENDED(offset) ((ULONG_PTR)(offset))
+
// So we can use the PAL_TRY_NAKED family of macros without dependencies on utilcode.
inline void RestoreSOToleranceState() {}
_target.ServiceProvider.AddServiceFactory<SOSHost>(() => new SOSHost(_contextService.Services));
- // Automatically enable symbol server support
+ // Automatically enable symbol server support, default cache and search for symbols in the dump directory
_symbolService.AddSymbolServer(msdl: true, symweb: false, symbolServerPath: null, authToken: null, timeoutInMinutes: 0);
_symbolService.AddCachePath(_symbolService.DefaultSymbolCache);
+ _symbolService.AddDirectoryPath(Path.GetDirectoryName(dump_path.FullName));
// Run the commands from the dotnet-dump command line
if (command != null)
NativeMethods.MINIDUMP_TYPE.MiniDumpWithTokenInformation;
break;
case DumpTypeOption.Mini:
- dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo;
+ dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpNormal |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithDataSegs |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithThreadInfo;
+ break;
+ case DumpTypeOption.Triage:
+ dumpType = NativeMethods.MINIDUMP_TYPE.MiniDumpFilterTriage |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpIgnoreInaccessibleMemory |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithoutOptionalData |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithProcessThreadData |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpFilterModulePaths |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithUnloadedModules |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpFilterMemory |
+ NativeMethods.MINIDUMP_TYPE.MiniDumpWithHandleData;
break;
}
// stacks, exception information, handle information, and all memory except for mapped images.
Mini, // A small dump containing module lists, thread lists, exception information and all stacks.
+
+ Triage // A small dump containing module lists, thread lists, exception information, all stacks and PMI removed.
}
public Dumper()
case DumpTypeOption.Mini:
dumpType = DumpType.Normal;
break;
+ case DumpTypeOption.Triage:
+ dumpType = DumpType.Triage;
+ break;
}
// Send the command to the runtime to initiate the core dump
</ItemGroup>
<ItemGroup>
- <PackageReference Include="NewtonSoft.Json" Version="12.0.2" />
+ <PackageReference Include="NewtonSoft.Json" Version="$(NewtonSoftJsonVersion)" />
</ItemGroup>
</Project>