Skip to content

Commit

Permalink
Implement SOS Hosting for Windows (dotnet-dump)
Browse files Browse the repository at this point in the history
Defined all the dbgeng delegates needed to implement the subset of the
IDebugClient and related interfaces to host SOS on Windows. Also modified
various parts of the native SOS to be able to be hosted.

Changed the Ext* and DML* output functions to formatted the output before
sending it to IDebugControl::OutputVaList. There is no way to create a
cdecl reverse pinvoke. The "args" OutputVaList is ignored when hosted.

Changed from IDebugAdvanced3 to IDebugAdvanced.

Cleanup (remove globals, etc.) exts.cpp DebugExtensionNotify code to make sure
none of the globals initialized by the original code are used because these
DebugExtensionInitialize, DebugExtensionNotify and DebugExtensionUninitialize
are only called when sos is running under cdb/windbg.

Simplified ProvideLibraryInternal (used by clrstack -i only) to work on a hosted
sos. It originally was using dbgeng functions that can't be supported.

Added 2.1 version of DumpTieredNativeCodeAddressInfo (not used yet).

Enable dotnet-dump testing on Windows.

Delete useless createdump commmand.

Remove spurious error message in GetCoreClrDirectory.

Update to latest symstore: 1.0.0-dev-64131-02.

Update dummy native projects to 2019.
  • Loading branch information
mikem8361 committed Jun 20, 2019
1 parent ed1f99c commit b0660e4
Show file tree
Hide file tree
Showing 40 changed files with 4,593 additions and 1,510 deletions.
12 changes: 0 additions & 12 deletions eng/Tools.props

This file was deleted.

3 changes: 1 addition & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<MicrosoftWin32PrimitivesVersion>4.3.0</MicrosoftWin32PrimitivesVersion>

<!-- Other libs -->
<MicrosoftSymbolStoreVersion>1.0.0-dev-64016-01</MicrosoftSymbolStoreVersion>
<MicrosoftSymbolStoreVersion>1.0.0-dev-64131-02</MicrosoftSymbolStoreVersion>
<MicrosoftDiagnosticsRuntimeVersion>1.0.5</MicrosoftDiagnosticsRuntimeVersion>

<MicrosoftDiagnosticsTracingTraceEventVersion>2.0.41</MicrosoftDiagnosticsTracingTraceEventVersion>
Expand All @@ -41,7 +41,6 @@
https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json;
https://dotnet.myget.org/F/symstore/api/v3/index.json;
https://dotnet.myget.org/F/dotnet-core/api/v3/index.json;
https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json;
https://dotnet.myget.org/F/system-commandline/api/v3/index.json
</RestoreSources>
</PropertyGroup>
Expand Down
131 changes: 77 additions & 54 deletions src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// --------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.CommandLine;
using System.CommandLine.Binding;
Expand All @@ -28,8 +29,9 @@ public class CommandProcessor
/// Create an instance of the command processor;
/// </summary>
/// <param name="console">console instance to use for commands</param>
/// <param name="assemblies">The list of assemblies to look for commands</param>
public CommandProcessor(IConsole console, IEnumerable<Assembly> assemblies)
/// <param name="assemblies">Optional list of assemblies to look for commands</param>
/// <param name="types">Optional list of types to look for commands</param>
public CommandProcessor(IConsole console, IEnumerable<Assembly> assemblies = null, IEnumerable<Type> types = null)
{
Debug.Assert(console != null);
Debug.Assert(assemblies != null);
Expand All @@ -43,7 +45,12 @@ public CommandProcessor(IConsole console, IEnumerable<Assembly> assemblies)
.UseSuggestDirective()
.UseParseErrorReporting()
.UseExceptionHandler();
BuildCommands(rootBuilder, assemblies);
if (assemblies != null) {
BuildCommands(rootBuilder, assemblies);
}
if (types != null) {
BuildCommands(rootBuilder, types);
}
_rootCommand = rootBuilder.Command;
_parser = rootBuilder.Build();
}
Expand Down Expand Up @@ -96,73 +103,89 @@ public Command GetCommand(string name)

private void BuildCommands(CommandLineBuilder rootBuilder, IEnumerable<Assembly> assemblies)
{
foreach (Type type in assemblies.SelectMany((assembly) => assembly.GetExportedTypes()))
BuildCommands(rootBuilder, assemblies.SelectMany((assembly) => assembly.GetExportedTypes()));
}

private void BuildCommands(CommandLineBuilder rootBuilder, IEnumerable<Type> types)
{
foreach (Type type in types)
{
Command command = null;
for (Type baseType = type; baseType != null; baseType = baseType.BaseType)
{
if (baseType == typeof(CommandBase)) {
break;
}
BuildCommands(rootBuilder, baseType);
}
}
}

private void BuildCommands(CommandLineBuilder rootBuilder, Type type)
{
Command command = null;

var baseAttributes = (BaseAttribute[])type.GetCustomAttributes(typeof(BaseAttribute), inherit: false);
foreach (BaseAttribute baseAttribute in baseAttributes)
var baseAttributes = (BaseAttribute[])type.GetCustomAttributes(typeof(BaseAttribute), inherit: false);
foreach (BaseAttribute baseAttribute in baseAttributes)
{
if (baseAttribute is CommandAttribute commandAttribute)
{
if (baseAttribute is CommandAttribute commandAttribute)
{
command = new Command(commandAttribute.Name, commandAttribute.Help);
var properties = new List<(PropertyInfo, Option)>();
PropertyInfo argument = null;
command = new Command(commandAttribute.Name, commandAttribute.Help);
var properties = new List<(PropertyInfo, Option)>();
PropertyInfo argument = null;

foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
{
var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
if (argumentAttribute != null)
{
var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
if (argumentAttribute != null)
if (argument != null) {
throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
}
IArgumentArity arity = property.PropertyType.IsArray ? ArgumentArity.ZeroOrMore : ArgumentArity.ZeroOrOne;

command.Argument = new Argument {
Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
Description = argumentAttribute.Help,
ArgumentType = property.PropertyType,
Arity = arity
};
argument = property;
}
else
{
var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
if (optionAttribute != null)
{
if (argument != null) {
throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
command.AddOption(option);
properties.Add((property, option));

foreach (var optionAliasAttribute in (OptionAliasAttribute[])property.GetCustomAttributes(typeof(OptionAliasAttribute), inherit: false))
{
option.AddAlias(optionAliasAttribute.Name);
}
IArgumentArity arity = property.PropertyType.IsArray ? ArgumentArity.ZeroOrMore : ArgumentArity.ZeroOrOne;

command.Argument = new Argument {
Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
Description = argumentAttribute.Help,
ArgumentType = property.PropertyType,
Arity = arity
};
argument = property;
}
else
{
var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
if (optionAttribute != null)
{
var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
command.AddOption(option);
properties.Add((property, option));

foreach (var optionAliasAttribute in (OptionAliasAttribute[])property.GetCustomAttributes(typeof(OptionAliasAttribute), inherit: false))
{
option.AddAlias(optionAliasAttribute.Name);
}
}
else
{
// If not an option, add as just a settable properties
properties.Add((property, null));
}
// If not an option, add as just a settable properties
properties.Add((property, null));
}
}
}

var handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
_commandHandlers.Add(command.Name, handler);
command.Handler = handler;
var handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
_commandHandlers.Add(command.Name, handler);
command.Handler = handler;

rootBuilder.AddCommand(command);
}
rootBuilder.AddCommand(command);
}

if (baseAttribute is CommandAliasAttribute commandAliasAttribute)
{
if (command == null) {
throw new ArgumentException($"No previous CommandAttribute for this CommandAliasAttribute: {type.Name}");
}
command.AddAlias(commandAliasAttribute.Name);
if (baseAttribute is CommandAliasAttribute commandAliasAttribute)
{
if (command == null) {
throw new ArgumentException($"No previous CommandAttribute for this CommandAliasAttribute: {type.Name}");
}
command.AddAlias(commandAliasAttribute.Name);
}
}
}
Expand Down
14 changes: 8 additions & 6 deletions src/SOS/SOS.Hosting/Amd64Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,21 @@ internal struct AMD64Context
public int MxCsr;

[FieldOffset(0x38)]
public short SegCs;
public short Cs;
[FieldOffset(0x3a)]
public short SegDs;
public short Ds;
[FieldOffset(0x3c)]
public short SegEs;
public short Es;
[FieldOffset(0x3e)]
public short SegFs;
public short Fs;
[FieldOffset(0x40)]
public short SegGs;
public short Gs;
[FieldOffset(0x42)]
public short SegSs;
public short Ss;
[FieldOffset(0x44)]
public int EFlags;
[FieldOffset(0x44)]
public ulong RFlags;

[FieldOffset(0x48)]
public ulong Dr0;
Expand Down
Loading

0 comments on commit b0660e4

Please sign in to comment.