From: Mike McLaughlin Date: Sat, 22 Jun 2019 02:31:43 +0000 (-0700) Subject: Implement SOS Hosting for Windows (dotnet-dump) (#352) X-Git-Tag: submit/tizen/20190813.035844~4^2^2~24 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9c8c520f5835fc84087698c9174e9cd9aa9604c;p=platform%2Fcore%2Fdotnet%2Fdiagnostics.git Implement SOS Hosting for Windows (dotnet-dump) (#352) * Implement SOS Hosting for Windows (dotnet-dump) 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. --- diff --git a/eng/Tools.props b/eng/Tools.props deleted file mode 100644 index f1662a3e3..000000000 --- a/eng/Tools.props +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - $(RestoreSources); - $(AdditionalRestoreSources) - - - diff --git a/eng/Versions.props b/eng/Versions.props index a3057c34f..29e40edb5 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -21,7 +21,7 @@ 4.3.0 - 1.0.0-dev-64016-01 + 1.0.0-dev-64131-02 1.0.5 2.0.43 diff --git a/src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs b/src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs index f174222d7..c36655c11 100644 --- a/src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs +++ b/src/Microsoft.Diagnostic.Repl/Command/CommandProcessor.cs @@ -5,6 +5,7 @@ // -------------------------------------------------------------------- using System; +using System.Collections; using System.Collections.Generic; using System.CommandLine; using System.CommandLine.Binding; @@ -28,8 +29,9 @@ namespace Microsoft.Diagnostics.Repl /// Create an instance of the command processor; /// /// console instance to use for commands - /// The list of assemblies to look for commands - public CommandProcessor(IConsole console, IEnumerable assemblies) + /// Optional list of assemblies to look for commands + /// Optional list of types to look for commands + public CommandProcessor(IConsole console, IEnumerable assemblies = null, IEnumerable types = null) { Debug.Assert(console != null); Debug.Assert(assemblies != null); @@ -43,7 +45,12 @@ namespace Microsoft.Diagnostics.Repl .UseSuggestDirective() .UseParseErrorReporting() .UseExceptionHandler(); - BuildCommands(rootBuilder, assemblies); + if (assemblies != null) { + BuildCommands(rootBuilder, assemblies); + } + if (types != null) { + BuildCommands(rootBuilder, types); + } _rootCommand = rootBuilder.Command; _parser = rootBuilder.Build(); } @@ -96,73 +103,89 @@ namespace Microsoft.Diagnostics.Repl private void BuildCommands(CommandLineBuilder rootBuilder, IEnumerable assemblies) { - foreach (Type type in assemblies.SelectMany((assembly) => assembly.GetExportedTypes())) + BuildCommands(rootBuilder, assemblies.SelectMany((assembly) => assembly.GetExportedTypes())); + } + + private void BuildCommands(CommandLineBuilder rootBuilder, IEnumerable 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); } } } diff --git a/src/SOS/SOS.Hosting/Amd64Context.cs b/src/SOS/SOS.Hosting/Amd64Context.cs index c7030aa53..9eb3b2612 100644 --- a/src/SOS/SOS.Hosting/Amd64Context.cs +++ b/src/SOS/SOS.Hosting/Amd64Context.cs @@ -29,17 +29,17 @@ namespace SOS 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; diff --git a/src/SOS/SOS.Hosting/LLDBServices.cs b/src/SOS/SOS.Hosting/LLDBServices.cs new file mode 100644 index 000000000..2423e3f9f --- /dev/null +++ b/src/SOS/SOS.Hosting/LLDBServices.cs @@ -0,0 +1,481 @@ +// 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.Diagnostics.Runtime; +using Microsoft.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class LLDBServices : COMCallableIUnknown + { + private static readonly Guid IID_ILLDBServices = new Guid("2E6C569A-9E14-4DA4-9DFC-CDB73A532566"); + private static readonly Guid IID_ILLDBServices2 = new Guid("012F32F0-33BA-4E8E-BC01-037D382D8A5E"); + + public IntPtr ILLDBServices { get; } + + readonly SOSHost _soshost; + + /// + /// Create an instance of the service wrapper SOS uses. + /// + /// SOS host instance + public LLDBServices(SOSHost soshost) + { + _soshost = soshost; + + VTableBuilder builder = AddInterface(IID_ILLDBServices, validate: false); + + builder.AddMethod(new GetCoreClrDirectoryDelegate(GetCoreClrDirectory)); + builder.AddMethod(new GetExpressionDelegate((self, expression) => SOSHost.GetExpression(expression))); + builder.AddMethod(new VirtualUnwindDelegate(VirtualUnwind)); + builder.AddMethod(new SetExceptionCallbackDelegate(SetExceptionCallback)); + builder.AddMethod(new ClearExceptionCallbackDelegate(ClearExceptionCallback)); + + builder.AddMethod(new GetInterruptDelegate(soshost.GetInterrupt)); + builder.AddMethod(new OutputVaListDelegate(soshost.OutputVaList)); + builder.AddMethod(new GetDebuggeeTypeDelegate(soshost.GetDebuggeeType)); + builder.AddMethod(new GetPageSizeDelegate(soshost.GetPageSize)); + builder.AddMethod(new GetExecutingProcessorTypeDelegate(soshost.GetExecutingProcessorType)); + builder.AddMethod(new ExecuteDelegate(soshost.Execute)); + builder.AddMethod(new GetLastEventInformationDelegate(soshost.GetLastEventInformation)); + builder.AddMethod(new DisassembleDelegate(soshost.Disassemble)); + + builder.AddMethod(new GetContextStackTraceDelegate(GetContextStackTrace)); + builder.AddMethod(new ReadVirtualDelegate(soshost.ReadVirtual)); + builder.AddMethod(new WriteVirtualDelegate(soshost.WriteVirtual)); + + builder.AddMethod(new GetSymbolOptionsDelegate(soshost.GetSymbolOptions)); + builder.AddMethod(new GetNameByOffsetDelegate(soshost.GetNameByOffset)); + builder.AddMethod(new GetNumberModulesDelegate(soshost.GetNumberModules)); + builder.AddMethod(new GetModuleByIndexDelegate(soshost.GetModuleByIndex)); + builder.AddMethod(new GetModuleByModuleNameDelegate(soshost.GetModuleByModuleName)); + builder.AddMethod(new GetModuleByOffsetDelegate(soshost.GetModuleByOffset)); + builder.AddMethod(new GetModuleNamesDelegate(soshost.GetModuleNames)); + builder.AddMethod(new GetLineByOffsetDelegate(soshost.GetLineByOffset)); + builder.AddMethod(new GetSourceFileLineOffsetsDelegate(soshost.GetSourceFileLineOffsets)); + builder.AddMethod(new FindSourceFileDelegate(soshost.FindSourceFile)); + + builder.AddMethod(new GetCurrentProcessIdDelegate(soshost.GetCurrentProcessId)); + builder.AddMethod(new GetCurrentThreadIdDelegate(soshost.GetCurrentThreadId)); + builder.AddMethod(new SetCurrentThreadIdDelegate(soshost.SetCurrentThreadId)); + builder.AddMethod(new GetCurrentThreadSystemIdDelegate(soshost.GetCurrentThreadSystemId)); + builder.AddMethod(new GetThreadIdBySystemIdDelegate(soshost.GetThreadIdBySystemId)); + builder.AddMethod(new GetThreadContextByIdDelegate(GetThreadContextById)); + + builder.AddMethod(new GetValueByNameDelegate(GetValueByName)); + builder.AddMethod(new GetInstructionOffsetDelegate(soshost.GetInstructionOffset)); + builder.AddMethod(new GetStackOffsetDelegate(soshost.GetStackOffset)); + builder.AddMethod(new GetFrameOffsetDelegate(soshost.GetFrameOffset)); + + ILLDBServices = builder.Complete(); + + builder = AddInterface(IID_ILLDBServices2, validate: false); + builder.AddMethod(new LoadNativeSymbolsDelegate2(LoadNativeSymbols2)); + builder.AddMethod(new AddModuleSymbolDelegate(AddModuleSymbol)); + builder.Complete(); + + AddRef(); + } + + #region ILLDBServices + + string GetCoreClrDirectory( + IntPtr self) + { + foreach (ModuleInfo module in _soshost.DataReader.EnumerateModules()) + { + if (SOSHost.IsRuntimeModule(module)) { + return Path.GetDirectoryName(module.FileName) + Path.DirectorySeparatorChar; + } + } + return null; + } + + int VirtualUnwind( + IntPtr self, + uint threadId, + uint contextSize, + byte[] context) + { + return E_NOTIMPL; + } + + int SetExceptionCallback( + IntPtr self, + PFN_EXCEPTION_CALLBACK callback) + { + return S_OK; + } + + int ClearExceptionCallback( + IntPtr self) + { + return S_OK; + } + + int GetContextStackTrace( + IntPtr self, + IntPtr startContext, + uint startContextSize, + DEBUG_STACK_FRAME[] frames, + uint framesSize, + IntPtr frameContexts, + uint frameContextsSize, + uint frameContextsEntrySize, + uint* framesFilled) + { + // Don't fail, but always return 0 native frames so "clrstack -f" still prints the managed frames + SOSHost.Write(framesFilled); + return S_OK; + } + + int GetThreadContextById( + IntPtr self, + uint threadId, + uint contextFlags, + uint contextSize, + IntPtr context) + { + if (_soshost.DataReader.GetThreadContext(threadId, contextFlags, contextSize, context)) { + return S_OK; + } + return E_FAIL; + } + + int GetValueByName( + IntPtr self, + string name, + out ulong value) + { + return _soshost.GetRegister(name, out value); + } + + #endregion + + #region ILLDBServices2 + + int LoadNativeSymbols2( + IntPtr self, + bool runtimeOnly, + ModuleLoadCallback callback) + { + foreach (ModuleInfo module in _soshost.DataReader.EnumerateModules()) + { + if (runtimeOnly) + { + if (SOSHost.IsRuntimeModule(module)) + { + callback(IntPtr.Zero, module.FileName, module.ImageBase, unchecked((int)module.FileSize)); + break; + } + } + else + { + callback(IntPtr.Zero, module.FileName, module.ImageBase, unchecked((int)module.FileSize)); + } + } + return S_OK; + } + + int AddModuleSymbol( + IntPtr self, + IntPtr parameter, + string symbolFilename) + { + return S_OK; + } + + #endregion + + #region ILLDBServices delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.LPStr)] + private delegate string GetCoreClrDirectoryDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate ulong GetExpressionDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string text); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int VirtualUnwindDelegate( + IntPtr self, + uint threadId, + uint contextSize, + byte[] context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int PFN_EXCEPTION_CALLBACK(LLDBServices services); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetExceptionCallbackDelegate( + IntPtr self, + PFN_EXCEPTION_CALLBACK callback); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ClearExceptionCallbackDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInterruptDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputVaListDelegate( + IntPtr self, + DEBUG_OUTPUT mask, + [In, MarshalAs(UnmanagedType.LPStr)] string format, + IntPtr va_list); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetDebuggeeTypeDelegate( + IntPtr self, + [Out] DEBUG_CLASS* Class, + [Out] DEBUG_CLASS_QUALIFIER* Qualifier); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetPageSizeDelegate( + IntPtr self, + [Out] uint* size); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExecutingProcessorTypeDelegate( + IntPtr self, + [Out] IMAGE_FILE_MACHINE* type); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ExecuteDelegate( + IntPtr self, + DEBUG_OUTCTL outputControl, + [In, MarshalAs(UnmanagedType.LPStr)] string command, + DEBUG_EXECUTE flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLastEventInformationDelegate( + IntPtr self, + [Out] DEBUG_EVENT* type, + [Out] uint* processId, + [Out] uint* threadId, + [In] IntPtr extraInformation, + [In] uint extraInformationSize, + [Out] uint* extraInformationUsed, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder description, + [In] uint descriptionSize, + [Out] uint* descriptionUsed); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int DisassembleDelegate( + IntPtr self, + [In] ulong offset, + [In] DEBUG_DISASM flags, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, + [In] uint bufferSize, + [Out] uint* disassemblySize, + [Out] ulong* endOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetContextStackTraceDelegate( + IntPtr self, + IntPtr startContext, + uint startContextSize, + [Out, MarshalAs(UnmanagedType.LPArray)] DEBUG_STACK_FRAME[] frames, + uint framesSize, + IntPtr frameContexts, + uint frameContextsSize, + uint frameContextsEntrySize, + uint* pframesFilled); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadVirtualDelegate( + IntPtr self, + [In] ulong address, + IntPtr buffer, + [In] uint bufferSize, + [Out] uint* bytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteVirtualDelegate( + IntPtr self, + [In] ulong address, + IntPtr buffer, + [In] uint bufferSize, + [Out] uint* bytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolOptionsDelegate( + IntPtr self, + out SYMOPT options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNameByOffsetDelegate( + IntPtr self, + [In] ulong offset, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder nameBuffer, + [In] uint nameBufferSize, + [Out] uint* nameSize, + [Out] ulong* displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberModulesDelegate( + IntPtr self, + out uint loaded, + out uint unloaded); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByIndexDelegate( + IntPtr self, + uint index, + out ulong baseAddress); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByModuleNameDelegate( + IntPtr self, + [In, MarshalAs(UnmanagedType.LPStr)] string name, + uint startIndex, + uint* index, + ulong* baseAddress); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByOffsetDelegate( + IntPtr self, + ulong offset, + uint startIndex, + uint* index, + ulong* baseAddress); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleNamesDelegate( + IntPtr self, + uint index, + ulong baseAddress, + [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder imageNameBuffer, + uint imageNameBufferSize, + uint* imageNameSize, + [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder moduleNameBuffer, + uint ModuleNameBufferSize, + uint* moduleNameSize, + [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder loadedImageNameBuffer, + uint loadedImageNameBufferSize, + uint* loadedImageNameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLineByOffsetDelegate( + IntPtr self, + ulong offset, + uint* line, + [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder fileBuffer, + uint fileBufferSize, + uint* fileSize, + ulong* displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceFileLineOffsetsDelegate( + IntPtr self, + [In, MarshalAs(UnmanagedType.LPStr)] string file, + [Out, MarshalAs(UnmanagedType.LPArray)] ulong[] buffer, + uint bufferLines, + uint* fileLines); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FindSourceFileDelegate( + IntPtr self, + uint startElement, + [In, MarshalAs(UnmanagedType.LPStr)] string file, + DEBUG_FIND_SOURCE flags, + uint* foundElement, + [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, + uint bufferSize, + uint* foundSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessIdDelegate( + IntPtr self, + out uint id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadIdDelegate( + IntPtr self, + [Out] out uint id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetCurrentThreadIdDelegate( + IntPtr self, + [In] uint id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadSystemIdDelegate( + IntPtr self, + [Out] out uint sysId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdBySystemIdDelegate( + IntPtr self, + [In] uint sysId, + [Out] out uint id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadContextByIdDelegate( + IntPtr self, + uint threadId, + uint contextFlags, + uint contextSize, + IntPtr context); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetValueByNameDelegate( + IntPtr self, + [In, MarshalAs(UnmanagedType.LPStr)] string name, + out ulong value); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInstructionOffsetDelegate( + IntPtr self, + [Out] out ulong offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetStackOffsetDelegate( + IntPtr self, + [Out] out ulong offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFrameOffsetDelegate( + IntPtr self, + [Out] out ulong offset); + + #endregion + + #region ILLDBServices2 delegates + + /// + /// The LoadNativeSymbolsDelegate2 callback + /// + public delegate void ModuleLoadCallback( + IntPtr parameter, + [MarshalAs(UnmanagedType.LPStr)] string moduleFilePath, + ulong moduleAddress, + int moduleSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int LoadNativeSymbolsDelegate2( + IntPtr self, + bool runtimeOnly, + ModuleLoadCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddModuleSymbolDelegate( + IntPtr self, + IntPtr parameter, + [MarshalAs(UnmanagedType.LPStr)] string symbolFilename); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/LLDBServicesWrapper.cs b/src/SOS/SOS.Hosting/LLDBServicesWrapper.cs deleted file mode 100644 index b1ae1c0c5..000000000 --- a/src/SOS/SOS.Hosting/LLDBServicesWrapper.cs +++ /dev/null @@ -1,947 +0,0 @@ -// 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.Diagnostics.Runtime; -using Microsoft.Diagnostics.Runtime.Interop; -using Microsoft.Diagnostics.Runtime.Utilities; -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; - -namespace SOS -{ - internal unsafe class LLDBServicesWrapper : COMCallableIUnknown - { - private static readonly Guid IID_ILLDBServices = new Guid("2E6C569A-9E14-4DA4-9DFC-CDB73A532566"); - private static readonly Guid IID_ILLDBServices2 = new Guid("012F32F0-33BA-4E8E-BC01-037D382D8A5E"); - private static readonly Guid IID_SOSHostServices = new Guid("D13608FB-AD14-4B49-990A-80284F934C41"); - - public IntPtr ILLDBServices { get; } - - static readonly string s_coreclrModuleName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "coreclr" : "libcoreclr.so"; - - readonly SOSHost _sosHost; - readonly IDataReader _dataReader; - readonly ISOSHostContext _context; - - /// - /// Create an instance of the service wrapper SOS uses. - /// - /// clrmd data reader instance - /// sos hosting context - public LLDBServicesWrapper(SOSHost host, IDataReader dataReader, ISOSHostContext context) - { - _sosHost = host; - _dataReader = dataReader; - _context = context; - - VTableBuilder builder = AddInterface(IID_ILLDBServices, validate: false); - - builder.AddMethod(new GetCoreClrDirectoryDelegate(GetCoreClrDirectory)); - builder.AddMethod(new GetExpressionDelegate(GetExpression)); - builder.AddMethod(new VirtualUnwindDelegate(VirtualUnwind)); - builder.AddMethod(new SetExceptionCallbackDelegate(SetExceptionCallback)); - builder.AddMethod(new ClearExceptionCallbackDelegate(ClearExceptionCallback)); - - builder.AddMethod(new GetInterruptDelegate(GetInterrupt)); - builder.AddMethod(new OutputVaListDelegate(OutputVaList)); - builder.AddMethod(new GetDebuggerTypeDelegate(GetDebuggerType)); - builder.AddMethod(new GetPageSizeDelegate(GetPageSize)); - builder.AddMethod(new GetExecutingProcessorTypeDelegate(GetExecutingProcessorType)); - builder.AddMethod(new ExecuteDelegate(Execute)); - builder.AddMethod(new GetLastEventInformationDelegate(GetLastEventInformation)); - builder.AddMethod(new DisassembleDelegate(Disassemble)); - - builder.AddMethod(new GetContextStackTraceDelegate(GetContextStackTrace)); - builder.AddMethod(new ReadVirtualDelegate(ReadVirtual)); - builder.AddMethod(new WriteVirtualDelegate(WriteVirtual)); - - builder.AddMethod(new GetSymbolOptionsDelegate(GetSymbolOptions)); - builder.AddMethod(new GetNameByOffsetDelegate(GetNameByOffset)); - builder.AddMethod(new GetNumberModulesDelegate(GetNumberModules)); - builder.AddMethod(new GetModuleByIndexDelegate(GetModuleByIndex)); - builder.AddMethod(new GetModuleByModuleNameDelegate(GetModuleByModuleName)); - builder.AddMethod(new GetModuleByOffsetDelegate(GetModuleByOffset)); - builder.AddMethod(new GetModuleNamesDelegate(GetModuleNames)); - builder.AddMethod(new GetLineByOffsetDelegate(GetLineByOffset)); - builder.AddMethod(new GetSourceFileLineOffsetsDelegate(GetSourceFileLineOffsets)); - builder.AddMethod(new FindSourceFileDelegate(FindSourceFile)); - - builder.AddMethod(new GetCurrentProcessIdDelegate(GetCurrentProcessId)); - builder.AddMethod(new GetCurrentThreadIdDelegate(GetCurrentThreadId)); - builder.AddMethod(new SetCurrentThreadIdDelegate(SetCurrentThreadId)); - builder.AddMethod(new GetCurrentThreadSystemIdDelegate(GetCurrentThreadSystemId)); - builder.AddMethod(new GetThreadIdBySystemIdDelegate(GetThreadIdBySystemId)); - builder.AddMethod(new GetThreadContextByIdDelegate(GetThreadContextById)); - - builder.AddMethod(new GetValueByNameDelegate(GetValueByName)); - builder.AddMethod(new GetInstructionOffsetDelegate(GetInstructionOffset)); - builder.AddMethod(new GetStackOffsetDelegate(GetStackOffset)); - builder.AddMethod(new GetFrameOffsetDelegate(GetFrameOffset)); - - ILLDBServices = builder.Complete(); - - builder = AddInterface(IID_ILLDBServices2, validate: false); - builder.AddMethod(new LoadNativeSymbolsDelegate2(LoadNativeSymbols2)); - builder.AddMethod(new AddModuleSymbolDelegate(AddModuleSymbol)); - builder.Complete(); - - AddRef(); - } - - #region ILLDBServices - - string GetCoreClrDirectory( - IntPtr self) - { - foreach (ModuleInfo module in _dataReader.EnumerateModules()) - { - if (string.Equals(Path.GetFileName(module.FileName), s_coreclrModuleName)) - { - return Path.GetDirectoryName(module.FileName) + Path.DirectorySeparatorChar; - } - } - return null; - } - - ulong GetExpression( - IntPtr self, - string text) - { - if (ulong.TryParse(text.Replace("0x", ""), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong result)) { - return result; - } - return 0; - } - - int VirtualUnwind( - IntPtr self, - uint threadId, - uint contextSize, - byte[] context) - { - return E_NOTIMPL; - } - - int SetExceptionCallback( - IntPtr self, - PFN_EXCEPTION_CALLBACK callback) - { - return S_OK; - } - - int ClearExceptionCallback( - IntPtr self) - { - return S_OK; - } - - int GetInterrupt( - IntPtr self) - { - return _context.CancellationToken.IsCancellationRequested ? S_OK : E_FAIL; - } - - int OutputVaList( - IntPtr self, - DEBUG_OUTPUT mask, - string format, - IntPtr va_list) - { - try - { - _context.Write(format); - } - catch (OperationCanceledException) - { - // ctrl-c interrupted the command - } - return S_OK; - } - - int GetDebuggerType( - IntPtr self, - out DEBUG_CLASS debugClass, - out DEBUG_CLASS_QUALIFIER qualifier) - { - debugClass = DEBUG_CLASS.USER_WINDOWS; - qualifier = DEBUG_CLASS_QUALIFIER.USER_WINDOWS_DUMP; - return S_OK; - } - - int GetPageSize( - IntPtr self, - out uint size) - { - size = 4096; - return S_OK; - } - - int GetExecutingProcessorType( - IntPtr self, - out IMAGE_FILE_MACHINE type) - { - switch (_dataReader.GetArchitecture()) - { - case Microsoft.Diagnostics.Runtime.Architecture.Amd64: - type = IMAGE_FILE_MACHINE.AMD64; - break; - case Microsoft.Diagnostics.Runtime.Architecture.X86: - type = IMAGE_FILE_MACHINE.I386; - break; - case Microsoft.Diagnostics.Runtime.Architecture.Arm: - type = IMAGE_FILE_MACHINE.ARM; - break; - default: - type = IMAGE_FILE_MACHINE.UNKNOWN; - break; - } - return S_OK; - } - - int Execute( - IntPtr self, - DEBUG_OUTCTL outputControl, - string command, - DEBUG_EXECUTE flags) - { - return E_NOTIMPL; - } - - int GetLastEventInformation( - IntPtr self, - out uint type, - out uint processId, - out uint threadId, - IntPtr extraInformation, - uint extraInformationSize, - out uint extraInformationUsed, - string description, - uint descriptionSize, - out uint descriptionUsed) - { - // Should never be called. This exception will take down the program. - throw new NotImplementedException("GetLastEventInformation"); - } - - int Disassemble( - IntPtr self, - ulong offset, - DEBUG_DISASM flags, - StringBuilder buffer, - uint bufferSize, - IntPtr pdisassemblySize, // uint - IntPtr pendOffset) // ulong - { - buffer.Clear(); - WriteUInt32(pdisassemblySize, 0); - WriteUInt64(pendOffset, offset); - return E_NOTIMPL; - } - - int GetContextStackTrace( - IntPtr self, - IntPtr startContext, - uint startContextSize, - DEBUG_STACK_FRAME[] frames, - uint framesSize, - IntPtr frameContexts, - uint frameContextsSize, - uint frameContextsEntrySize, - IntPtr pframesFilled) // uint - { - // Don't fail, but always return 0 native frames so "clrstack -f" still prints the managed frames - WriteUInt32(pframesFilled, 0); - return S_OK; - } - - int ReadVirtual( - IntPtr self, - ulong address, - IntPtr buffer, - int bytesRequested, - IntPtr pbytesRead) // uint - { - if (_dataReader.ReadMemory(address, buffer, bytesRequested, out int bytesRead)) - { - WriteUInt32(pbytesRead, (uint)bytesRead); - return S_OK; - } - return E_FAIL; - } - - int WriteVirtual( - IntPtr self, - ulong address, - IntPtr buffer, - uint bytesRequested, - IntPtr pbytesWritten) - { - // This gets used by MemoryBarrier() calls in the dac, which really shouldn't matter what we do here. - WriteUInt32(pbytesWritten, bytesRequested); - return S_OK; - } - - int GetSymbolOptions( - IntPtr self, - out SYMOPT options) - { - options = SYMOPT.LOAD_LINES; - return S_OK; - } - - int GetNameByOffset( - IntPtr self, - ulong offset, - StringBuilder nameBuffer, - uint nameBufferSize, - IntPtr pnameSize, // uint - IntPtr pdisplacement) // ulong - { - nameBuffer.Clear(); - WriteUInt32(pnameSize, 0); - WriteUInt64(pdisplacement, 0); - return E_NOTIMPL; - } - - int GetNumberModules( - IntPtr self, - out uint loaded, - out uint unloaded) - { - loaded = (uint)_dataReader.EnumerateModules().Count(); - unloaded = 0; - return S_OK; - } - - int GetModuleByIndex( - IntPtr self, - uint index, - out ulong baseAddress) - { - baseAddress = 0; - try - { - ModuleInfo module = _dataReader.EnumerateModules().ElementAt((int)index); - if (module == null) - { - return E_FAIL; - } - baseAddress = module.ImageBase; - } - catch (ArgumentOutOfRangeException) - { - return E_FAIL; - } - return S_OK; - } - - int GetModuleByModuleName( - IntPtr self, - string name, - uint startIndex, - IntPtr pIndex, - out ulong baseAddress) - { - // The returned "index" is never used by SOS. Always passes startIndex = 0; - Debug.Assert(pIndex == IntPtr.Zero); - Debug.Assert(startIndex == 0); - - baseAddress = 0; - foreach (ModuleInfo module in _dataReader.EnumerateModules()) - { - if (string.Equals(Path.GetFileName(module.FileName), name)) - { - baseAddress = module.ImageBase; - return S_OK; - } - } - return E_FAIL; - } - - int GetModuleByOffset( - IntPtr self, - ulong offset, - uint startIndex, - IntPtr pindex, // uint - IntPtr pbaseAddress) // ulong - { - WriteUInt32(pindex, 0); - WriteUInt64(pbaseAddress, 0); - return E_NOTIMPL; - } - - int GetModuleNames( - IntPtr self, - uint index, - ulong baseAddress, - StringBuilder imageNameBuffer, - uint imageNameBufferSize, - IntPtr pimageNameSize, // uint - StringBuilder moduleNameBuffer, - uint ModuleNameBufferSize, - IntPtr pmoduleNameSize, // uint - StringBuilder loadedImageNameBuffer, - uint loadedImageNameBufferSize, - IntPtr ploadedImageNameSize) // uint - { - WriteUInt32(pimageNameSize, 0); - WriteUInt32(pmoduleNameSize, 0); - WriteUInt32(ploadedImageNameSize, 0); - return E_NOTIMPL; - } - - int GetLineByOffset( - IntPtr self, - ulong offset, - IntPtr pline, // uint - StringBuilder fileBuffer, - uint fileBufferSize, - IntPtr pfileSize, // uint - IntPtr pdisplacement) // ulong - { - WriteUInt32(pline, 0); - WriteUInt32(pfileSize, 0); - WriteUInt64(pdisplacement, 0); - return E_NOTIMPL; - } - - int GetSourceFileLineOffsets( - IntPtr self, - string file, - ulong[] buffer, - uint bufferLines, - IntPtr pfileLines) // uint - { - WriteUInt32(pfileLines, 0); - return E_NOTIMPL; - } - - int FindSourceFile( - IntPtr self, - uint startElement, - string file, - uint flags, - IntPtr pfoundElement, // uint - StringBuilder buffer, - uint bufferSize, - IntPtr pfoundSize) // uint - { - WriteUInt32(pfoundElement, 0); - WriteUInt32(pfoundSize, 0); - return E_NOTIMPL; - } - - int GetCurrentProcessId( - IntPtr self, - out uint id) - { - id = 0; - if (_dataReader is IDataReader2 dataReader2) { - id = dataReader2.ProcessId; - } - return S_OK; - } - - int GetCurrentThreadId( - IntPtr self, - out uint id) - { - return GetThreadIdBySystemId(self, (uint)_context.CurrentThreadId, out id); - } - - int SetCurrentThreadId( - IntPtr self, - uint id) - { - try - { - unchecked { - _context.CurrentThreadId = (int)_dataReader.EnumerateAllThreads().ElementAt((int)id); - } - } - catch (ArgumentOutOfRangeException) - { - return E_FAIL; - } - return S_OK; - } - - int GetCurrentThreadSystemId( - IntPtr self, - out uint sysId) - { - sysId = (uint)_context.CurrentThreadId; - return S_OK; - } - - int GetThreadIdBySystemId( - IntPtr self, - uint sysId, - out uint id) - { - id = 0; - if (sysId != 0) - { - foreach (uint s in _dataReader.EnumerateAllThreads()) - { - if (s == sysId) { - return S_OK; - } - id++; - } - } - return E_FAIL; - } - - int GetThreadContextById( - IntPtr self, - uint threadId, - uint contextFlags, - uint contextSize, - IntPtr context) - { - if (_dataReader.GetThreadContext(threadId, contextFlags, contextSize, context)) { - return S_OK; - } - return E_FAIL; - } - - int GetValueByName( - IntPtr self, - string name, - out ulong value) - { - return GetRegister(name, out value); - } - - int GetInstructionOffset( - IntPtr self, - out ulong offset) - { - // TODO: Support other architectures - return GetRegister("rip", out offset); - } - - int GetStackOffset( - IntPtr self, - out ulong offset) - { - // TODO: Support other architectures - return GetRegister("rsp", out offset); - } - - int GetFrameOffset( - IntPtr self, - out ulong offset) - { - // TODO: Support other architectures - return GetRegister("rbp", out offset); - } - - #endregion - - void WriteUInt32(IntPtr pointer, uint value) - { - if (pointer != IntPtr.Zero) { - Marshal.WriteInt32(pointer, unchecked((int)value)); - } - } - - void WriteUInt64(IntPtr pointer, ulong value) - { - if (pointer != IntPtr.Zero) { - Marshal.WriteInt64(pointer, unchecked((long)value)); - } - } - - // TODO: Support other architectures - int GetRegister(string register, out ulong value) - { - value = 0; - int hr = GetCurrentThreadSystemId(IntPtr.Zero, out uint threadId); - if (hr != 0) { - return hr; - } - byte[] buffer = new byte[AMD64Context.Size]; - if (!_dataReader.GetThreadContext(threadId, uint.MaxValue, (uint)AMD64Context.Size, buffer)) - { - return E_FAIL; - } - fixed (byte* ptr = buffer) - { - AMD64Context* context = (AMD64Context*)ptr; - switch (register.ToLower()) - { - case "rax": - value = context->Rax; - break; - case "rbx": - value = context->Rbx; - break; - case "rcx": - value = context->Rcx; - break; - case "rdx": - value = context->Rdx; - break; - case "rsi": - value = context->Rsi; - break; - case "rdi": - value = context->Rdi; - break; - case "r8": - value = context->R8; - break; - case "r9": - value = context->R9; - break; - case "r10": - value = context->R10; - break; - case "r11": - value = context->R11; - break; - case "r12": - value = context->R12; - break; - case "r13": - value = context->R13; - break; - case "r14": - value = context->R14; - break; - case "r15": - value = context->R15; - break; - case "rip": - value = context->Rip; - break; - case "rsp": - value = context->Rsp; - break; - case "rbp": - value = context->Rbp; - break; - default: - return E_FAIL; - } - } - return S_OK; - } - - #region ILLDBServices2 - - int LoadNativeSymbols2( - IntPtr self, - bool runtimeOnly, - ModuleLoadCallback callback) - { - foreach (ModuleInfo module in _dataReader.EnumerateModules()) - { - callback(IntPtr.Zero, module.FileName, module.ImageBase, unchecked((int)module.FileSize)); - } - return S_OK; - } - - int AddModuleSymbol( - IntPtr self, - IntPtr parameter, - string symbolFilename) - { - return S_OK; - } - - #endregion - - #region ILLDBServices delegates - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - [return: MarshalAs(UnmanagedType.LPStr)] - private delegate string GetCoreClrDirectoryDelegate( - IntPtr self); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate ulong GetExpressionDelegate( - IntPtr self, - [In][MarshalAs(UnmanagedType.LPStr)] string text); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int VirtualUnwindDelegate( - IntPtr self, - uint threadId, - uint contextSize, - byte[] context); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int PFN_EXCEPTION_CALLBACK(LLDBServicesWrapper services); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int SetExceptionCallbackDelegate( - IntPtr self, - PFN_EXCEPTION_CALLBACK callback); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int ClearExceptionCallbackDelegate( - IntPtr self); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetInterruptDelegate( - IntPtr self); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int OutputVaListDelegate( - IntPtr self, - DEBUG_OUTPUT mask, - [In, MarshalAs(UnmanagedType.LPStr)] string format, - IntPtr va_list); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetDebuggerTypeDelegate( - IntPtr self, - out DEBUG_CLASS debugClass, - out DEBUG_CLASS_QUALIFIER qualifier); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetPageSizeDelegate( - IntPtr self, - out uint size); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetExecutingProcessorTypeDelegate( - IntPtr self, - out IMAGE_FILE_MACHINE type); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int ExecuteDelegate( - IntPtr self, - DEBUG_OUTCTL outputControl, - [In, MarshalAs(UnmanagedType.LPStr)] string command, - DEBUG_EXECUTE flags); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetLastEventInformationDelegate( - IntPtr self, - out uint type, - out uint processId, - out uint threadId, - IntPtr extraInformation, - uint extraInformationSize, - out uint extraInformationUsed, - [In][MarshalAs(UnmanagedType.LPStr)] string description, - uint descriptionSize, - out uint descriptionUsed); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int DisassembleDelegate( - IntPtr self, - ulong offset, - DEBUG_DISASM flags, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, - uint bufferSize, - IntPtr pdisassemblySize, - IntPtr pendOffset); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetContextStackTraceDelegate( - IntPtr self, - IntPtr startContext, - uint startContextSize, - [Out, MarshalAs(UnmanagedType.LPArray)] DEBUG_STACK_FRAME[] frames, - uint framesSize, - IntPtr frameContexts, - uint frameContextsSize, - uint frameContextsEntrySize, - IntPtr pframesFilled); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int ReadVirtualDelegate( - IntPtr self, - ulong address, - IntPtr buffer, - int bytesRequested, - IntPtr pbytesRead); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int WriteVirtualDelegate( - IntPtr self, - ulong address, - IntPtr buffer, - uint bytesRequested, - IntPtr pbytesWritten); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetSymbolOptionsDelegate( - IntPtr self, - out SYMOPT options); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetNameByOffsetDelegate( - IntPtr self, - ulong offset, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder nameBuffer, - uint nameBufferSize, - IntPtr pnameSize, - IntPtr pdisplacement); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetNumberModulesDelegate( - IntPtr self, - out uint loaded, - out uint unloaded); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetModuleByIndexDelegate( - IntPtr self, - uint index, - out ulong baseAddress); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetModuleByModuleNameDelegate( - IntPtr self, - [In, MarshalAs(UnmanagedType.LPStr)] string name, - uint startIndex, - IntPtr index, - out ulong baseAddress); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetModuleByOffsetDelegate( - IntPtr self, - ulong offset, - uint startIndex, - IntPtr pindex, - IntPtr pbaseAddress); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetModuleNamesDelegate( - IntPtr self, - uint index, - ulong baseAddress, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder imageNameBuffer, - uint imageNameBufferSize, - IntPtr pimageNameSize, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder moduleNameBuffer, - uint ModuleNameBufferSize, - IntPtr pmoduleNameSize, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder loadedImageNameBuffer, - uint loadedImageNameBufferSize, - IntPtr ploadedImageNameSize); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetLineByOffsetDelegate( - IntPtr self, - ulong offset, - IntPtr line, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder fileBuffer, - uint fileBufferSize, - IntPtr fileSize, - IntPtr displacement); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetSourceFileLineOffsetsDelegate( - IntPtr self, - [In, MarshalAs(UnmanagedType.LPStr)] string file, - [Out, MarshalAs(UnmanagedType.LPArray)] ulong[] buffer, - uint bufferLines, - IntPtr fileLines); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int FindSourceFileDelegate( - IntPtr self, - uint startElement, - [In, MarshalAs(UnmanagedType.LPStr)] string file, - uint flags, - IntPtr foundElement, - [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer, - uint bufferSize, - IntPtr foundSize); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetCurrentProcessIdDelegate( - IntPtr self, - out uint id); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetCurrentThreadIdDelegate( - IntPtr self, - out uint id); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int SetCurrentThreadIdDelegate( - IntPtr self, - uint id); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetCurrentThreadSystemIdDelegate( - IntPtr self, - out uint sysId); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetThreadIdBySystemIdDelegate( - IntPtr self, - uint sysId, - out uint id); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetThreadContextByIdDelegate( - IntPtr self, - uint threadId, - uint contextFlags, - uint contextSize, - IntPtr context); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetValueByNameDelegate( - IntPtr self, - [In, MarshalAs(UnmanagedType.LPStr)] string name, - out ulong value); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetInstructionOffsetDelegate( - IntPtr self, - out ulong offset); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetStackOffsetDelegate( - IntPtr self, - out ulong offset); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int GetFrameOffsetDelegate( - IntPtr self, - out ulong offset); - - #endregion - - #region ILLDBServices2 delegates - - /// - /// The LoadNativeSymbolsDelegate2 callback - /// - public delegate void ModuleLoadCallback( - IntPtr parameter, - [MarshalAs(UnmanagedType.LPStr)] string moduleFilePath, - ulong moduleAddress, - int moduleSize); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int LoadNativeSymbolsDelegate2( - IntPtr self, - bool runtimeOnly, - ModuleLoadCallback callback); - - [UnmanagedFunctionPointer(CallingConvention.StdCall)] - private delegate int AddModuleSymbolDelegate( - IntPtr self, - IntPtr parameter, - [MarshalAs(UnmanagedType.LPStr)] string symbolFilename); - - #endregion - } -} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/SOSHost.cs b/src/SOS/SOS.Hosting/SOSHost.cs index 306ae73a7..6491c83e3 100644 --- a/src/SOS/SOS.Hosting/SOSHost.cs +++ b/src/SOS/SOS.Hosting/SOSHost.cs @@ -3,11 +3,17 @@ // See the LICENSE file in the project root for more information. using Microsoft.Diagnostics.Runtime; +using Microsoft.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; +using System.Linq; using System.Reflection; using System.Runtime.InteropServices; +using System.Text; namespace SOS { @@ -16,6 +22,12 @@ namespace SOS /// public sealed class SOSHost { + internal const int S_OK = DebugClient.S_OK; + internal const int E_INVALIDARG = DebugClient.E_INVALIDARG; + internal const int E_FAIL = DebugClient.E_FAIL; + internal const int E_NOTIMPL = DebugClient.E_NOTIMPL; + internal const int E_NOINTERFACE = DebugClient.E_NOINTERFACE; + [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int SOSCommandDelegate( IntPtr ILLDBServices, @@ -25,11 +37,15 @@ namespace SOS private delegate int SOSInitializeDelegate( [In, MarshalAs(UnmanagedType.Struct)] ref SOSNetCoreCallbacks callbacks, int callbacksSize, - [In, MarshalAs(UnmanagedType.LPStr)] string tempDirectory, - [In, MarshalAs(UnmanagedType.LPStr)] string dacFilePath, + [In, MarshalAs(UnmanagedType.LPStr)] string tempDirectory, + [In, MarshalAs(UnmanagedType.LPStr)] string dacFilePath, [In, MarshalAs(UnmanagedType.LPStr)] string dbiFilePath, bool symbolStoreEnabled); + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate ulong GetExpressionDelegate( + [In, MarshalAs(UnmanagedType.LPStr)] string expression); + private const string SOSInitialize = "SOSInitializeByHost"; #region SOS.NETCore function delegates @@ -115,6 +131,7 @@ namespace SOS public GetLineByILOffsetDelegate GetLineByILOffsetDelegate; public GetLocalVariableNameDelegate GetLocalVariableNameDelegate; public GetMetadataLocatorDelegate GetMetadataLocatorDelegate; + public GetExpressionDelegate GetExpressionDelegate; } static SOSNetCoreCallbacks s_callbacks = new SOSNetCoreCallbacks { @@ -123,15 +140,24 @@ namespace SOS DisableSymbolStoreDelegate = SymbolReader.DisableSymbolStore, LoadNativeSymbolsDelegate = SymbolReader.LoadNativeSymbols, LoadSymbolsForModuleDelegate = SymbolReader.LoadSymbolsForModule, - DisposeDelegate = SymbolReader.Dispose, + DisposeDelegate = SymbolReader.Dispose, ResolveSequencePointDelegate = SymbolReader.ResolveSequencePoint, GetLineByILOffsetDelegate = SymbolReader.GetLineByILOffset, GetLocalVariableNameDelegate = SymbolReader.GetLocalVariableName, - GetMetadataLocatorDelegate = MetadataHelper.GetMetadataLocator + GetMetadataLocatorDelegate = MetadataHelper.GetMetadataLocator, + GetExpressionDelegate = SOSHost.GetExpression, }; - readonly LLDBServicesWrapper _wrapper; - IntPtr _sosLibrary = IntPtr.Zero; + internal readonly IDataReader DataReader; + internal readonly ISOSHostContext SOSHostContext; + + private static readonly string s_coreclrModuleName; + private static readonly Dictionary s_registersByName; + private static readonly int[] s_registerOffsets; + + private readonly COMCallableIUnknown _ccw; + private readonly IntPtr _interface; + private IntPtr _sosLibrary = IntPtr.Zero; /// /// Enable the assembly resolver to get the right SOS.NETCore version (the one @@ -140,6 +166,33 @@ namespace SOS static SOSHost() { AssemblyResolver.Enable(); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + s_coreclrModuleName = "coreclr"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { + s_coreclrModuleName = "libcoreclr.so"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { + s_coreclrModuleName = "libcoreclr.dylib"; + } + + // TODO: Support other architectures + Type contextType = typeof(AMD64Context); + var registerNames = new Dictionary(); + var offsets = new List(); + int index = 0; + + FieldInfo[] fields = contextType.GetFields(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic); + foreach (FieldInfo field in fields) { + registerNames.Add(field.Name.ToLower(), index); + + FieldOffsetAttribute attribute = field.GetCustomAttributes(inherit: false).Single(); + offsets.Insert(index, attribute.Value); + index++; + } + s_registersByName = registerNames; + s_registerOffsets = offsets.ToArray(); } /// @@ -152,9 +205,22 @@ namespace SOS /// public SOSHost(IDataReader dataReader, ISOSHostContext context) { + DataReader = dataReader; + SOSHostContext = context; string rid = InstallHelper.GetRid(); SOSPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), rid); - _wrapper = new LLDBServicesWrapper(this, dataReader, context); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var debugClient = new DebugClient(this); + _ccw = debugClient; + _interface = debugClient.IDebugClient; + } + else + { + var lldbServices = new LLDBServices(this); + _ccw = lldbServices; + _interface = lldbServices.ILLDBServices; + } } /// @@ -203,7 +269,7 @@ namespace SOS int result = initializeFunc( ref s_callbacks, - Marshal.SizeOf(), + Marshal.SizeOf(), tempDirectory, dacFilePath, dbiFilePath, @@ -250,11 +316,655 @@ namespace SOS } var commandFunc = (SOSCommandDelegate)Marshal.GetDelegateForFunctionPointer(commandAddress, typeof(SOSCommandDelegate)); - int result = commandFunc(_wrapper.ILLDBServices, arguments ?? ""); + int result = commandFunc(_interface, arguments ?? ""); if (result != 0) { throw new InvalidOperationException($"SOS command FAILED 0x{result:X8}"); } } + + #region Reverse PInvoke Implementations + + internal static ulong GetExpression( + string expression) + { + if (expression != null) + { + if (ulong.TryParse(expression.Replace("0x", ""), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong result)) + { + return result; + } + } + return 0; + } + + internal int GetInterrupt( + IntPtr self) + { + return SOSHostContext.CancellationToken.IsCancellationRequested ? S_OK : E_FAIL; + } + + internal int OutputVaList( + IntPtr self, + DEBUG_OUTPUT mask, + string format, + IntPtr va_list) + { + try + { + // The text has already been formated by sos + SOSHostContext.Write(format); + } + catch (OperationCanceledException) + { + // ctrl-c interrupted the command + } + return S_OK; + } + + internal unsafe int GetDebuggeeType( + IntPtr self, + DEBUG_CLASS* debugClass, + DEBUG_CLASS_QUALIFIER* qualifier) + { + *debugClass = DEBUG_CLASS.USER_WINDOWS; + *qualifier = DEBUG_CLASS_QUALIFIER.USER_WINDOWS_DUMP; + return S_OK; + } + + internal unsafe int GetDumpFormatFlags( + IntPtr self, + DEBUG_FORMAT* formatFlags) + { + *formatFlags = DEBUG_FORMAT.DEFAULT; + return DebugClient.S_OK; + } + + internal unsafe int GetPageSize( + IntPtr self, + uint* size) + { + *size = 4096; + return S_OK; + } + + internal unsafe int GetExecutingProcessorType( + IntPtr self, + IMAGE_FILE_MACHINE* type) + { + switch (DataReader.GetArchitecture()) + { + case Microsoft.Diagnostics.Runtime.Architecture.Amd64: + *type = IMAGE_FILE_MACHINE.AMD64; + break; + case Microsoft.Diagnostics.Runtime.Architecture.X86: + *type = IMAGE_FILE_MACHINE.I386; + break; + case Microsoft.Diagnostics.Runtime.Architecture.Arm: + *type = IMAGE_FILE_MACHINE.ARM; + break; + default: + *type = IMAGE_FILE_MACHINE.UNKNOWN; + break; + } + return S_OK; + } + + internal int Execute( + IntPtr self, + DEBUG_OUTCTL outputControl, + string command, + DEBUG_EXECUTE flags) + { + return E_NOTIMPL; + } + + internal unsafe int GetLastEventInformation( + IntPtr self, + DEBUG_EVENT* type, + uint* processId, + uint* threadId, + IntPtr extraInformation, + uint extraInformationSize, + uint* extraInformationUsed, + StringBuilder description, + uint descriptionSize, + uint* descriptionUsed) + { + // Should never be called. This exception will take down the program. + throw new NotImplementedException("GetLastEventInformation"); + } + + internal unsafe int Disassemble( + IntPtr self, + ulong offset, + DEBUG_DISASM flags, + StringBuilder buffer, + uint bufferSize, + uint* disassemblySize, + ulong* endOffset) + { + buffer.Clear(); + Write(disassemblySize); + Write(endOffset, offset); + return E_NOTIMPL; + } + + internal unsafe int ReadVirtual( + IntPtr self, + ulong address, + IntPtr buffer, + uint bytesRequested, + uint* pbytesRead) + { + if (DataReader.ReadMemory(address, buffer, unchecked((int)bytesRequested), out int bytesRead)) + { + Write(pbytesRead, (uint)bytesRead); + return S_OK; + } + return E_FAIL; + } + + internal unsafe int WriteVirtual( + IntPtr self, + ulong address, + IntPtr buffer, + uint bytesRequested, + uint* pbytesWritten) + { + // This gets used by MemoryBarrier() calls in the dac, which really shouldn't matter what we do here. + Write(pbytesWritten, bytesRequested); + return S_OK; + } + + internal int GetSymbolOptions( + IntPtr self, + out SYMOPT options) + { + options = SYMOPT.LOAD_LINES; + return S_OK; + } + + internal unsafe int GetNameByOffset( + IntPtr self, + ulong offset, + StringBuilder nameBuffer, + uint nameBufferSize, + uint* nameSize, + ulong* displacement) + { + nameBuffer.Clear(); + Write(nameSize); + Write(displacement); + return E_NOTIMPL; + } + + internal int GetNumberModules( + IntPtr self, + out uint loaded, + out uint unloaded) + { + loaded = (uint)DataReader.EnumerateModules().Count(); + unloaded = 0; + return S_OK; + } + + internal int GetModuleByIndex( + IntPtr self, + uint index, + out ulong baseAddress) + { + baseAddress = 0; + try + { + ModuleInfo module = DataReader.EnumerateModules().ElementAt((int)index); + if (module == null) + { + return E_FAIL; + } + baseAddress = module.ImageBase; + } + catch (ArgumentOutOfRangeException) + { + return E_FAIL; + } + return S_OK; + } + + internal unsafe int GetModuleByModuleName( + IntPtr self, + string name, + uint startIndex, + uint* index, + ulong* baseAddress) + { + Debug.Assert(startIndex == 0); + Write(index); + Write(baseAddress); + + uint i = 0; + foreach (ModuleInfo module in DataReader.EnumerateModules()) + { + if (IsModuleEqual(module, name)) + { + Write(index, i); + Write(baseAddress, module.ImageBase); + return S_OK; + } + i++; + } + return E_FAIL; + } + + internal unsafe int GetModuleByOffset( + IntPtr self, + ulong offset, + uint startIndex, + uint* index, + ulong* baseAddress) + { + Write(index); + Write(baseAddress); + return E_NOTIMPL; + } + + internal unsafe int GetModuleNames( + IntPtr self, + uint index, + ulong baseAddress, + StringBuilder imageNameBuffer, + uint imageNameBufferSize, + uint* imageNameSize, + StringBuilder moduleNameBuffer, + uint moduleNameBufferSize, + uint* moduleNameSize, + StringBuilder loadedImageNameBuffer, + uint loadedImageNameBufferSize, + uint* loadedImageNameSize) + { + Write(imageNameSize); + Write(moduleNameSize); + Write(loadedImageNameSize); + + uint i = 0; + foreach (ModuleInfo module in DataReader.EnumerateModules()) + { + if (index != uint.MaxValue && i == index || index == uint.MaxValue && baseAddress == module.ImageBase) + { + if (imageNameBuffer != null) { + imageNameBuffer.Append(module.FileName); + } + Write(imageNameSize, (uint)module.FileName.Length + 1); + + string moduleName = GetModuleName(module); + if (moduleNameBuffer != null) { + moduleNameBuffer.Append(moduleName); + } + Write(moduleNameSize, (uint)moduleName.Length + 1); + return S_OK; + } + i++; + } + return E_FAIL; + } + + internal unsafe int GetModuleParameters( + IntPtr self, + uint count, + ulong* bases, + uint start, + DEBUG_MODULE_PARAMETERS* moduleParams) + { + Debug.Assert(bases != null); + Debug.Assert(start == 0); + + foreach (ModuleInfo module in DataReader.EnumerateModules()) + { + for (int i = 0; i < count; i++) + { + if (bases[i] == module.ImageBase) + { + moduleParams[i].Base = module.ImageBase; + moduleParams[i].Size = module.FileSize; + moduleParams[i].TimeDateStamp = module.TimeStamp; + moduleParams[i].Checksum = 0; + moduleParams[i].Flags = DEBUG_MODULE.LOADED; + moduleParams[i].SymbolType = DEBUG_SYMTYPE.PDB; + + uint imageNameSize = (uint)module.FileName.Length + 1; + moduleParams[i].ImageNameSize = imageNameSize; + + string moduleName = GetModuleName(module); + uint moduleNameSize = (uint)moduleName.Length + 1; + moduleParams[i].ModuleNameSize = moduleNameSize; + + moduleParams[i].LoadedImageNameSize = 0; + moduleParams[i].SymbolFileNameSize = 0; + moduleParams[i].MappedImageNameSize = 0; + } + } + } + return S_OK; + } + + internal unsafe int GetLineByOffset( + IntPtr self, + ulong offset, + uint* line, + StringBuilder fileBuffer, + uint fileBufferSize, + uint* fileSize, + ulong* displacement) + { + Write(line); + Write(fileSize); + Write(displacement); + return E_NOTIMPL; + } + + internal unsafe int GetSourceFileLineOffsets( + IntPtr self, + string file, + ulong[] buffer, + uint bufferLines, + uint* fileLines) + { + Write(fileLines); + return E_NOTIMPL; + } + + internal unsafe int FindSourceFile( + IntPtr self, + uint startElement, + string file, + DEBUG_FIND_SOURCE flags, + uint* foundElement, + StringBuilder buffer, + uint bufferSize, + uint* foundSize) + { + Write(foundElement); + Write(foundSize); + return E_NOTIMPL; + } + + internal unsafe int GetSymbolPath( + IntPtr self, + StringBuilder buffer, + int bufferSize, + uint* pathSize) + { + if (buffer != null) { + buffer.Clear(); + } + Write(pathSize); + return S_OK; + } + + internal int GetThreadContext( + IntPtr self, + IntPtr context, + uint contextSize) + { + uint threadId = (uint)SOSHostContext.CurrentThreadId; + if (!DataReader.GetThreadContext(threadId, uint.MaxValue, contextSize, context)) { + return E_FAIL; + } + return S_OK; + } + + internal int SetThreadContext( + IntPtr self, + IntPtr context, + uint contextSize) + { + return DebugClient.NotImplemented; + } + + internal int GetNumberThreads( + IntPtr self, + out uint number) + { + number = (uint)DataReader.EnumerateAllThreads().Count(); + return DebugClient.S_OK; + } + + internal int GetTotalNumberThreads( + IntPtr self, + out uint total, + out uint largestProcess) + { + total = (uint)DataReader.EnumerateAllThreads().Count(); + largestProcess = total; + return DebugClient.S_OK; + } + + internal int GetCurrentProcessId( + IntPtr self, + out uint id) + { + id = 0; + if (DataReader is IDataReader2 dataReader2) { + id = dataReader2.ProcessId; + } + return S_OK; + } + + internal int GetCurrentThreadId( + IntPtr self, + out uint id) + { + return GetThreadIdBySystemId(self, (uint)SOSHostContext.CurrentThreadId, out id); + } + + internal int SetCurrentThreadId( + IntPtr self, + uint id) + { + try + { + unchecked { + SOSHostContext.CurrentThreadId = (int)DataReader.EnumerateAllThreads().ElementAt((int)id); + } + } + catch (ArgumentOutOfRangeException) + { + return E_FAIL; + } + return S_OK; + } + + internal int GetCurrentThreadSystemId( + IntPtr self, + out uint sysId) + { + sysId = (uint)SOSHostContext.CurrentThreadId; + return S_OK; + } + + internal unsafe int GetThreadIdsByIndex( + IntPtr self, + uint start, + uint count, + uint* ids, + uint* sysIds) + { + uint id = 0; + int index = 0; + foreach (uint s in DataReader.EnumerateAllThreads()) + { + if (id >= count) { + break; + } + if (id >= start) + { + if (ids != null) { + ids[index] = id; + } + if (sysIds != null) { + sysIds[index] = s; + } + index++; + } + id++; + } + return DebugClient.S_OK; + } + + internal int GetThreadIdBySystemId( + IntPtr self, + uint sysId, + out uint id) + { + id = 0; + if (sysId != 0) + { + foreach (uint s in DataReader.EnumerateAllThreads()) + { + if (s == sysId) { + return S_OK; + } + id++; + } + } + return E_FAIL; + } + + internal unsafe int GetCurrentThreadTeb( + IntPtr self, + ulong* offset) + { + uint threadId = (uint)SOSHostContext.CurrentThreadId; + ulong teb = DataReader.GetThreadTeb(threadId); + Write(offset, teb); + return S_OK; + } + + internal int GetInstructionOffset( + IntPtr self, + out ulong offset) + { + // TODO: Support other architectures + return GetRegister("rip", out offset); + } + + internal int GetStackOffset( + IntPtr self, + out ulong offset) + { + // TODO: Support other architectures + return GetRegister("rsp", out offset); + } + + internal int GetFrameOffset( + IntPtr self, + out ulong offset) + { + // TODO: Support other architectures + return GetRegister("rbp", out offset); + } + + internal int GetIndexByName( + IntPtr self, + string name, + out uint index) + { + if (!s_registersByName.TryGetValue(name, out int value)) { + index = 0; + return E_INVALIDARG; + } + index = (uint)value; + return S_OK; + } + + internal int GetValue( + IntPtr self, + uint register, + out DEBUG_VALUE value) + { + return GetRegister((int)register, out value); + } + + internal unsafe int GetRegister( + string register, + out ulong value) + { + value = 0; + if (!s_registersByName.TryGetValue(register, out int index)) { + return E_INVALIDARG; + } + int hr = GetRegister(index, out DEBUG_VALUE debugValue); + if (hr != S_OK) { + return hr; + } + // TODO: Support other architectures + value = debugValue.I64; + return S_OK; + } + + internal unsafe int GetRegister( + int index, + out DEBUG_VALUE value) + { + value = new DEBUG_VALUE(); + + if (index >= s_registerOffsets.Length) { + return E_INVALIDARG; + } + uint threadId = (uint)SOSHostContext.CurrentThreadId; + + // TODO: Support other architectures + byte[] buffer = new byte[AMD64Context.Size]; + fixed (byte* ptr = buffer) + { + if (!DataReader.GetThreadContext(threadId, uint.MaxValue, (uint)AMD64Context.Size, new IntPtr(ptr))) { + return E_FAIL; + } + int offset = s_registerOffsets[index]; + value.I64 = *((ulong*)(ptr + offset)); + } + return S_OK; + } + + internal static bool IsRuntimeModule(ModuleInfo module) + { + return IsModuleEqual(module, s_coreclrModuleName); + } + + internal static bool IsModuleEqual(ModuleInfo module, string moduleName) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + return StringComparer.OrdinalIgnoreCase.Equals(GetModuleName(module), moduleName); + } + else { + return string.Equals(GetModuleName(module), moduleName); + } + } + + internal static string GetModuleName(ModuleInfo module) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + return Path.GetFileNameWithoutExtension(module.FileName); + } + else { + return Path.GetFileName(module.FileName); + } + } + + internal unsafe static void Write(uint* pointer, uint value = 0) + { + if (pointer != null) { + *pointer = value; + } + } + + internal unsafe static void Write(ulong* pointer, ulong value = 0) + { + if (pointer != null) { + *pointer = value; + } + } + + #endregion } } diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugAdvanced.cs b/src/SOS/SOS.Hosting/dbgeng/DebugAdvanced.cs new file mode 100644 index 000000000..506d69ae7 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugAdvanced.cs @@ -0,0 +1,38 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; + +namespace SOS +{ + internal unsafe class DebugAdvanced + { + internal DebugAdvanced(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugAdvanced).GUID, validate: true); + builder.AddMethod(new GetThreadContextDelegate(soshost.GetThreadContext)); + builder.AddMethod(new SetThreadContextDelegate(soshost.SetThreadContext)); + builder.Complete(); + } + + #region IDebugAdvanced Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadContextDelegate( + [In] IntPtr self, + [In] IntPtr context, + [In] uint contextSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetThreadContextDelegate( + [In] IntPtr self, + [In] IntPtr context, + [In] uint contextSize); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugClient.cs b/src/SOS/SOS.Hosting/dbgeng/DebugClient.cs new file mode 100644 index 000000000..a8f1f3480 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugClient.cs @@ -0,0 +1,381 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class DebugClient : COMCallableIUnknown + { + new internal const int S_OK = COMHelper.S_OK; + new internal const int E_INVALIDARG = COMHelper.E_INVALIDARG; + new internal const int E_FAIL = COMHelper.E_FAIL; + new internal const int E_NOTIMPL = COMHelper.E_NOTIMPL; + new internal const int E_NOINTERFACE = COMHelper.E_NOINTERFACE; + + internal readonly IntPtr IDebugClient; + + readonly DebugAdvanced _debugAdvanced; + readonly DebugControl _debugControl; + readonly DebugDataSpaces _debugDataSpaces; + readonly DebugRegisters _debugRegisters; + readonly DebugSymbols _debugSymbols; + readonly DebugSystemObjects _debugSystemObjects; + + /// + /// Create an instance of the service wrapper SOS uses. + /// + /// SOS host instance + public DebugClient(SOSHost soshost) + { + VTableBuilder builder = AddInterface(typeof(IDebugClient).GUID, validate: true); + AddDebugClient(builder, soshost); + IDebugClient = builder.Complete(); + + _debugAdvanced = new DebugAdvanced(this, soshost); + _debugControl = new DebugControl(this, soshost); + _debugDataSpaces = new DebugDataSpaces(this, soshost); + _debugRegisters = new DebugRegisters(this, soshost); + _debugSymbols = new DebugSymbols(this, soshost); + _debugSystemObjects = new DebugSystemObjects(this, soshost); + + AddRef(); + } + + private static void AddDebugClient(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new AttachKernelDelegate((self, flags, connectOptions) => NotImplemented)); + builder.AddMethod(new GetKernelConnectionOptionsDelegate((self, buffer, bufferSize, optionsSize) => NotImplemented)); + builder.AddMethod(new SetKernelConnectionOptionsDelegate((self, options) => NotImplemented)); + builder.AddMethod(new StartProcessServerDelegate((self, flags, options, reserved) => NotImplemented)); + builder.AddMethod(new ConnectProcessServerDelegate((self, remoteOptions, server) => NotImplemented)); + builder.AddMethod(new DisconnectProcessServerDelegate((self, server) => NotImplemented)); + builder.AddMethod(new GetRunningProcessSystemIdsDelegate((self, server, ids, count, actualCount) => NotImplemented)); + builder.AddMethod(new GetRunningProcessSystemIdByExecutableNameDelegate((self, server, exeName, flags, id) => NotImplemented)); + builder.AddMethod(new GetRunningProcessDescriptionDelegate((self, server, systemId, flags, exeName, exeNameSize, actualExeNameSize, description, descriptionSize, actualDescriptionSize) => NotImplemented)); + builder.AddMethod(new AttachProcessDelegate((self, server, processId, attachFlags) => NotImplemented)); + builder.AddMethod(new CreateProcessDelegate((self, server, commandLine, flags) => NotImplemented)); + builder.AddMethod(new CreateProcessAndAttachDelegate((self, server, commandLine, flags, processId, attachFlags) => NotImplemented)); + builder.AddMethod(new GetProcessOptionsDelegate((self, options) => NotImplemented)); + builder.AddMethod(new AddProcessOptionsDelegate((self, options) => NotImplemented)); + builder.AddMethod(new RemoveProcessOptionsDelegate((self, options) => NotImplemented)); + builder.AddMethod(new SetProcessOptionsDelegate((self, options) => NotImplemented)); + builder.AddMethod(new OpenDumpFileDelegate((self, dumpFile) => NotImplemented)); + builder.AddMethod(new WriteDumpFileDelegate((self, dumpFile, qualifier) => NotImplemented)); + builder.AddMethod(new ConnectSessionDelegate((self, flags, historyLimit) => NotImplemented)); + builder.AddMethod(new StartServerDelegate((self, options) => NotImplemented)); + builder.AddMethod(new OutputServerDelegate((self, outputControl, machine, flags) => NotImplemented)); + builder.AddMethod(new TerminateProcessesDelegate((self) => NotImplemented)); + builder.AddMethod(new DetachProcessesDelegate((self) => NotImplemented)); + builder.AddMethod(new EndSessionDelegate((self, flags) => NotImplemented)); + builder.AddMethod(new GetExitCodeDelegate((self, code) => NotImplemented)); + builder.AddMethod(new DispatchCallbacksDelegate((self, timeout) => NotImplemented)); + builder.AddMethod(new ExitDispatchDelegate((self, client) => NotImplemented)); + builder.AddMethod(new CreateClientDelegate((self, client) => NotImplemented)); + builder.AddMethod(new GetInputCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new SetInputCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new GetOutputCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new SetOutputCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new GetOutputMaskDelegate((self, mask) => NotImplemented)); + builder.AddMethod(new SetOutputMaskDelegate((self, mask) => NotImplemented)); + builder.AddMethod(new GetOtherOutputMaskDelegate((self, client, mask) => NotImplemented)); + builder.AddMethod(new SetOtherOutputMaskDelegate((self, client, mask) => NotImplemented)); + builder.AddMethod(new GetOutputWidthDelegate((self, columns) => NotImplemented)); + builder.AddMethod(new SetOutputWidthDelegate((self, columns) => NotImplemented)); + builder.AddMethod(new GetOutputLinePrefixDelegate((self, buffer, bufferSize, prefixSize) => NotImplemented)); + builder.AddMethod(new SetOutputLinePrefixDelegate((self, prefix) => NotImplemented)); + builder.AddMethod(new GetIdentityDelegate((self, buffer, bufferSize, identitySize) => NotImplemented)); + builder.AddMethod(new OutputIdentityDelegate((self, outputControl, flags, format) => NotImplemented)); + builder.AddMethod(new GetEventCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new SetEventCallbacksDelegate((self, callbacks) => NotImplemented)); + builder.AddMethod(new FlushCallbacksDelegate((self) => NotImplemented)); + } + + internal static int NotImplemented + { + get { + System.Diagnostics.Debugger.Break(); + return E_NOTIMPL; + } + } + + #region IDebugClient Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AttachKernelDelegate( + IntPtr self, + [In] DEBUG_ATTACH flags, + [In][MarshalAs(UnmanagedType.LPStr)] string connectOptions); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetKernelConnectionOptionsDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* OptionsSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetKernelConnectionOptionsDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int StartProcessServerDelegate( + IntPtr self, + [In] DEBUG_CLASS Flags, + [In][MarshalAs(UnmanagedType.LPStr)] string Options, + [In] IntPtr Reserved); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ConnectProcessServerDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string RemoteOptions, + [Out] ulong* Server); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int DisconnectProcessServerDelegate( + IntPtr self, + [In] ulong Server); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetRunningProcessSystemIdsDelegate( + IntPtr self, + [In] ulong Server, + [Out] uint* Ids, + [In] uint Count, + [Out] uint* ActualCount); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetRunningProcessSystemIdByExecutableNameDelegate( + IntPtr self, + [In] ulong Server, + [In][MarshalAs(UnmanagedType.LPStr)] string ExeName, + [In] DEBUG_GET_PROC Flags, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetRunningProcessDescriptionDelegate( + IntPtr self, + [In] ulong Server, + [In] uint SystemId, + [In] DEBUG_PROC_DESC Flags, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder ExeName, + [In] int ExeNameSize, + [Out] uint* ActualExeNameSize, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Description, + [In] int DescriptionSize, + [Out] uint* ActualDescriptionSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AttachProcessDelegate( + IntPtr self, + [In] ulong Server, + [In] uint ProcessID, + [In] DEBUG_ATTACH AttachFlags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CreateProcessDelegate( + IntPtr self, + [In] ulong Server, + [In][MarshalAs(UnmanagedType.LPStr)] string CommandLine, + [In] DEBUG_CREATE_PROCESS Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CreateProcessAndAttachDelegate( + IntPtr self, + [In] ulong Server, + [In][MarshalAs(UnmanagedType.LPStr)] string CommandLine, + [In] DEBUG_CREATE_PROCESS Flags, + [In] uint ProcessId, + [In] DEBUG_ATTACH AttachFlags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessOptionsDelegate( + IntPtr self, + [Out] DEBUG_PROCESS* Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddProcessOptionsDelegate( + IntPtr self, + [In] DEBUG_PROCESS Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveProcessOptionsDelegate( + IntPtr self, + [In] DEBUG_PROCESS Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetProcessOptionsDelegate( + IntPtr self, + [In] DEBUG_PROCESS Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OpenDumpFileDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string DumpFile); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteDumpFileDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string DumpFile, + [In] DEBUG_DUMP Qualifier); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ConnectSessionDelegate( + IntPtr self, + [In] DEBUG_CONNECT_SESSION Flags, + [In] uint HistoryLimit); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int StartServerDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputServerDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPStr)] string Machine, + [In] DEBUG_SERVERS Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int TerminateProcessesDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int DetachProcessesDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int EndSessionDelegate( + IntPtr self, + [In] DEBUG_END Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExitCodeDelegate( + IntPtr self, + [Out] uint* Code); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int DispatchCallbacksDelegate( + IntPtr self, + [In] uint Timeout); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ExitDispatchDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.Interface)] IDebugClient Client); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CreateClientDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Client); // out IDebugClient + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInputCallbacksDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Callbacks); // out IDebugInputCallbacks + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetInputCallbacksDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.Interface)] IDebugInputCallbacks Callbacks); + + /* GetOutputCallbacks could a conversion thunk from the debugger engine so we can't specify a specific interface */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOutputCallbacksDelegate( + IntPtr self, + [Out] IntPtr Callbacks); // out IDebugOutputCallbacks + + /* We may have to pass a debugger engine conversion thunk back in so we can't specify a specific interface */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetOutputCallbacksDelegate( + IntPtr self, + [In] IDebugOutputCallbacks Callbacks); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOutputMaskDelegate( + IntPtr self, + [Out] DEBUG_OUTPUT* Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetOutputMaskDelegate( + IntPtr self, + [In] DEBUG_OUTPUT Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOtherOutputMaskDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.Interface)] IDebugClient Client, + [Out] DEBUG_OUTPUT* Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetOtherOutputMaskDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.Interface)] IDebugClient Client, + [In] DEBUG_OUTPUT Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOutputWidthDelegate( + IntPtr self, + [Out] uint* Columns); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetOutputWidthDelegate( + IntPtr self, + [In] uint Columns); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOutputLinePrefixDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PrefixSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetOutputLinePrefixDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Prefix); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetIdentityDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* IdentitySize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputIdentityDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] uint Flags, + [In][MarshalAs(UnmanagedType.LPStr)] string Format); + + /* GetEventCallbacks could a conversion thunk from the debugger engine so we can't specify a specific interface */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEventCallbacksDelegate( + IntPtr self, + [Out] IntPtr Callbacks); // out IDebugEventCallbacks + + /* We may have to pass a debugger engine conversion thunk back in so we can't specify a specific interface */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetEventCallbacksDelegate( + IntPtr self, + [In] IDebugEventCallbacks Callbacks); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FlushCallbacksDelegate( + IntPtr self); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugControl.cs b/src/SOS/SOS.Hosting/dbgeng/DebugControl.cs new file mode 100644 index 000000000..7e6b6259c --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugControl.cs @@ -0,0 +1,790 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class DebugControl + { + internal DebugControl(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugControl).GUID, validate: true); + AddDebugControl(builder, soshost); + builder.Complete(); + + builder = client.AddInterface(typeof(IDebugControl2).GUID, validate: true); + AddDebugControl2(builder, soshost); + builder.Complete(); + } + + private static void AddDebugControl(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new GetInterruptDelegate(soshost.GetInterrupt)); + builder.AddMethod(new SetInterruptDelegate((self, flags) => DebugClient.S_OK)); + builder.AddMethod(new GetInterruptTimeoutDelegate((self, seconds) => DebugClient.NotImplemented)); + builder.AddMethod(new SetInterruptTimeoutDelegate((self, seconds) => DebugClient.NotImplemented)); + builder.AddMethod(new GetLogFileDelegate((self, buffer, bufferSize, fileSize, append) => DebugClient.NotImplemented)); + builder.AddMethod(new OpenLogFileDelegate((self, file, append) => DebugClient.NotImplemented)); + builder.AddMethod(new CloseLogFileDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new GetLogMaskDelegate((self, mask) => DebugClient.NotImplemented)); + builder.AddMethod(new SetLogMaskDelegate((self, mask) => DebugClient.NotImplemented)); + builder.AddMethod(new InputDelegate((self, buffer, bufferSize, inputSize) => DebugClient.NotImplemented)); + builder.AddMethod(new ReturnInputDelegate((self, buffer) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputDelegate((self, mask, format) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputVaListDelegate(soshost.OutputVaList)); + builder.AddMethod(new ControlledOutputDelegate((self, outputControl, mask, format) => DebugClient.NotImplemented)); + builder.AddMethod(new ControlledOutputVaListDelegate((self, outputControl, mask, format, valist) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputPromptDelegate((self, outputControl, format) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputPromptVaListDelegate((self, outputControl, format, valist) => DebugClient.NotImplemented)); + builder.AddMethod(new GetPromptTextDelegate((self, buffer, bufferSize, textSize) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputCurrentStateDelegate((self, outputControl, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputVersionInformationDelegate((self, outputControl) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNotifyEventHandleDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new SetNotifyEventHandleDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new AssembleDelegate((self, offset, instr, endoffset) => DebugClient.NotImplemented)); + builder.AddMethod(new DisassembleDelegate(soshost.Disassemble)); + builder.AddMethod(new GetDisassembleEffectiveOffsetDelegate((self, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputDisassemblyDelegate((self, outputControl, offset, flags, endOffset) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputDisassemblyLinesDelegate((self, outputControl, previousLines, totalLines, offset, flags, offsetLine, startOffset, EndOffset, lineOffsets) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNearInstructionDelegate((self, offset, delta, nearOffset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetStackTraceDelegate((self, frameOffset, stackOffset, instructionOffset, frames, frameSize, framesFilled) => DebugClient.NotImplemented)); + builder.AddMethod(new GetReturnOffsetDelegate((self, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputStackTraceDelegate((self, outputControl, frames, frameSize, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new GetDebuggeeTypeDelegate(soshost.GetDebuggeeType)); + builder.AddMethod(new GetActualProcessorTypeDelegate((self, type) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExecutingProcessorTypeDelegate(soshost.GetExecutingProcessorType)); + builder.AddMethod(new GetNumberPossibleExecutingProcessorTypesDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetPossibleExecutingProcessorTypesDelegate((self, start, count, types) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberProcessorsDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSystemVersionDelegate((self, platformId, major, minor, servicePack, servicePackSize, servicePackUsed, servicePackNumber, buildString, buildStringSize, buildStringUse) => DebugClient.NotImplemented)); + builder.AddMethod(new GetPageSizeDelegate(soshost.GetPageSize)); + builder.AddMethod(new IsPointer64BitDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadBugCheckDataDelegate((self, code, arg1, arg2, arg3, arg4) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberSupportedProcessorTypesDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSupportedProcessorTypesDelegate((self, start, count, types) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessorTypeNamesDelegate((self, type, fullNameBuffer, fullNameBufferSize, fullNameSize, abbrevNameBuffer, abbrevNameBufferSize, abbrevNameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetEffectiveProcessorTypeDelegate((self, type) => DebugClient.NotImplemented)); + builder.AddMethod(new SetEffectiveProcessorTypeDelegate((self, type) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExecutionStatusDelegate((self, status) => DebugClient.NotImplemented)); + builder.AddMethod(new SetExecutionStatusDelegate((self, status) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCodeLevelDelegate((self, level) => DebugClient.NotImplemented)); + builder.AddMethod(new SetCodeLevelDelegate((self, level) => DebugClient.NotImplemented)); + builder.AddMethod(new GetEngineOptionsDelegate((self, options) => DebugClient.E_NOTIMPL)); + builder.AddMethod(new AddEngineOptionsDelegate((self, options) => DebugClient.E_NOTIMPL)); + builder.AddMethod(new RemoveEngineOptionsDelegate((self, options) => DebugClient.NotImplemented)); + builder.AddMethod(new SetEngineOptionsDelegate((self, options) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSystemErrorControlDelegate((self, outputLevel, breakLevel) => DebugClient.NotImplemented)); + builder.AddMethod(new SetSystemErrorControlDelegate((self, outputLevel, breakLevel) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTextMacroDelegate((self, slot, buffer, bufferSize, macroSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetTextMacroDelegate((self, slot, macro) => DebugClient.NotImplemented)); + builder.AddMethod(new GetRadixDelegate((self, radix) => DebugClient.NotImplemented)); + builder.AddMethod(new SetRadixDelegate((self, radix) => DebugClient.NotImplemented)); + builder.AddMethod(new EvaluateDelegate((self, expression, desiredType, value, remainderIndex) => DebugClient.NotImplemented)); + builder.AddMethod(new CoerceValueDelegate((self, inValue, outType, outValue) => DebugClient.NotImplemented)); + builder.AddMethod(new CoerceValuesDelegate((self, count, inValues, outTypes, outValues) => DebugClient.NotImplemented)); + builder.AddMethod(new ExecuteDelegate(soshost.Execute)); + builder.AddMethod(new ExecuteCommandFileDelegate((self, outputControl, commandFile, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberBreakpointsDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetBreakpointByIndexDelegate((self, index, bp) => DebugClient.NotImplemented)); + builder.AddMethod(new GetBreakpointByIdDelegate((self, id, bp) => DebugClient.NotImplemented)); + builder.AddMethod(new GetBreakpointParametersDelegate((self, count, ids, start, bpParams) => DebugClient.NotImplemented)); + builder.AddMethod(new AddBreakpointDelegate((self, type, desiredid, bp) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveBreakpointDelegate((self, bp) => DebugClient.NotImplemented)); + builder.AddMethod(new AddExtensionDelegate((self, path, flags, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveExtensionDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExtensionByPathDelegate((self, path, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new CallExtensionDelegate((self, handle, function, arguments) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExtensionFunctionDelegate((self, handle, functionName, function) => DebugClient.NotImplemented)); + builder.AddMethod(new GetWindbgExtensionApis32Delegate((self, api) => DebugClient.NotImplemented)); + builder.AddMethod(new GetWindbgExtensionApis64Delegate((self, api) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberEventFiltersDelegate((self, specificEvents, specificExceptions, arbitaryExceptions) => DebugClient.NotImplemented)); + builder.AddMethod(new GetEventFilterTextDelegate((self, index, buffer, bufferSize, textSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetEventFilterCommandDelegate((self, index, buffer, bufferSize, commandSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetEventFilterCommandDelegate((self, index, command) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSpecificFilterParametersDelegate((self, start, count, filterParams) => DebugClient.NotImplemented)); + builder.AddMethod(new SetSpecificFilterParametersDelegate((self, start, count, filterParams) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSpecificEventFilterArgumentDelegate((self, index, buffer, bufferSize, argumentSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetSpecificEventFilterArgumentDelegate((self, index, argument) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExceptionFilterParametersDelegate((self, count, codes, start, filterParams) => DebugClient.NotImplemented)); + builder.AddMethod(new SetExceptionFilterParametersDelegate((self, count, filterParams) => DebugClient.NotImplemented)); + builder.AddMethod(new GetExceptionFilterSecondCommandDelegate((self, index, buffer, bufferSize, commandSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetExceptionFilterSecondCommandDelegate((self, index, command) => DebugClient.NotImplemented)); + builder.AddMethod(new WaitForEventDelegate((self, flags, timeout) => DebugClient.NotImplemented)); + builder.AddMethod(new GetLastEventInformationDelegate(soshost.GetLastEventInformation)); + } + + private static void AddDebugControl2(VTableBuilder builder, SOSHost soshost) + { + AddDebugControl(builder, soshost); + builder.AddMethod(new GetCurrentTimeDateDelegate((self, timeDate) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentSystemUpTimeDelegate((self, uptime) => DebugClient.NotImplemented)); + builder.AddMethod(new GetDumpFormatFlagsDelegate(soshost.GetDumpFormatFlags)); + builder.AddMethod(new GetNumberTextReplacementsDelegate((self, numRepl) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTextReplacementDelegate((self, srcText, index, srcBuffer, srcBufferSize, srcSize, dstBuffer, dstBufferSize, dstSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetTextReplacementDelegate((self, srcText, dstText) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveTextReplacementsDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputTextReplacementsDelegate((self, outputControl, flags) => DebugClient.NotImplemented)); + } + + #region IDebugControl Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInterruptDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetInterruptDelegate( + IntPtr self, + [In] DEBUG_INTERRUPT Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInterruptTimeoutDelegate( + IntPtr self, + [Out] int* Seconds); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetInterruptTimeoutDelegate( + IntPtr self, + [In] uint Seconds); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLogFileDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* FileSize, + [Out][MarshalAs(UnmanagedType.Bool)] bool* Append); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OpenLogFileDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string File, + [In][MarshalAs(UnmanagedType.Bool)] bool Append); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CloseLogFileDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLogMaskDelegate( + IntPtr self, + [Out] DEBUG_OUTPUT* Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetLogMaskDelegate( + IntPtr self, + [In] DEBUG_OUTPUT Mask); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int InputDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* InputSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReturnInputDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Buffer); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int OutputDelegate( + IntPtr self, + [In] DEBUG_OUTPUT Mask, + [In][MarshalAs(UnmanagedType.LPStr)] string Format); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputVaListDelegate( + IntPtr self, + [In] DEBUG_OUTPUT Mask, + [In][MarshalAs(UnmanagedType.LPStr)] string Format, + [In] IntPtr valist); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + private delegate int ControlledOutputDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] DEBUG_OUTPUT Mask, + [In][MarshalAs(UnmanagedType.LPStr)] string Format); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ControlledOutputVaListDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] DEBUG_OUTPUT Mask, + [In][MarshalAs(UnmanagedType.LPStr)] string Format, + [In] IntPtr valist); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputPromptDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPStr)] string Format); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputPromptVaListDelegate( /* THIS SHOULD NEVER BE CALLED FROM C# */ + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPStr)] string Format, + [In] IntPtr valist); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetPromptTextDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* TextSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputCurrentStateDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] DEBUG_CURRENT Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputVersionInformationDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNotifyEventHandleDelegate( + IntPtr self, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetNotifyEventHandleDelegate( + IntPtr self, + [In] ulong Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AssembleDelegate( + IntPtr self, + [In] ulong Offset, + [In][MarshalAs(UnmanagedType.LPStr)] string Instr, + [Out] ulong* EndOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int DisassembleDelegate( + IntPtr self, + [In] ulong Offset, + [In] DEBUG_DISASM Flags, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] uint BufferSize, + [Out] uint* DisassemblySize, + [Out] ulong* EndOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetDisassembleEffectiveOffsetDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputDisassemblyDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] ulong Offset, + [In] DEBUG_DISASM Flags, + [Out] ulong* EndOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputDisassemblyLinesDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] uint PreviousLines, + [In] uint TotalLines, + [In] ulong Offset, + [In] DEBUG_DISASM Flags, + [Out] uint* OffsetLine, + [Out] ulong* StartOffset, + [Out] ulong* EndOffset, + [Out] ulong* LineOffsets); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNearInstructionDelegate( + IntPtr self, + [In] ulong Offset, + [In] int Delta, + [Out] ulong* NearOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetStackTraceDelegate( + IntPtr self, + [In] ulong FrameOffset, + [In] ulong StackOffset, + [In] ulong InstructionOffset, + [Out] DEBUG_STACK_FRAME* Frames, + [In] int FrameSize, + [Out] uint* FramesFilled); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetReturnOffsetDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputStackTraceDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPArray)] DEBUG_STACK_FRAME[] Frames, + [In] int FramesSize, + [In] DEBUG_STACK Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetDebuggeeTypeDelegate( + IntPtr self, + [Out] DEBUG_CLASS* Class, + [Out] DEBUG_CLASS_QUALIFIER* Qualifier); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetActualProcessorTypeDelegate( + IntPtr self, + [Out] IMAGE_FILE_MACHINE* Type); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExecutingProcessorTypeDelegate( + IntPtr self, + [Out] IMAGE_FILE_MACHINE* Type); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberPossibleExecutingProcessorTypesDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetPossibleExecutingProcessorTypesDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [Out] IMAGE_FILE_MACHINE* Types); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberProcessorsDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSystemVersionDelegate( + IntPtr self, + [Out] uint* PlatformId, + [Out] uint* Major, + [Out] uint* Minor, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder ServicePackString, + [In] int ServicePackStringSize, + [Out] uint* ServicePackStringUsed, + [Out] uint* ServicePackNumber, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder BuildString, + [In] int BuildStringSize, + [Out] uint* BuildStringUsed); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetPageSizeDelegate( + IntPtr self, + [Out] uint* Size); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int IsPointer64BitDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadBugCheckDataDelegate( + IntPtr self, + [Out] uint* Code, + [Out] ulong* Arg1, + [Out] ulong* Arg2, + [Out] ulong* Arg3, + [Out] ulong* Arg4); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberSupportedProcessorTypesDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSupportedProcessorTypesDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [Out] IMAGE_FILE_MACHINE* Types); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessorTypeNamesDelegate( + IntPtr self, + [In] IMAGE_FILE_MACHINE Type, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder FullNameBuffer, + [In] int FullNameBufferSize, + [Out] uint* FullNameSize, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder AbbrevNameBuffer, + [In] int AbbrevNameBufferSize, + [Out] uint* AbbrevNameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEffectiveProcessorTypeDelegate( + IntPtr self, + [Out] IMAGE_FILE_MACHINE* Type); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetEffectiveProcessorTypeDelegate( + IntPtr self, + [In] IMAGE_FILE_MACHINE Type); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExecutionStatusDelegate( + IntPtr self, + [Out] DEBUG_STATUS* Status); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetExecutionStatusDelegate( + IntPtr self, + [In] DEBUG_STATUS Status); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCodeLevelDelegate( + IntPtr self, + [Out] DEBUG_LEVEL* Level); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetCodeLevelDelegate( + IntPtr self, + [In] DEBUG_LEVEL Level); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEngineOptionsDelegate( + IntPtr self, + [Out] DEBUG_ENGOPT* Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddEngineOptionsDelegate( + IntPtr self, + [In] DEBUG_ENGOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveEngineOptionsDelegate( + IntPtr self, + [In] DEBUG_ENGOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetEngineOptionsDelegate( + IntPtr self, + [In] DEBUG_ENGOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSystemErrorControlDelegate( + IntPtr self, + [Out] ERROR_LEVEL* OutputLevel, + [Out] ERROR_LEVEL* BreakLevel); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSystemErrorControlDelegate( + IntPtr self, + [In] ERROR_LEVEL OutputLevel, + [In] ERROR_LEVEL BreakLevel); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTextMacroDelegate( + IntPtr self, + [In] uint Slot, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* MacroSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetTextMacroDelegate( + IntPtr self, + [In] uint Slot, + [In][MarshalAs(UnmanagedType.LPStr)] string Macro); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetRadixDelegate( + IntPtr self, + [Out] uint* Radix); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetRadixDelegate( + IntPtr self, + [In] uint Radix); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int EvaluateDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Expression, + [In] DEBUG_VALUE_TYPE DesiredType, + [Out] DEBUG_VALUE* Value, + [Out] uint* RemainderIndex); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CoerceValueDelegate( + IntPtr self, + [In] DEBUG_VALUE In, + [In] DEBUG_VALUE_TYPE OutType, + [Out] DEBUG_VALUE* Out); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CoerceValuesDelegate( + IntPtr self, + [In] uint Count, + [In][MarshalAs(UnmanagedType.LPArray)] DEBUG_VALUE[] In, + [In][MarshalAs(UnmanagedType.LPArray)] DEBUG_VALUE_TYPE[] OutType, + [Out] DEBUG_VALUE* Out); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ExecuteDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPStr)] string Command, + [In] DEBUG_EXECUTE Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ExecuteCommandFileDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In][MarshalAs(UnmanagedType.LPStr)] string CommandFile, + [In] DEBUG_EXECUTE Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberBreakpointsDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetBreakpointByIndexDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr bp); // out IDebugBreakpoint + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetBreakpointByIdDelegate( + IntPtr self, + [In] uint Id, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr bp); // out IDebugBreakpoint + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetBreakpointParametersDelegate( + IntPtr self, + [In] uint Count, + [In][MarshalAs(UnmanagedType.LPArray)] uint[] Ids, + [In] uint Start, + [Out] DEBUG_BREAKPOINT_PARAMETERS* Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddBreakpointDelegate( + IntPtr self, + [In] DEBUG_BREAKPOINT_TYPE Type, + [In] uint DesiredId, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr bp); // out IDebugBreakpoint + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveBreakpointDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.Interface)] IDebugBreakpoint Bp); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddExtensionDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Path, + [In] uint Flags, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveExtensionDelegate( + IntPtr self, + [In] ulong Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExtensionByPathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Path, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CallExtensionDelegate( + IntPtr self, + [In] ulong Handle, + [In][MarshalAs(UnmanagedType.LPStr)] string Function, + [In][MarshalAs(UnmanagedType.LPStr)] string Arguments); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExtensionFunctionDelegate( + IntPtr self, + [In] ulong Handle, + [In][MarshalAs(UnmanagedType.LPStr)] string FuncName, + [Out] IntPtr* Function); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetWindbgExtensionApis32Delegate( + IntPtr self, + [In][Out] WINDBG_EXTENSION_APIS* Api); + + /* Must be In and Out as the nSize member has to be initialized */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetWindbgExtensionApis64Delegate( + IntPtr self, + [In][Out] WINDBG_EXTENSION_APIS* Api); + + /* Must be In and Out as the nSize member has to be initialized */ + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberEventFiltersDelegate( + IntPtr self, + [Out] uint* SpecificEvents, + [Out] uint* SpecificExceptions, + [Out] uint* ArbitraryExceptions); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEventFilterTextDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* TextSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEventFilterCommandDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* CommandSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetEventFilterCommandDelegate( + IntPtr self, + [In] uint Index, + [In][MarshalAs(UnmanagedType.LPStr)] string Command); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSpecificFilterParametersDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [Out] DEBUG_SPECIFIC_FILTER_PARAMETERS* Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSpecificFilterParametersDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [In][MarshalAs(UnmanagedType.LPArray)] DEBUG_SPECIFIC_FILTER_PARAMETERS[] Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSpecificEventFilterArgumentDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* ArgumentSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSpecificEventFilterArgumentDelegate( + IntPtr self, + [In] uint Index, + [In][MarshalAs(UnmanagedType.LPStr)] string Argument); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExceptionFilterParametersDelegate( + IntPtr self, + [In] uint Count, + [In][MarshalAs(UnmanagedType.LPArray)] uint[] Codes, + [In] uint Start, + [Out] DEBUG_EXCEPTION_FILTER_PARAMETERS* Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetExceptionFilterParametersDelegate( + IntPtr self, + [In] uint Count, + [In][MarshalAs(UnmanagedType.LPArray)] DEBUG_EXCEPTION_FILTER_PARAMETERS[] Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetExceptionFilterSecondCommandDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* CommandSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetExceptionFilterSecondCommandDelegate( + IntPtr self, + [In] uint Index, + [In][MarshalAs(UnmanagedType.LPStr)] string Command); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WaitForEventDelegate( + IntPtr self, + [In] DEBUG_WAIT Flags, + [In] uint Timeout); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLastEventInformationDelegate( + IntPtr self, + [Out] DEBUG_EVENT* Type, + [Out] uint* ProcessId, + [Out] uint* ThreadId, + [In] IntPtr ExtraInformation, + [In] uint ExtraInformationSize, + [Out] uint* ExtraInformationUsed, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Description, + [In] uint DescriptionSize, + [Out] uint* DescriptionUsed); + + #endregion + + #region IDebugControl2 Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentTimeDateDelegate( + IntPtr self, + [Out] uint* TimeDate); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentSystemUpTimeDelegate( + IntPtr self, + [Out] uint* UpTime); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetDumpFormatFlagsDelegate( + IntPtr self, + [Out] DEBUG_FORMAT* FormatFlags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberTextReplacementsDelegate( + IntPtr self, + [Out] uint* NumRepl); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTextReplacementDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string SrcText, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder SrcBuffer, + [In] int SrcBufferSize, + [Out] uint* SrcSize, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder DstBuffer, + [In] int DstBufferSize, + [Out] uint* DstSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetTextReplacementDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string SrcText, + [In][MarshalAs(UnmanagedType.LPStr)] string DstText); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveTextReplacementsDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputTextReplacementsDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] DEBUG_OUT_TEXT_REPL Flags); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugDataSpaces.cs b/src/SOS/SOS.Hosting/dbgeng/DebugDataSpaces.cs new file mode 100644 index 000000000..253d27f11 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugDataSpaces.cs @@ -0,0 +1,282 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; + +namespace SOS +{ + internal unsafe class DebugDataSpaces + { + internal DebugDataSpaces(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugDataSpaces).GUID, validate: true); + AddDebugDataSpaces(builder, soshost); + builder.Complete(); + + builder = client.AddInterface(typeof(IDebugDataSpaces2).GUID, validate: true); + AddDebugDataSpaces2(builder, soshost); + builder.Complete(); + } + + private static void AddDebugDataSpaces(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new ReadVirtualDelegate(soshost.ReadVirtual)); + builder.AddMethod(new WriteVirtualDelegate(soshost.WriteVirtual)); + builder.AddMethod(new SearchVirtualDelegate((self, offset, length, pattern, patternSize, patternGranularity, matchOffset) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadVirtualUncachedDelegate((self, offset, buffer, bufferSize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteVirtualUncachedDelegate((self, offset, buffer, bufferSize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadPointersVirtualDelegate((self, count, offset, ptrs) => DebugClient.NotImplemented)); + builder.AddMethod(new WritePointersVirtualDelegate((self, count, offset, ptrs) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadPhysicalDelegate((self, offset, buffer, bufferSize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WritePhysicalDelegate((self, offset, buffer, bufferSize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadControlDelegate((self, processor, offset, buffer, bufferSize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteControlDelegate((self, processor, offset, buffer, bufferSize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadIoDelegate((self, interfaceType, busNumber, addressSpace, offset, buffer, bufferSize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteIoDelegate((self, interfaceType, busNumber, addressSpace, offset, buffer, bufferSize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadMsrDelegate((self, msr, msrValue) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteMsrDelegate((self, msr, msrValue) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadBusDataDelegate((self, busDataType, busNumber, slotNumber, offset, buffer, bufferSize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteBusDataDelegate((self, busDataType, busNumber, slotNumber, offset, buffer, bufferSize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new CheckLowMemoryDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadDebuggerDataDelegate((self, index, buffer, bufferSize, dataSize) => DebugClient.E_NOTIMPL)); + builder.AddMethod(new ReadProcessorSystemDataDelegate((self, processor, index, buffer, bufferSize, dataSize) => DebugClient.NotImplemented)); + } + + private static void AddDebugDataSpaces2(VTableBuilder builder, SOSHost soshost) + { + AddDebugDataSpaces(builder, soshost); + builder.AddMethod(new VirtualToPhysicalDelegate((self, virtualAddress, physicalAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetVirtualTranslationPhysicalOffsetsDelegate((self, virtualAddress, offsets, offsetsSize, levels) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadHandleDataDelegate((self, handle, dataType, buffer, bufferSize, dataSize) => DebugClient.NotImplemented)); + builder.AddMethod(new FillVirtualDelegate((self, start, size, buffer, patternSize, filled) => DebugClient.NotImplemented)); + builder.AddMethod(new FillPhysicalDelegate((self, start, size, buffer, patternSize, filled) => DebugClient.NotImplemented)); + builder.AddMethod(new QueryVirtualDelegate((self, offset, info) => DebugClient.NotImplemented)); + } + + #region IDebugDataSpaces Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private unsafe delegate int ReadVirtualDelegate( + IntPtr self, + [In] ulong address, + IntPtr buffer, + [In] uint bufferSize, + [Out] uint* bytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteVirtualDelegate( + IntPtr self, + [In] ulong address, + IntPtr buffer, + [In] uint bufferSize, + [Out] uint* bytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SearchVirtualDelegate( + IntPtr self, + [In] ulong Offset, + [In] ulong Length, + [In] byte* pattern, + [In] uint PatternSize, + [In] uint PatternGranularity, + [Out] ulong* MatchOffset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadVirtualUncachedDelegate( + IntPtr self, + [In] ulong Offset, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteVirtualUncachedDelegate( + IntPtr self, + [In] ulong Offset, + [In] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadPointersVirtualDelegate( + IntPtr self, + [In] uint Count, + [In] ulong Offset, + [Out] ulong* Ptrs); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WritePointersVirtualDelegate( + IntPtr self, + [In] uint Count, + [In] ulong Offset, + [In] ulong[] Ptrs); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadPhysicalDelegate( + IntPtr self, + [In] ulong Offset, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WritePhysicalDelegate( + IntPtr self, + [In] ulong Offset, + [In] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadControlDelegate( + IntPtr self, + [In] uint Processor, + [In] ulong Offset, + [Out] byte* buffer, + [In] int BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteControlDelegate( + IntPtr self, + [In] uint Processor, + [In] ulong Offset, + [In] byte* buffer, + [In] int BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadIoDelegate( + IntPtr self, + [In] INTERFACE_TYPE InterfaceType, + [In] uint BusNumber, + [In] uint AddressSpace, + [In] ulong Offset, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteIoDelegate( + IntPtr self, + [In] INTERFACE_TYPE InterfaceType, + [In] uint BusNumber, + [In] uint AddressSpace, + [In] ulong Offset, + [In] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadMsrDelegate( + IntPtr self, + [In] uint Msr, + [Out] ulong* MsrValue); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteMsrDelegate( + IntPtr self, + [In] uint Msr, + [In] ulong MsrValue); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadBusDataDelegate( + IntPtr self, + [In] BUS_DATA_TYPE BusDataType, + [In] uint BusNumber, + [In] uint SlotNumber, + [In] uint Offset, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteBusDataDelegate( + IntPtr self, + [In] BUS_DATA_TYPE BusDataType, + [In] uint BusNumber, + [In] uint SlotNumber, + [In] uint Offset, + [In] byte* buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CheckLowMemoryDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadDebuggerDataDelegate( + IntPtr self, + [In] uint Index, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* DataSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadProcessorSystemDataDelegate( + IntPtr self, + [In] uint Processor, + [In] DEBUG_DATA Index, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* DataSize); + + #endregion + + #region IDebugDataSpaces2 Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int VirtualToPhysicalDelegate( + IntPtr self, + [In] ulong Virtual, + [Out] ulong* Physical); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetVirtualTranslationPhysicalOffsetsDelegate( + IntPtr self, + [In] ulong Virtual, + [Out] ulong* Offsets, + [In] uint OffsetsSize, + [Out] uint* Levels); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadHandleDataDelegate( + IntPtr self, + [In] ulong Handle, + [In] DEBUG_HANDLE_DATA_TYPE DataType, + [Out] byte* buffer, + [In] uint BufferSize, + [Out] uint* DataSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FillVirtualDelegate( + IntPtr self, + [In] ulong Start, + [In] uint Size, + [In] byte* buffer, + [In] uint PatternSize, + [Out] uint* Filled); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FillPhysicalDelegate( + IntPtr self, + [In] ulong Start, + [In] uint Size, + [In] byte* buffer, + [In] uint PatternSize, + [Out] uint* Filled); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int QueryVirtualDelegate( + IntPtr self, + [In] ulong Offset, + [Out] MEMORY_BASIC_INFORMATION64* Info); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugRegisters.cs b/src/SOS/SOS.Hosting/dbgeng/DebugRegisters.cs new file mode 100644 index 000000000..3348c1196 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugRegisters.cs @@ -0,0 +1,110 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class DebugRegisters + { + internal DebugRegisters(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugRegisters).GUID, validate: true); + AddDebugRegisters(builder, soshost); + builder.Complete(); + } + + private static void AddDebugRegisters(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new GetNumberRegistersDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetDescriptionDelegate((self, register, nameBuffer, nameBufferSize, nameSize, desc) => DebugClient.NotImplemented)); + builder.AddMethod(new GetIndexByNameDelegate(soshost.GetIndexByName)); + builder.AddMethod(new GetValueDelegate(soshost.GetValue)); + builder.AddMethod(new SetValueDelegate((self, register, value) => DebugClient.NotImplemented)); + builder.AddMethod(new GetValuesDelegate((self, count, indices, start, values) => DebugClient.NotImplemented)); + builder.AddMethod(new SetValuesDelegate((self, count, indices, start, values) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputRegistersDelegate((self, outputControl, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new GetInstructionOffsetDelegate(soshost.GetInstructionOffset)); + builder.AddMethod(new GetStackOffsetDelegate(soshost.GetStackOffset)); + builder.AddMethod(new GetFrameOffsetDelegate(soshost.GetFrameOffset)); + } + + #region IDebugRegisters Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberRegistersDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetDescriptionDelegate( + IntPtr self, + [In] uint Register, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder NameBuffer, + [In] int NameBufferSize, + [Out] uint* NameSize, + [Out] DEBUG_REGISTER_DESCRIPTION* Desc); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetIndexByNameDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Name, + [Out] out uint Index); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetValueDelegate( + IntPtr self, + [In] uint Register, + [Out] out DEBUG_VALUE Value); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetValueDelegate( + IntPtr self, + [In] uint Register, + [In] DEBUG_VALUE* Value); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetValuesDelegate( //FIX ME!!! This needs to be tested + IntPtr self, + [In] uint Count, + [In] uint* Indices, + [In] uint Start, + [Out] DEBUG_VALUE* Values); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetValuesDelegate( + IntPtr self, + [In] uint Count, + [In] uint* Indices, + [In] uint Start, + [In] DEBUG_VALUE* Values); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputRegistersDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] DEBUG_REGISTERS Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetInstructionOffsetDelegate( + IntPtr self, + [Out] out ulong Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetStackOffsetDelegate( + IntPtr self, + [Out] out ulong Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFrameOffsetDelegate( + IntPtr self, + [Out] out ulong Offset); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugSymbols.cs b/src/SOS/SOS.Hosting/dbgeng/DebugSymbols.cs new file mode 100644 index 000000000..259a160b1 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugSymbols.cs @@ -0,0 +1,1138 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class DebugSymbols + { + internal DebugSymbols(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugSymbols).GUID, validate: true); + AddDebugSymbols(builder, soshost); + builder.Complete(); + + builder = client.AddInterface(typeof(IDebugSymbols2).GUID, validate: true); + AddDebugSymbols2(builder, soshost); + builder.Complete(); + + builder = client.AddInterface(typeof(IDebugSymbols3).GUID, validate: true); + AddDebugSymbols3(builder, soshost); + builder.Complete(); + } + + private static void AddDebugSymbols(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new GetSymbolOptionsDelegate(soshost.GetSymbolOptions)); + builder.AddMethod(new AddSymbolOptionsDelegate((self, options) => DebugClient.S_OK)); + builder.AddMethod(new RemoveSymbolOptionsDelegate((self, options) => DebugClient.S_OK)); + builder.AddMethod(new SetSymbolOptionsDelegate((self, options) => DebugClient.S_OK)); + builder.AddMethod(new GetNameByOffsetDelegate(soshost.GetNameByOffset)); + builder.AddMethod(new GetOffsetByNameDelegate((self, symbol, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNearNameByOffsetDelegate((self, offset, delta, nameBuffer, nameBufferSize, nameSize, displacement) => DebugClient.NotImplemented)); + builder.AddMethod(new GetLineByOffsetDelegate(soshost.GetLineByOffset)); + builder.AddMethod(new GetOffsetByLineDelegate((self, line, file, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberModulesDelegate(soshost.GetNumberModules)); + builder.AddMethod(new GetModuleByIndexDelegate(soshost.GetModuleByIndex)); + builder.AddMethod(new GetModuleByModuleNameDelegate(soshost.GetModuleByModuleName)); + builder.AddMethod(new GetModuleByOffsetDelegate(soshost.GetModuleByOffset)); + builder.AddMethod(new GetModuleNamesDelegate(soshost.GetModuleNames)); + builder.AddMethod(new GetModuleParametersDelegate(soshost.GetModuleParameters)); + builder.AddMethod(new GetSymbolModuleDelegate((self, symbol, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeNameDelegate((self, module, typeId, nameBuffer, nameBufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeIdDelegate((self, module, name, typeId) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeSizeDelegate((self, module, typeId, size) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldOffsetDelegate((self, module, typeId, field, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolTypeIdDelegate((self, symbol, typeId, module) => DebugClient.NotImplemented)); + builder.AddMethod(new GetOffsetTypeIdDelegate((self, offset, typeId, module) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadTypedDataVirtualDelegate((self, offset, module, typeid, buffer, buffersize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteTypedDataVirtualDelegate((self, offset, module, typeid, buffer, buffersize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputTypedDataVirtualDelegate((self, outputControl, offset, module, typeId, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new ReadTypedDataPhysicalDelegate((self, offset, module, typeid, buffer, buffersize, bytesRead) => DebugClient.NotImplemented)); + builder.AddMethod(new WriteTypedDataPhysicalDelegate((self, offset, module, typeid, buffer, buffersize, bytesWritten) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputTypedDataPhysicalDelegate((self, outputControl, offset, module, typeId, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new GetScopeDelegate((self, instructionOffset, scopeFrame, scopeContext, scopeContextSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetScopeDelegate((IntPtr self, ulong instructionOffset, ref DEBUG_STACK_FRAME scopeFrame, IntPtr scopeContext, uint scopeContextSize) => DebugClient.NotImplemented)); + builder.AddMethod(new ResetScopeDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new GetScopeSymbolGroupDelegate((self, flags, update, symbols) => DebugClient.NotImplemented)); + builder.AddMethod(new CreateSymbolGroupDelegate((self, group) => DebugClient.NotImplemented)); + builder.AddMethod(new StartSymbolMatchDelegate((self, pattern, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNextSymbolMatchDelegate((self, handle, buffer, buffesSize, matchSize, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new EndSymbolMatchDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new ReloadDelegate((self, module) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolPathDelegate(soshost.GetSymbolPath)); + builder.AddMethod(new SetSymbolPathDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendSymbolPathDelegate((self, addition) => DebugClient.NotImplemented)); + builder.AddMethod(new GetImagePathDelegate((self, buffer, bufferSize, pathSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetImagePathDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendImagePathDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourcePathDelegate((self, buffer, bufferSize, pathSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourcePathElementDelegate((self, index, buffer, bufferSize, elementSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetSourcePathDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendSourcePathDelegate((self, addition) => DebugClient.NotImplemented)); + builder.AddMethod(new FindSourceFileDelegate(soshost.FindSourceFile)); + builder.AddMethod(new GetSourceFileLineOffsetsDelegate((self, file, buffer, bufferLines, fileLines) => DebugClient.NotImplemented)); + } + + private static void AddDebugSymbols2(VTableBuilder builder, SOSHost soshost) + { + AddDebugSymbols(builder, soshost); + builder.AddMethod(new GetModuleVersionInformationDelegate((self, index, baseAddress, item, buffer, bufferSize, verInfoSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleNameStringDelegate((self, which, index, baseAddress, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetConstantNameDelegate((self, module, typeId, value, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldNameDelegate((self, module, typeId, fieldIndex, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeOptionsDelegate((self, options) => DebugClient.NotImplemented)); + builder.AddMethod(new AddTypeOptionsDelegate((self, options) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveTypeOptionsDelegate((self, options) => DebugClient.NotImplemented)); + builder.AddMethod(new SetTypeOptionsDelegate((self, options) => DebugClient.NotImplemented)); + } + + private static void AddDebugSymbols3(VTableBuilder builder, SOSHost soshost) + { + AddDebugSymbols2(builder, soshost); + builder.AddMethod(new GetNameByOffsetWideDelegate(soshost.GetNameByOffset)); + builder.AddMethod(new GetOffsetByNameWideDelegate((self, symbol, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNearNameByOffsetWideDelegate((self, offset, delta, nameBuffer, nameBufferSize, nameSize, displacement) => DebugClient.NotImplemented)); + builder.AddMethod(new GetLineByOffsetWideDelegate((self, offset, line, fileBuffer, fileBufferSize, fileSize, displacement) => DebugClient.NotImplemented)); + builder.AddMethod(new GetOffsetByLineWideDelegate((self, line, file, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleByModuleNameWideDelegate(soshost.GetModuleByModuleName)); + builder.AddMethod(new GetSymbolModuleWideDelegate((self, symbol, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeNameWideDelegate((self, module, typeId, nameBuffer, nameBufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetTypeIdWideDelegate((self, module, name, typeId) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldOffsetWideDelegate((self, module, typeId, field, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolTypeIdWideDelegate((self, symbol, typeId, module) => DebugClient.NotImplemented)); + builder.AddMethod(new GetScopeSymbolGroup2Delegate((self, flags, update, symbols) => DebugClient.NotImplemented)); + builder.AddMethod(new CreateSymbolGroup2Delegate((self, group) => DebugClient.NotImplemented)); + builder.AddMethod(new StartSymbolMatchWideDelegate((self, pattern, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNextSymbolMatchWideDelegate((self, handle, buffer, buffesSize, matchSize, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new ReloadWideDelegate((self, module) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolPathWideDelegate(soshost.GetSymbolPath)); + builder.AddMethod(new SetSymbolPathWideDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendSymbolPathWideDelegate((self, addition) => DebugClient.NotImplemented)); + builder.AddMethod(new GetImagePathWideDelegate((self, buffer, bufferSize, pathSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetImagePathWideDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendImagePathWideDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourcePathWideDelegate((self, buffer, bufferSize, pathSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourcePathElementWideDelegate((self, index, buffer, bufferSize, elementSize) => DebugClient.NotImplemented)); + builder.AddMethod(new SetSourcePathWideDelegate((self, path) => DebugClient.NotImplemented)); + builder.AddMethod(new AppendSourcePathWideDelegate((self, addition) => DebugClient.NotImplemented)); + builder.AddMethod(new FindSourceFileWideDelegate(soshost.FindSourceFile)); + builder.AddMethod(new GetSourceFileLineOffsetsWideDelegate((self, file, buffer, bufferLines, fileLines) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleVersionInformationWideDelegate((self, index, baseAddress, item, buffer, bufferSize, verInfoSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleNameStringWideDelegate((self, which, index, baseAddress, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetConstantNameWideDelegate((self, module, typeId, value, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldNameWideDelegate((self, module, typeId, fieldIndex, buffer, bufferSize, nameSize) => DebugClient.NotImplemented)); + builder.AddMethod(new IsManagedModuleDelegate((self, index, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleByModuleName2Delegate((self, name, startIndex, flags, index, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleByModuleName2WideDelegate((self, name, startIndex, flags, index, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetModuleByOffset2Delegate((self, offset, startIndex, flags, index, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new AddSyntheticModuleDelegate((self, baseAddress, size, imagePath, moduleName, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new AddSyntheticModuleWideDelegate((self, baseAddress, size, imagePath, moduleName, flags) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveSyntheticModuleDelegate((self, baseAddress) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentScopeFrameIndexDelegate((self, index) => DebugClient.NotImplemented)); + builder.AddMethod(new SetScopeFrameByIndexDelegate((self, index) => DebugClient.NotImplemented)); + builder.AddMethod(new SetScopeFromJitDebugInfoDelegate((self, outputControl, infoOffset) => DebugClient.NotImplemented)); + builder.AddMethod(new SetScopeFromStoredEventDelegate((self) => DebugClient.NotImplemented)); + builder.AddMethod(new OutputSymbolByOffsetDelegate((self, outputControl, flags, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFunctionEntryByOffsetDelegate((self, offset, flags, buffer, buffersize, bufferNeeded) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldTypeAndOffsetDelegate((self, module, containerTypeId, field, fieldTypeId, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetFieldTypeAndOffsetWideDelegate((self, module, containerTypeId, field, fieldTypeId, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new AddSyntheticSymbolDelegate((self, offset, size, name, flags, id) => DebugClient.NotImplemented)); + builder.AddMethod(new AddSyntheticSymbolWideDelegate((self, offset, size, name, flags, id) => DebugClient.NotImplemented)); + builder.AddMethod(new RemoveSyntheticSymbolDelegate((self, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntriesByOffsetDelegate((self, offset, flags, ids, displacement, idsCount, entries) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntriesByNameDelegate((self, symbol, flags, ids, idsCount, entries) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntriesByNameWideDelegate((self, symbol, flags, ids, idsCount, entries) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryByTokenDelegate((self, moduleBase, token, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryInformationDelegate((self, id, info) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryStringDelegate((self, id, which, buffer, bufferSize, stringSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryStringWideDelegate((self, id, which, buffer, bufferSize, stringSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryOffsetRegionsDelegate((self, id, flags, regions, regionsCount, regionsAvail) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSymbolEntryBySymbolEntryDelegate((self, fromId, flags, toId) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntriesByOffsetDelegate((self, offset, flags, entries, entriesCount, entriesAvail) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntriesByLineDelegate((self, line, file, flags, entries, entriesCount, entriesAvail) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntriesByLineWideDelegate((self, line, file, flags, entries, entriesCount, entriesAvail) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntryStringDelegate((self, entry, which, buffer, bufferSize, stringSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntryStringWideDelegate((self, entry, which, buffer, bufferSize, stringSize) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntryOffsetRegionsDelegate((self, entry, flags, regions, regionsCount, regionsAvail) => DebugClient.NotImplemented)); + builder.AddMethod(new GetSourceEntryBySourceEntryDelegate((self, fromEntry, flags, toEntry) => DebugClient.NotImplemented)); + } + + #region IDebugSymbols Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolOptionsDelegate( + IntPtr self, + [Out] out SYMOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddSymbolOptionsDelegate( + IntPtr self, + [In] SYMOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveSymbolOptionsDelegate( + IntPtr self, + [In] SYMOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSymbolOptionsDelegate( + IntPtr self, + [In] SYMOPT Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private unsafe delegate int GetNameByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder NameBuffer, + [In] uint NameBufferSize, + [Out] uint* NameSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOffsetByNameDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Symbol, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNearNameByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [In] int Delta, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder NameBuffer, + [In] int NameBufferSize, + [Out] uint* NameSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLineByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Line, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder FileBuffer, + [In] uint FileBufferSize, + [Out] uint* FileSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOffsetByLineDelegate( + IntPtr self, + [In] uint Line, + [In][MarshalAs(UnmanagedType.LPStr)] string File, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberModulesDelegate( + IntPtr self, + [Out] out uint Loaded, + [Out] out uint Unloaded); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByIndexDelegate( + IntPtr self, + [In] uint Index, + [Out] out ulong Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByModuleNameDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Name, + [In] uint StartIndex, + [Out] uint* Index, + [Out] ulong* Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [In] uint StartIndex, + [Out] uint* Index, + [Out] ulong* Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleNamesDelegate( + IntPtr self, + [In] uint Index, + [In] ulong Base, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder ImageNameBuffer, + [In] uint ImageNameBufferSize, + [Out] uint* ImageNameSize, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder ModuleNameBuffer, + [In] uint ModuleNameBufferSize, + [Out] uint* ModuleNameSize, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder LoadedImageNameBuffer, + [In] uint LoadedImageNameBufferSize, + [Out] uint* LoadedImageNameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleParametersDelegate( + IntPtr self, + [In] uint Count, + [In] ulong* Bases, + [In] uint Start, + [Out] DEBUG_MODULE_PARAMETERS* Params); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolModuleDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Symbol, + [Out] ulong* Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeNameDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder NameBuffer, + [In] int NameBufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeIdDelegate( + IntPtr self, + [In] ulong Module, + [In][MarshalAs(UnmanagedType.LPStr)] string Name, + [Out] uint* TypeId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeSizeDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [Out] uint* Size); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldOffsetDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In][MarshalAs(UnmanagedType.LPStr)] string Field, + [Out] uint* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolTypeIdDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Symbol, + [Out] uint* TypeId, + [Out] ulong* Module); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOffsetTypeIdDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* TypeId, + [Out] ulong* Module); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadTypedDataVirtualDelegate( + IntPtr self, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [Out] byte* Buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteTypedDataVirtualDelegate( + IntPtr self, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [In] IntPtr Buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputTypedDataVirtualDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [In] DEBUG_TYPEOPTS Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReadTypedDataPhysicalDelegate( + IntPtr self, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [In] IntPtr Buffer, + [In] uint BufferSize, + [Out] uint* BytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int WriteTypedDataPhysicalDelegate( + IntPtr self, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [In] IntPtr Buffer, + [In] uint BufferSize, + [Out] uint* BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputTypedDataPhysicalDelegate( + IntPtr self, + [In] DEBUG_OUTCTL OutputControl, + [In] ulong Offset, + [In] ulong Module, + [In] uint TypeId, + [In] DEBUG_TYPEOPTS Flags); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetScopeDelegate( + IntPtr self, + [Out] ulong* InstructionOffset, + [Out] DEBUG_STACK_FRAME* ScopeFrame, + [In] IntPtr ScopeContext, + [In] uint ScopeContextSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetScopeDelegate( + IntPtr self, + [In] ulong InstructionOffset, + [In] ref DEBUG_STACK_FRAME ScopeFrame, + [In] IntPtr ScopeContext, + [In] uint ScopeContextSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ResetScopeDelegate( + IntPtr self); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetScopeSymbolGroupDelegate( + IntPtr self, + [In] DEBUG_SCOPE_GROUP Flags, + [In][MarshalAs(UnmanagedType.Interface)] IDebugSymbolGroup Update, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Symbols); // out IDebugSymbolGroup + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CreateSymbolGroupDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Group); // out IDebugSymbolGroup + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int StartSymbolMatchDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Pattern, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNextSymbolMatchDelegate( + IntPtr self, + [In] ulong Handle, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* MatchSize, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int EndSymbolMatchDelegate( + IntPtr self, + [In] ulong Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReloadDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Module); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolPathDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSymbolPathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendSymbolPathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetImagePathDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetImagePathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendImagePathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourcePathDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourcePathElementDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* ElementSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSourcePathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendSourcePathDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FindSourceFileDelegate( + IntPtr self, + [In] uint StartElement, + [In][MarshalAs(UnmanagedType.LPStr)] string File, + [In] DEBUG_FIND_SOURCE Flags, + [Out] uint* FoundElement, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] uint BufferSize, + [Out] uint* FoundSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceFileLineOffsetsDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string File, + [Out] ulong* Buffer, + [In] int BufferLines, + [Out] uint* FileLines); + + #endregion + + #region IDebugSymbols2 Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleVersionInformationDelegate( + IntPtr self, + [In] uint Index, + [In] ulong Base, + [In][MarshalAs(UnmanagedType.LPStr)] string Item, + [Out] byte* Buffer, + [In] uint BufferSize, + [Out] uint* VerInfoSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleNameStringDelegate( + IntPtr self, + [In] DEBUG_MODNAME Which, + [In] uint Index, + [In] ulong Base, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] uint BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetConstantNameDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In] ulong Value, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldNameDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In] uint FieldIndex, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeOptionsDelegate( + IntPtr self, + [Out] DEBUG_TYPEOPTS* Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddTypeOptionsDelegate( + IntPtr self, + [In] DEBUG_TYPEOPTS Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveTypeOptionsDelegate( + IntPtr self, + [In] DEBUG_TYPEOPTS Options); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetTypeOptionsDelegate( + IntPtr self, + [In] DEBUG_TYPEOPTS Options); + + #endregion + + #region IDebugSymbols3 Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNameByOffsetWideDelegate( + IntPtr self, + [In] ulong Offset, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder NameBuffer, + [In] uint NameBufferSize, + [Out] uint* NameSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOffsetByNameWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Symbol, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNearNameByOffsetWideDelegate( + IntPtr self, + [In] ulong Offset, + [In] int Delta, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder NameBuffer, + [In] int NameBufferSize, + [Out] uint* NameSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetLineByOffsetWideDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Line, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder FileBuffer, + [In] int FileBufferSize, + [Out] uint* FileSize, + [Out] ulong* Displacement); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetOffsetByLineWideDelegate( + IntPtr self, + [In] uint Line, + [In][MarshalAs(UnmanagedType.LPWStr)] string File, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByModuleNameWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Name, + [In] uint StartIndex, + [Out] uint* Index, + [Out] ulong* Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolModuleWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Symbol, + [Out] ulong* Base); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeNameWideDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder NameBuffer, + [In] int NameBufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTypeIdWideDelegate( + IntPtr self, + [In] ulong Module, + [In][MarshalAs(UnmanagedType.LPWStr)] string Name, + [Out] uint* TypeId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldOffsetWideDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In][MarshalAs(UnmanagedType.LPWStr)] string Field, + [Out] uint* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolTypeIdWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Symbol, + [Out] uint* TypeId, + [Out] ulong* Module); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetScopeSymbolGroup2Delegate( + IntPtr self, + [In] DEBUG_SCOPE_GROUP Flags, + [In][MarshalAs(UnmanagedType.Interface)] IDebugSymbolGroup2 Update, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Symbols); // out IDebugSymbolGroup2 + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int CreateSymbolGroup2Delegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.Interface)] IntPtr Group); // out IDebugSymbolGroup2 + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int StartSymbolMatchWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Pattern, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNextSymbolMatchWideDelegate( + IntPtr self, + [In] ulong Handle, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* MatchSize, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int ReloadWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Module); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolPathWideDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSymbolPathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendSymbolPathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetImagePathWideDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetImagePathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendImagePathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourcePathWideDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* PathSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourcePathElementWideDelegate( + IntPtr self, + [In] uint Index, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* ElementSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetSourcePathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Path); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AppendSourcePathWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Addition); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int FindSourceFileWideDelegate( + IntPtr self, + [In] uint StartElement, + [In][MarshalAs(UnmanagedType.LPWStr)] string File, + [In] DEBUG_FIND_SOURCE Flags, + [Out] uint* FoundElement, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] uint BufferSize, + [Out] uint* FoundSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceFileLineOffsetsWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string File, + [Out] ulong* Buffer, + [In] int BufferLines, + [Out] uint* FileLines); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleVersionInformationWideDelegate( + IntPtr self, + [In] uint Index, + [In] ulong Base, + [In][MarshalAs(UnmanagedType.LPWStr)] string Item, + [In] IntPtr Buffer, + [In] int BufferSize, + [Out] uint* VerInfoSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleNameStringWideDelegate( + IntPtr self, + [In] DEBUG_MODNAME Which, + [In] uint Index, + [In] ulong Base, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetConstantNameWideDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In] ulong Value, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldNameWideDelegate( + IntPtr self, + [In] ulong Module, + [In] uint TypeId, + [In] uint FieldIndex, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* NameSize); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int IsManagedModuleDelegate( + IntPtr self, + [In] uint Index, + [In] ulong Base + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByModuleName2Delegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Name, + [In] uint StartIndex, + [In] DEBUG_GETMOD Flags, + [Out] uint* Index, + [Out] ulong* Base + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByModuleName2WideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Name, + [In] uint StartIndex, + [In] DEBUG_GETMOD Flags, + [Out] uint* Index, + [Out] ulong* Base + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetModuleByOffset2Delegate( + IntPtr self, + [In] ulong Offset, + [In] uint StartIndex, + [In] DEBUG_GETMOD Flags, + [Out] uint* Index, + [Out] ulong* Base + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddSyntheticModuleDelegate( + IntPtr self, + [In] ulong Base, + [In] uint Size, + [In][MarshalAs(UnmanagedType.LPStr)] string ImagePath, + [In][MarshalAs(UnmanagedType.LPStr)] string ModuleName, + [In] DEBUG_ADDSYNTHMOD Flags + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddSyntheticModuleWideDelegate( + IntPtr self, + [In] ulong Base, + [In] uint Size, + [In][MarshalAs(UnmanagedType.LPWStr)] string ImagePath, + [In][MarshalAs(UnmanagedType.LPWStr)] string ModuleName, + [In] DEBUG_ADDSYNTHMOD Flags + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveSyntheticModuleDelegate( + IntPtr self, + [In] ulong Base + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentScopeFrameIndexDelegate( + IntPtr self, + [Out] uint* Index + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetScopeFrameByIndexDelegate( + IntPtr self, + [In] uint Index + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetScopeFromJitDebugInfoDelegate( + IntPtr self, + [In] uint OutputControl, + [In] ulong InfoOffset + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetScopeFromStoredEventDelegate( + IntPtr self + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int OutputSymbolByOffsetDelegate( + IntPtr self, + [In] uint OutputControl, + [In] DEBUG_OUTSYM Flags, + [In] ulong Offset + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFunctionEntryByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [In] DEBUG_GETFNENT Flags, + [In] IntPtr Buffer, + [In] uint BufferSize, + [Out] uint* BufferNeeded + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldTypeAndOffsetDelegate( + IntPtr self, + [In] ulong Module, + [In] uint ContainerTypeId, + [In][MarshalAs(UnmanagedType.LPStr)] string Field, + [Out] uint* FieldTypeId, + [Out] uint* Offset + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetFieldTypeAndOffsetWideDelegate( + IntPtr self, + [In] ulong Module, + [In] uint ContainerTypeId, + [In][MarshalAs(UnmanagedType.LPWStr)] string Field, + [Out] uint* FieldTypeId, + [Out] uint* Offset + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddSyntheticSymbolDelegate( + IntPtr self, + [In] ulong Offset, + [In] uint Size, + [In][MarshalAs(UnmanagedType.LPStr)] string Name, + [In] DEBUG_ADDSYNTHSYM Flags, + [Out] DEBUG_MODULE_AND_ID* Id + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int AddSyntheticSymbolWideDelegate( + IntPtr self, + [In] ulong Offset, + [In] uint Size, + [In][MarshalAs(UnmanagedType.LPWStr)] string Name, + [In] DEBUG_ADDSYNTHSYM Flags, + [Out] DEBUG_MODULE_AND_ID* Id + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int RemoveSyntheticSymbolDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID Id + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntriesByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [In] uint Flags, + [Out] DEBUG_MODULE_AND_ID* Ids, + [Out] ulong* Displacements, + [In] uint IdsCount, + [Out] uint* Entries + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntriesByNameDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStr)] string Symbol, + [In] uint Flags, + [Out] DEBUG_MODULE_AND_ID* Ids, + [In] uint IdsCount, + [Out] uint* Entries + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntriesByNameWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPWStr)] string Symbol, + [In] uint Flags, + [Out] DEBUG_MODULE_AND_ID* Ids, + [In] uint IdsCount, + [Out] uint* Entries + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryByTokenDelegate( + IntPtr self, + [In] ulong ModuleBase, + [In] uint Token, + [Out] DEBUG_MODULE_AND_ID* Id + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryInformationDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID Id, + [Out] DEBUG_SYMBOL_ENTRY* Info + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryStringDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID Id, + [In] uint Which, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* StringSize + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryStringWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID Id, + [In] uint Which, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* StringSize + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryOffsetRegionsDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID Id, + [In] uint Flags, + [Out] DEBUG_OFFSET_REGION* Regions, + [In] uint RegionsCount, + [Out] uint* RegionsAvail + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSymbolEntryBySymbolEntryDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_MODULE_AND_ID FromId, + [In] uint Flags, + [Out] DEBUG_MODULE_AND_ID* ToId + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntriesByOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [In] uint Flags, + [Out] DEBUG_SYMBOL_SOURCE_ENTRY* Entries, + [In] uint EntriesCount, + [Out] uint* EntriesAvail + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntriesByLineDelegate( + IntPtr self, + [In] uint Line, + [In][MarshalAs(UnmanagedType.LPStr)] string File, + [In] uint Flags, + [Out] DEBUG_SYMBOL_SOURCE_ENTRY* Entries, + [In] uint EntriesCount, + [Out] uint* EntriesAvail + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntriesByLineWideDelegate( + IntPtr self, + [In] uint Line, + [In][MarshalAs(UnmanagedType.LPWStr)] string File, + [In] uint Flags, + [Out] DEBUG_SYMBOL_SOURCE_ENTRY* Entries, + [In] uint EntriesCount, + [Out] uint* EntriesAvail + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntryStringDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_SYMBOL_SOURCE_ENTRY Entry, + [In] uint Which, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* StringSize + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntryStringWideDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_SYMBOL_SOURCE_ENTRY Entry, + [In] uint Which, + [Out][MarshalAs(UnmanagedType.LPWStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* StringSize + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntryOffsetRegionsDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_SYMBOL_SOURCE_ENTRY Entry, + [In] uint Flags, + [Out] DEBUG_OFFSET_REGION* Regions, + [In] uint RegionsCount, + [Out] uint* RegionsAvail + ); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetSourceEntryBySourceEntryDelegate( + IntPtr self, + [In][MarshalAs(UnmanagedType.LPStruct)] DEBUG_SYMBOL_SOURCE_ENTRY FromEntry, + [In] uint Flags, + [Out] DEBUG_SYMBOL_SOURCE_ENTRY* ToEntry + ); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.Hosting/dbgeng/DebugSystemObjects.cs b/src/SOS/SOS.Hosting/dbgeng/DebugSystemObjects.cs new file mode 100644 index 000000000..54a7cf866 --- /dev/null +++ b/src/SOS/SOS.Hosting/dbgeng/DebugSystemObjects.cs @@ -0,0 +1,222 @@ +// 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.Diagnostics.Runtime.Interop; +using Microsoft.Diagnostics.Runtime.Utilities; +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace SOS +{ + internal unsafe class DebugSystemObjects + { + internal DebugSystemObjects(DebugClient client, SOSHost soshost) + { + VTableBuilder builder = client.AddInterface(typeof(IDebugSystemObjects).GUID, validate: true); + AddDebugSystemObjects(builder, soshost); + builder.Complete(); + } + + private static void AddDebugSystemObjects(VTableBuilder builder, SOSHost soshost) + { + builder.AddMethod(new GetEventThreadDelegate((self, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetEventProcessDelegate((self, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentThreadIdDelegate(soshost.GetCurrentThreadId)); + builder.AddMethod(new SetCurrentThreadIdDelegate(soshost.SetCurrentThreadId)); + builder.AddMethod(new GetCurrentProcessIdDelegate(soshost.GetCurrentProcessId)); + builder.AddMethod(new SetCurrentProcessIdDelegate((self, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberThreadsDelegate(soshost.GetNumberThreads)); + builder.AddMethod(new GetTotalNumberThreadsDelegate(soshost.GetTotalNumberThreads)); + builder.AddMethod(new GetThreadIdsByIndexDelegate(soshost.GetThreadIdsByIndex)); + builder.AddMethod(new GetThreadIdByProcessorDelegate((self, processor, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentThreadDataOffsetDelegate((self, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetThreadIdByDataOffsetDelegate((self, offset, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentThreadTebDelegate(soshost.GetCurrentThreadTeb)); + builder.AddMethod(new GetThreadIdByTebDelegate((self, offset, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentThreadSystemIdDelegate(soshost.GetCurrentThreadSystemId)); + builder.AddMethod(new GetThreadIdBySystemIdDelegate(soshost.GetThreadIdBySystemId)); + builder.AddMethod(new GetCurrentThreadHandleDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new GetThreadIdByHandleDelegate((self, handle, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetNumberProcessesDelegate((self, number) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessIdsByIndexDelegate((self, start, count, ids, sysIds) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentProcessDataOffsetDelegate((self, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessIdByDataOffsetDelegate((self, offset, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentProcessPebDelegate((self, offset) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessIdByPebDelegate((self, offset, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentProcessSystemIdDelegate((self, sysId) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessIdBySystemIdDelegate((self, sysId, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentProcessHandleDelegate((self, handle) => DebugClient.NotImplemented)); + builder.AddMethod(new GetProcessIdByHandleDelegate((self, handle, id) => DebugClient.NotImplemented)); + builder.AddMethod(new GetCurrentProcessExecutableNameDelegate((self, buffer, bufferSize, exeSize) => DebugClient.NotImplemented)); + } + + #region IDebugSystemObjects Delegates + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEventThreadDelegate( + IntPtr self, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetEventProcessDelegate( + IntPtr self, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadIdDelegate( + IntPtr self, + [Out] out uint Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetCurrentThreadIdDelegate( + IntPtr self, + [In] uint Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessIdDelegate( + IntPtr self, + [Out] out uint Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int SetCurrentProcessIdDelegate( + IntPtr self, + [In] uint Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberThreadsDelegate( + IntPtr self, + [Out] out uint Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetTotalNumberThreadsDelegate( + IntPtr self, + [Out] out uint Total, + [Out] out uint LargestProcess); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdsByIndexDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [Out] uint* Ids, + [Out] uint* SysIds); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdByProcessorDelegate( + IntPtr self, + [In] uint Processor, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadDataOffsetDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdByDataOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadTebDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdByTebDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadSystemIdDelegate( + IntPtr self, + [Out] out uint SysId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdBySystemIdDelegate( + IntPtr self, + [In] uint SysId, + [Out] out uint Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentThreadHandleDelegate( + IntPtr self, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetThreadIdByHandleDelegate( + IntPtr self, + [In] ulong Handle, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetNumberProcessesDelegate( + IntPtr self, + [Out] uint* Number); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessIdsByIndexDelegate( + IntPtr self, + [In] uint Start, + [In] uint Count, + [Out] uint* Ids, + [Out] uint* SysIds); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessDataOffsetDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessIdByDataOffsetDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessPebDelegate( + IntPtr self, + [Out] ulong* Offset); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessIdByPebDelegate( + IntPtr self, + [In] ulong Offset, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessSystemIdDelegate( + IntPtr self, + [Out] uint* SysId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessIdBySystemIdDelegate( + IntPtr self, + [In] uint SysId, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessHandleDelegate( + IntPtr self, + [Out] ulong* Handle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetProcessIdByHandleDelegate( + IntPtr self, + [In] ulong Handle, + [Out] uint* Id); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + private delegate int GetCurrentProcessExecutableNameDelegate( + IntPtr self, + [Out][MarshalAs(UnmanagedType.LPStr)] StringBuilder Buffer, + [In] int BufferSize, + [Out] uint* ExeSize); + + #endregion + } +} \ No newline at end of file diff --git a/src/SOS/SOS.NETCore/SymbolReader.cs b/src/SOS/SOS.NETCore/SymbolReader.cs index 9bd04f220..28d24c627 100644 --- a/src/SOS/SOS.NETCore/SymbolReader.cs +++ b/src/SOS/SOS.NETCore/SymbolReader.cs @@ -262,8 +262,12 @@ namespace SOS var machOFile = new MachOFile(new StreamAddressSpace(stream), 0, true); generator = new MachOFileKeyGenerator(s_tracer, machOFile, moduleFilePath); } - else + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { + var peFile = new PEFile(new StreamAddressSpace(stream), true); + generator = new PEFileKeyGenerator(s_tracer, peFile, moduleFilePath); + } + else { return; } diff --git a/src/SOS/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt b/src/SOS/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt index 3ccab463b..6880bfc6e 100644 --- a/src/SOS/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt +++ b/src/SOS/SOS.UnitTests/ConfigFiles/Windows/Debugger.Tests.Config.txt @@ -60,6 +60,11 @@ $(RepoRootDir)\.dotnet\shared\Microsoft.NETCore.App\$(RuntimeVersion21) + + + $(RepoRootDir)\.dotnet\dotnet.exe --fx-version $(RuntimeFrameworkVersion) $(RepoRootDir)\.dotnet\shared\Microsoft.NETCore.App\$(RuntimeFrameworkVersion) diff --git a/src/SOS/SOS.UnitTests/SOS.cs b/src/SOS/SOS.UnitTests/SOS.cs index fc8796df9..16f439203 100644 --- a/src/SOS/SOS.UnitTests/SOS.cs +++ b/src/SOS/SOS.UnitTests/SOS.cs @@ -82,8 +82,8 @@ public class SOS } // With the dotnet-dump analyze tool - if (OS.Kind == OSKind.Linux) - { + if (config.DotNetDumpPath() != null) + { using (SOSRunner runner = await SOSRunner.StartDebugger(config, Output, testName, debuggeeName, debuggeeArguments, SOSRunner.Options.LoadDumpWithDotNetDump)) { await runner.RunScript(scriptName); diff --git a/src/SOS/SOS.UnitTests/SOSRunner.cs b/src/SOS/SOS.UnitTests/SOSRunner.cs index ef87e3b28..839df9d59 100644 --- a/src/SOS/SOS.UnitTests/SOSRunner.cs +++ b/src/SOS/SOS.UnitTests/SOSRunner.cs @@ -730,7 +730,12 @@ public class SOSRunner : IDisposable switch (OS.Kind) { case OSKind.Windows: - return NativeDebugger.Cdb; + switch (options) { + case Options.LoadDumpWithDotNetDump: + return NativeDebugger.DotNetDump; + default: + return NativeDebugger.Cdb; + } case OSKind.Linux: case OSKind.OSX: diff --git a/src/SOS/Strike/Strike.vcxproj b/src/SOS/Strike/Strike.vcxproj index ca82bf2b2..9f5e15cb1 100644 --- a/src/SOS/Strike/Strike.vcxproj +++ b/src/SOS/Strike/Strike.vcxproj @@ -20,7 +20,7 @@ {41F59D85-FC36-3015-861B-F177863252BC} - 10.0.17134.0 + 10.0 Win32Proj x64 Strike @@ -30,7 +30,7 @@ DynamicLibrary MultiByte - v141 + v142 DynamicLibrary @@ -114,7 +114,7 @@ _MT true Level3 - FEATURE_PAL;DEBUG;_DEBUG;_DBG;URTBLDENV_FRIENDLY=Checked;BUILDENV_CHECKED=1;_AMD64_;_WIN64;AMD64;BIT64=1;_TARGET_64BIT_=1;_TARGET_AMD64_=1;DBG_TARGET_64BIT=1;DBG_TARGET_AMD64=1;DBG_TARGET_WIN64=1;WIN32;_WIN32;WINVER=0x0602;_WIN32_WINNT=0x0602;WIN32_LEAN_AND_MEAN=1;_CRT_SECURE_NO_WARNINGS;FEATURE_CORESYSTEM;FEATURE_COMINTEROP;FEATURE_HIJACK;_SECURE_SCL=0;_TARGET_WIN64_=1;SOS_TARGET_AMD64=1;SOS_TARGET_ARM64=1;STRIKE;USE_STL;FX_VER_INTERNALNAME_STR=SOS.dll;CMAKE_INTDIR="Debug";sos_EXPORTS;%(PreprocessorDefinitions) + DEBUG;_DEBUG;_DBG;URTBLDENV_FRIENDLY=Checked;BUILDENV_CHECKED=1;_AMD64_;_WIN64;AMD64;BIT64=1;_TARGET_64BIT_=1;_TARGET_AMD64_=1;DBG_TARGET_64BIT=1;DBG_TARGET_AMD64=1;DBG_TARGET_WIN64=1;WIN32;_WIN32;WINVER=0x0602;_WIN32_WINNT=0x0602;WIN32_LEAN_AND_MEAN=1;_CRT_SECURE_NO_WARNINGS;FEATURE_CORESYSTEM;FEATURE_COMINTEROP;FEATURE_HIJACK;_SECURE_SCL=0;_TARGET_WIN64_=1;SOS_TARGET_AMD64=1;SOS_TARGET_ARM64=1;STRIKE;USE_STL;FX_VER_INTERNALNAME_STR=SOS.dll;CMAKE_INTDIR="Debug";sos_EXPORTS;%(PreprocessorDefinitions) $(IntDir) diff --git a/src/SOS/Strike/datatarget.cpp b/src/SOS/Strike/datatarget.cpp index 543340114..71970e6f3 100644 --- a/src/SOS/Strike/datatarget.cpp +++ b/src/SOS/Strike/datatarget.cpp @@ -208,7 +208,7 @@ DataTarget::GetThreadContext( } return g_ExtServices->GetThreadContextById(threadID, contextFlags, contextSize, context); #else - if (g_ExtSystem == NULL || g_ExtAdvanced3 == NULL) + if (g_ExtSystem == NULL || g_ExtAdvanced == NULL) { return E_UNEXPECTED; } @@ -239,7 +239,7 @@ DataTarget::GetThreadContext( ((CONTEXT*) context)->ContextFlags = contextFlags; // Ok, do it! - hr = g_ExtAdvanced3->GetThreadContext((LPVOID) context, contextSize); + hr = g_ExtAdvanced->GetThreadContext((LPVOID) context, contextSize); // This is cleanup; failure here doesn't mean GetThreadContext should fail // (that's determined by hr). diff --git a/src/SOS/Strike/exts.cpp b/src/SOS/Strike/exts.cpp index 4df9234bf..ed40770d0 100644 --- a/src/SOS/Strike/exts.cpp +++ b/src/SOS/Strike/exts.cpp @@ -21,23 +21,18 @@ extern void SOSShutdown(); // WINDBG_EXTENSION_APIS ExtensionApis; -ULONG PageSize; - OnUnloadTask *OnUnloadTask::s_pUnloadTaskList = NULL; // // Valid for the lifetime of the debug session. // -ULONG TargetMachine; -BOOL Connected; -ULONG g_TargetClass; DWORD_PTR g_filterHint = 0; PDEBUG_CLIENT g_ExtClient; PDEBUG_DATA_SPACES2 g_ExtData2; PDEBUG_SYMBOLS2 g_ExtSymbols2; -PDEBUG_ADVANCED3 g_ExtAdvanced3; +PDEBUG_ADVANCED g_ExtAdvanced; PDEBUG_CLIENT g_pCallbacksClient; #else @@ -97,7 +92,7 @@ ExtQuery(ILLDBServices* services) #ifndef FEATURE_PAL SOS_ExtQueryFailGo(g_ExtData2, IDebugDataSpaces2); SOS_ExtQueryFailGo(g_ExtSymbols2, IDebugSymbols2); - SOS_ExtQueryFailGo(g_ExtAdvanced3, IDebugAdvanced3); + SOS_ExtQueryFailGo(g_ExtAdvanced, IDebugAdvanced); #endif // FEATURE_PAL return S_OK; @@ -165,7 +160,7 @@ ExtRelease(void) #ifndef FEATURE_PAL EXT_RELEASE(g_ExtData2); EXT_RELEASE(g_ExtSymbols2); - EXT_RELEASE(g_ExtAdvanced3); + EXT_RELEASE(g_ExtAdvanced); g_ExtClient = NULL; #else EXT_RELEASE(g_DebugClient); @@ -204,6 +199,11 @@ void CleanupEventCallbacks() bool g_Initialized = false; +bool IsInitializedByDbgEng() +{ + return g_Initialized; +} + extern "C" HRESULT CALLBACK @@ -240,7 +240,7 @@ DebugExtensionInitialize(PULONG Version, PULONG Flags) } // Fixes the "Unable to read dynamic function table entries" error messages by disabling the WinDbg security - // feature that prevents the loading of unknown out of proc tack walkers. + // feature that prevents the loading of unknown out of proc stack walkers. DebugControl->Execute(DEBUG_OUTCTL_IGNORE, ".settings set EngineInitialization.VerifyFunctionTableCallbacks=false", DEBUG_EXECUTE_NOT_LOGGED | DEBUG_EXECUTE_NO_REPEAT); @@ -289,69 +289,6 @@ void CALLBACK DebugExtensionNotify(ULONG Notify, ULONG64 /*Argument*/) { - // - // The first time we actually connect to a target, get the page size - // - - if ((Notify == DEBUG_NOTIFY_SESSION_ACCESSIBLE) && (!Connected)) - { - IDebugClient *DebugClient; - PDEBUG_DATA_SPACES DebugDataSpaces; - PDEBUG_CONTROL DebugControl; - HRESULT Hr; - ULONG64 Page; - - if ((Hr = DebugCreate(__uuidof(IDebugClient), - (void **)&DebugClient)) == S_OK) - { - // - // Get the page size and PAE enable flag - // - - if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugDataSpaces), - (void **)&DebugDataSpaces)) == S_OK) - { - if ((Hr = DebugDataSpaces->ReadDebuggerData( - DEBUG_DATA_MmPageSize, &Page, - sizeof(Page), NULL)) == S_OK) - { - PageSize = (ULONG)(ULONG_PTR)Page; - } - - DebugDataSpaces->Release(); - } - // - // Get the architecture type. - // - - if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl), - (void **)&DebugControl)) == S_OK) - { - if ((Hr = DebugControl->GetActualProcessorType( - &TargetMachine)) == S_OK) - { - Connected = TRUE; - } - ULONG Qualifier; - if ((Hr = DebugControl->GetDebuggeeType(&g_TargetClass, &Qualifier)) == S_OK) - { - } - - DebugControl->Release(); - } - - DebugClient->Release(); - } - } - - - if (Notify == DEBUG_NOTIFY_SESSION_INACTIVE) - { - Connected = FALSE; - PageSize = 0; - TargetMachine = 0; - } - return; } @@ -365,30 +302,6 @@ DebugExtensionUninitialize(void) return; } - -BOOL DllInit( - HANDLE /*hModule*/, - DWORD dwReason, - DWORD /*dwReserved*/ - ) -{ - switch (dwReason) { - case DLL_THREAD_ATTACH: - break; - - case DLL_THREAD_DETACH: - break; - - case DLL_PROCESS_DETACH: - break; - - case DLL_PROCESS_ATTACH: - break; - } - - return TRUE; -} - BOOL WINAPI DllMain(HANDLE hInstance, DWORD dwReason, LPVOID lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) diff --git a/src/SOS/Strike/exts.h b/src/SOS/Strike/exts.h index 0d7ad392d..46a5916f4 100644 --- a/src/SOS/Strike/exts.h +++ b/src/SOS/Strike/exts.h @@ -142,12 +142,17 @@ extern PDEBUG_REGISTERS g_ExtRegisters; extern PDEBUG_CLIENT g_ExtClient; extern PDEBUG_DATA_SPACES2 g_ExtData2; extern PDEBUG_SYMBOLS2 g_ExtSymbols2; -extern PDEBUG_ADVANCED3 g_ExtAdvanced3; +extern PDEBUG_ADVANCED g_ExtAdvanced; + +bool +IsInitializedByDbgEng(); #else // FEATURE_PAL extern ILLDBServices* g_ExtServices; +#define IsInitializedByDbgEng() false + #endif // FEATURE_PAL HRESULT @@ -305,11 +310,6 @@ HRESULT CheckEEDll(); extern BOOL g_bDacBroken; -#define PAGE_ALIGN64(Va) ((ULONG64)((Va) & ~((ULONG64) ((LONG64) (LONG) PageSize - 1)))) - -extern ULONG PageSize; - - //----------------------------------------------------------------------------------------- // // Target platform abstraction @@ -446,10 +446,6 @@ inline CLRDATA_ADDRESS GetBP(const CROSS_PLATFORM_CONTEXT& context) extern WINDBG_EXTENSION_APIS ExtensionApis; #define GetExpression (ExtensionApis.lpGetExpressionRoutine) -extern ULONG TargetMachine; -extern ULONG g_TargetClass; -extern ULONG g_VDbgEng; - #else // FEATURE_PAL #define GetExpression(exp) g_ExtServices->GetExpression(exp) diff --git a/src/SOS/Strike/hostcoreclr.cpp b/src/SOS/Strike/hostcoreclr.cpp index 2a8dface9..f0e23b2bf 100644 --- a/src/SOS/Strike/hostcoreclr.cpp +++ b/src/SOS/Strike/hostcoreclr.cpp @@ -256,7 +256,6 @@ static HRESULT GetCoreClrDirectory(std::string& coreClrDirectory) } if (GetFileAttributesA(szModuleName) == INVALID_FILE_ATTRIBUTES) { - ExtErr("Error: coreclr module name doesn't exists\n"); return HRESULT_FROM_WIN32(GetLastError()); } coreClrDirectory = szModuleName; @@ -272,6 +271,26 @@ static HRESULT GetCoreClrDirectory(std::string& coreClrDirectory) return S_OK; } +/**********************************************************************\ + * Returns the coreclr module/runtime directory of the target. +\**********************************************************************/ +HRESULT GetCoreClrDirectory(LPWSTR modulePath, int modulePathSize) +{ + std::string coreclrDirectory; + HRESULT hr = GetCoreClrDirectory(coreclrDirectory); + if (FAILED(hr)) + { + return hr; + } + int length = MultiByteToWideChar(CP_ACP, 0, coreclrDirectory.c_str(), -1, modulePath, modulePathSize); + if (0 >= length) + { + ExtErr("MultiByteToWideChar(coreclrDirectory) failed. Last error = 0x%x\n", GetLastError()); + return HRESULT_FROM_WIN32(GetLastError()); + } + return S_OK; +} + // // Searches the runtime directory for a .NET Core runtime version // @@ -587,6 +606,11 @@ extern "C" HRESULT SOSInitializeByHost(SOSNetCoreCallbacks* callbacks, int callb { g_dbiFilePath = _strdup(dbiFilePath); } +#ifndef FEATURE_PAL + // When SOS is hosted on dotnet-dump, the ExtensionApis are not set so + // the expression evaluation function needs to be supplied. + GetExpression = (PWINDBG_GET_EXPRESSION64)callbacks->GetExpressionDelegate; +#endif g_symbolStoreInitialized = symbolStoreEnabled; g_hostingInitialized = true; return S_OK; @@ -746,48 +770,6 @@ static int ReadMemoryForSymbols(ULONG64 address, uint8_t *buffer, int cb) return 0; } -#ifdef FEATURE_PAL - -// -// Symbol downloader callback -// -static void SymbolFileCallback(void* param, const char* moduleFileName, const char* symbolFilePath) -{ - if (strcmp(moduleFileName, MAIN_CLR_DLL_NAME_A) == 0) { - return; - } - if (strcmp(moduleFileName, MAKEDLLNAME_A("mscordaccore")) == 0) { - if (g_dacFilePath == nullptr) { - g_dacFilePath = _strdup(symbolFilePath); - } - return; - } - if (strcmp(moduleFileName, MAKEDLLNAME_A("mscordbi")) == 0) { - if (g_dbiFilePath == nullptr) { - g_dbiFilePath = _strdup(symbolFilePath); - } - return; - } - ToRelease services2(NULL); - HRESULT Status = g_ExtServices->QueryInterface(__uuidof(ILLDBServices2), (void**)&services2); - if (SUCCEEDED(Status)) - { - services2->AddModuleSymbol(param, symbolFilePath); - } -} - -// -// Enumerate native module callback -// -static void LoadNativeSymbolsCallback(void* param, const char* moduleFilePath, ULONG64 moduleAddress, int moduleSize) -{ - _ASSERTE(g_hostingInitialized); - _ASSERTE(g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate != nullptr); - g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate(SymbolFileCallback, param, GetTempDirectory(), moduleFilePath, moduleAddress, moduleSize, ReadMemoryForSymbols); -} - -#endif - /**********************************************************************\ * Setup and initialize the symbol server support. \**********************************************************************/ @@ -833,6 +815,46 @@ void InitializeSymbolStore() #endif } +// +// Symbol downloader callback +// +static void SymbolFileCallback(void* param, const char* moduleFileName, const char* symbolFilePath) +{ + if (strcmp(moduleFileName, MAIN_CLR_DLL_NAME_A) == 0) { + return; + } + if (strcmp(moduleFileName, MAKEDLLNAME_A("mscordaccore")) == 0) { + if (g_dacFilePath == nullptr) { + g_dacFilePath = _strdup(symbolFilePath); + } + return; + } + if (strcmp(moduleFileName, MAKEDLLNAME_A("mscordbi")) == 0) { + if (g_dbiFilePath == nullptr) { + g_dbiFilePath = _strdup(symbolFilePath); + } + return; + } +#ifdef FEATURE_PAL + ToRelease services2(NULL); + HRESULT Status = g_ExtServices->QueryInterface(__uuidof(ILLDBServices2), (void**)&services2); + if (SUCCEEDED(Status)) + { + services2->AddModuleSymbol(param, symbolFilePath); + } +#endif +} + +// +// Enumerate native module callback +// +static void LoadNativeSymbolsCallback(void* param, const char* moduleFilePath, ULONG64 moduleAddress, int moduleSize) +{ + _ASSERTE(g_hostingInitialized); + _ASSERTE(g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate != nullptr); + g_SOSNetCoreCallbacks.LoadNativeSymbolsDelegate(SymbolFileCallback, param, GetTempDirectory(), moduleFilePath, moduleAddress, moduleSize, ReadMemoryForSymbols); +} + /**********************************************************************\ * Enumerate the native modules and attempt to download the symbols * for them. Depends on the lldb callback to enumerate modules. Not @@ -840,19 +862,40 @@ void InitializeSymbolStore() \**********************************************************************/ HRESULT LoadNativeSymbols(bool runtimeOnly) { - HRESULT Status = S_OK; -#ifdef FEATURE_PAL + HRESULT hr = S_OK; if (g_symbolStoreInitialized) { +#ifdef FEATURE_PAL ToRelease services2(NULL); - Status = g_ExtServices->QueryInterface(__uuidof(ILLDBServices2), (void**)&services2); - if (SUCCEEDED(Status)) + hr = g_ExtServices->QueryInterface(__uuidof(ILLDBServices2), (void**)&services2); + if (SUCCEEDED(hr)) { - Status = services2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback); + hr = services2->LoadNativeSymbols(runtimeOnly, LoadNativeSymbolsCallback); + } +#else + if (runtimeOnly) + { + ULONG index; + ULONG64 moduleAddress; + HRESULT hr = g_ExtSymbols->GetModuleByModuleName(MAIN_CLR_MODULE_NAME_A, 0, &index, &moduleAddress); + if (SUCCEEDED(hr)) + { + ArrayHolder moduleFilePath = new char[MAX_LONGPATH + 1]; + hr = g_ExtSymbols->GetModuleNames(index, 0, moduleFilePath, MAX_LONGPATH, NULL, NULL, 0, NULL, NULL, 0, NULL); + if (SUCCEEDED(hr)) + { + DEBUG_MODULE_PARAMETERS moduleParams; + hr = g_ExtSymbols->GetModuleParameters(1, &moduleAddress, 0, &moduleParams); + if (SUCCEEDED(hr)) + { + LoadNativeSymbolsCallback(nullptr, moduleFilePath, moduleAddress, moduleParams.Size); + } + } + } } - } #endif - return Status; + } + return hr; } /**********************************************************************\ @@ -973,7 +1016,8 @@ HRESULT SymbolReader::LoadSymbolsForWindowsPDB(___in IMetaDataImport* pMD, ___in if (m_pSymReader != NULL) return S_OK; - IfFailRet(CoInitialize(NULL)); + // Ignore errors to be able to run under a managed host (dotnet-dump). + CoInitialize(NULL); // We now need a binder object that will take the module and return a ToRelease pSymBinder; diff --git a/src/SOS/Strike/hostcoreclr.h b/src/SOS/Strike/hostcoreclr.h index fbbcb205e..f6c17d9c9 100644 --- a/src/SOS/Strike/hostcoreclr.h +++ b/src/SOS/Strike/hostcoreclr.h @@ -25,6 +25,7 @@ typedef void (*DisposeDelegate)(PVOID); typedef BOOL (*ResolveSequencePointDelegate)(PVOID, const char*, unsigned int, unsigned int*, unsigned int*); typedef BOOL (*GetLocalVariableNameDelegate)(PVOID, int, int, BSTR*); typedef BOOL (*GetLineByILOffsetDelegate)(PVOID, mdMethodDef, ULONG64, ULONG *, BSTR*); +typedef DWORD_PTR (*GetExpressionDelegate)(PCSTR); typedef BOOL (*GetMetadataLocatorDelegate)( LPCWSTR imagePath, @@ -50,6 +51,7 @@ struct SOSNetCoreCallbacks GetLineByILOffsetDelegate GetLineByILOffsetDelegate; GetLocalVariableNameDelegate GetLocalVariableNameDelegate; GetMetadataLocatorDelegate GetMetadataLocatorDelegate; + GetExpressionDelegate GetExpressionDelegate; }; static const char *SOSManagedDllName = "SOS.NETCore"; @@ -60,6 +62,7 @@ extern HMODULE g_hInstance; extern LPCSTR g_hostRuntimeDirectory; extern SOSNetCoreCallbacks g_SOSNetCoreCallbacks; +extern HRESULT GetCoreClrDirectory(LPWSTR modulePath, int modulePathSize); extern LPCSTR GetDacFilePath(); extern LPCSTR GetDbiFilePath(); extern BOOL IsHostingInitialized(); diff --git a/src/SOS/Strike/sos_unixexports.src b/src/SOS/Strike/sos_unixexports.src index acb294055..979c279f1 100644 --- a/src/SOS/Strike/sos_unixexports.src +++ b/src/SOS/Strike/sos_unixexports.src @@ -4,7 +4,6 @@ bpmd ClrStack -CreateDump DumpArray DumpAssembly DumpAsync @@ -43,6 +42,7 @@ HistStats IP2MD Name2EE PrintException +PathTo StopOnCatch SetHostRuntime SetSymbolServer @@ -54,4 +54,4 @@ Token2EE u VerifyHeap -SOSInitializeByHost \ No newline at end of file +SOSInitializeByHost diff --git a/src/SOS/Strike/stressLogDump.cpp b/src/SOS/Strike/stressLogDump.cpp index 756cc73f7..b4d13ba5d 100644 --- a/src/SOS/Strike/stressLogDump.cpp +++ b/src/SOS/Strike/stressLogDump.cpp @@ -297,7 +297,7 @@ vDoOut(BOOL bToConsole, FILE* file, PCSTR Format, ...) if (bToConsole) { - g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); + OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); } else { diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index c0ce606a0..fa7212bd7 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -346,10 +346,11 @@ static HRESULT GetContextStackTrace(ULONG osThreadId, PULONG pnumFrames) { PDEBUG_CONTROL4 debugControl4; - HRESULT hr; + HRESULT hr = S_OK; + *pnumFrames = 0; // Do we have advanced capability? - if ((hr = g_ExtControl->QueryInterface(__uuidof(IDebugControl4), (void **)&debugControl4)) == S_OK) + if (g_ExtControl->QueryInterface(__uuidof(IDebugControl4), (void **)&debugControl4) == S_OK) { ULONG oldId, id; g_ExtSystem->GetCurrentThreadId(&oldId); @@ -10473,7 +10474,6 @@ DECLARE_API(Name2EE) } -#ifndef FEATURE_PAL DECLARE_API(PathTo) { INIT_API(); @@ -10512,8 +10512,6 @@ DECLARE_API(PathTo) return Status; } -#endif - /**********************************************************************\ @@ -14142,7 +14140,6 @@ static HRESULT DumpMDInfoBuffer(DWORD_PTR dwStartAddr, DWORD Flags, ULONG64 Esp, bModuleNameWorked = TRUE; } } -#ifdef FEATURE_PAL else { if (g_sos->GetPEFileName(dmd.File, MAX_LONGPATH, wszNameBuffer, NULL) == S_OK) @@ -14158,7 +14155,6 @@ static HRESULT DumpMDInfoBuffer(DWORD_PTR dwStartAddr, DWORD Flags, ULONG64 Esp, } } } -#endif // FEATURE_PAL // Under certain circumstances DacpMethodDescData::GetMethodDescName() // returns a module qualified method name @@ -15368,86 +15364,6 @@ _EFN_GetManagedObjectFieldInfo( #endif // FEATURE_PAL -#ifdef FEATURE_PAL - -#ifdef CREATE_DUMP_SUPPORTED -#include -#include "datatarget.h" -extern bool CreateDumpForSOS(const char* programPath, const char* dumpPathTemplate, pid_t pid, MINIDUMP_TYPE minidumpType, ICLRDataTarget* dataTarget); -extern bool g_diagnostics; -#endif // CREATE_DUMP_SUPPORTED - -DECLARE_API(CreateDump) -{ - INIT_API(); -#ifdef CREATE_DUMP_SUPPORTED - StringHolder sFileName; - BOOL normal = FALSE; - BOOL withHeap = FALSE; - BOOL triage = FALSE; - BOOL full = FALSE; - BOOL diag = FALSE; - - size_t nArg = 0; - CMDOption option[] = - { // name, vptr, type, hasValue - {"-n", &normal, COBOOL, FALSE}, - {"-h", &withHeap, COBOOL, FALSE}, - {"-t", &triage, COBOOL, FALSE}, - {"-f", &full, COBOOL, FALSE}, - {"-d", &diag, COBOOL, FALSE}, - }; - CMDValue arg[] = - { // vptr, type - {&sFileName.data, COSTRING} - }; - if (!GetCMDOption(args, option, _countof(option), arg, _countof(arg), &nArg)) - { - return E_FAIL; - } - MINIDUMP_TYPE minidumpType = MiniDumpWithPrivateReadWriteMemory; - ULONG pid = 0; - g_ExtSystem->GetCurrentProcessId(&pid); - - if (full) - { - minidumpType = MiniDumpWithFullMemory; - } - else if (withHeap) - { - minidumpType = MiniDumpWithPrivateReadWriteMemory; - } - else if (triage) - { - minidumpType = MiniDumpFilterTriage; - } - else if (normal) - { - minidumpType = MiniDumpNormal; - } - g_diagnostics = diag; - - const char* programPath = g_ExtServices->GetCoreClrDirectory(); - const char* dumpPathTemplate = "/tmp/coredump.%d"; - ToRelease dataTarget = new DataTarget(); - dataTarget->AddRef(); - - if (sFileName.data != nullptr) - { - dumpPathTemplate = sFileName.data; - } - if (!CreateDumpForSOS(programPath, dumpPathTemplate, pid, minidumpType, dataTarget)) - { - Status = E_FAIL; - } -#else // CREATE_DUMP_SUPPORTED - ExtErr("CreateDump not supported on this platform\n"); -#endif // CREATE_DUMP_SUPPORTED - return Status; -} - -#endif // FEATURE_PAL - // // Sets the .NET Core runtime path to use to run the managed code within SOS/native debugger. // diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index f0843b6bc..6bc5f2325 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -517,12 +517,10 @@ HRESULT CheckEEDll() g_ExtSymbols->Reload("/f " MAIN_CLR_DLL_NAME_A); g_ExtSymbols->GetModuleParameters(1, &g_moduleInfo[MSCORWKS].baseAddr, 0, &Params); } - if (Params.SymbolType == SymPdb || Params.SymbolType == SymDia) { g_moduleInfo[MSCORWKS].hasPdb = TRUE; } - g_moduleInfo[MSCORWKS].size = Params.Size; } if (g_moduleInfo[MSCORWKS].baseAddr != 0 && g_moduleInfo[MSCORWKS].hasPdb == FALSE) @@ -530,7 +528,6 @@ HRESULT CheckEEDll() ExtOut("PDB symbol for coreclr.dll not loaded\n"); } } - return (g_moduleInfo[MSCORWKS].baseAddr != 0) ? S_OK : E_FAIL; #else return S_OK; @@ -1461,7 +1458,7 @@ int GetValueFieldOffset(CLRDATA_ADDRESS cdaMT, __in_z LPCWSTR wszFieldName, Dacp if (dmtd.ParentMethodTable) { DWORD retVal = GetValueFieldOffset(dmtd.ParentMethodTable, wszFieldName, pDacpFieldDescData); - if (retVal != NOT_FOUND) + if (retVal != (DWORD)NOT_FOUND) { // Return in case of error or success. Fall through for field-not-found. return retVal; @@ -3055,23 +3052,58 @@ void DumpTieredNativeCodeAddressInfo(struct DacpTieredVersionData * pTieredVersi { ExtOut("Code Version History:\n"); + for(int i = cTieredVersionData - 1; i >= 0; --i) + { + const char *descriptor = NULL; + switch(pTieredVersionData[i].OptimizationTier) + { + case DacpTieredVersionData::OptimizationTier_Unknown: + default: + descriptor = "Unknown Tier"; + break; + case DacpTieredVersionData::OptimizationTier_MinOptJitted: + descriptor = "MinOptJitted"; + break; + case DacpTieredVersionData::OptimizationTier_Optimized: + descriptor = "Optimized"; + break; + case DacpTieredVersionData::OptimizationTier_QuickJitted: + descriptor = "QuickJitted"; + break; + case DacpTieredVersionData::OptimizationTier_OptimizedTier1: + descriptor = "OptimizedTier1"; + break; + case DacpTieredVersionData::OptimizationTier_ReadyToRun: + descriptor = "ReadyToRun"; + break; + } + + DMLOut(" CodeAddr: %s (%s)\n", DMLIP(pTieredVersionData[i].NativeCodeAddr), descriptor); + ExtOut(" NativeCodeVersion: %p\n", SOS_PTR(pTieredVersionData[i].NativeCodeVersionNodePtr)); + } +} + +// 2.1 version +void DumpTieredNativeCodeAddressInfo_21(struct DacpTieredVersionData_21 * pTieredVersionData, const UINT cTieredVersionData) +{ + ExtOut("Code Version History:\n"); + for(int i = cTieredVersionData - 1; i >= 0; --i) { const char *descriptor = NULL; switch(pTieredVersionData[i].TieredInfo) { - case DacpTieredVersionData::TIERED_UNKNOWN: + case DacpTieredVersionData_21::TIERED_UNKNOWN: default: - _ASSERTE(!"Update SOS to understand the new tier"); descriptor = "Unknown Tier"; break; - case DacpTieredVersionData::NON_TIERED: + case DacpTieredVersionData_21::NON_TIERED: descriptor = "Non-Tiered"; break; - case DacpTieredVersionData::TIERED_0: + case DacpTieredVersionData_21::TIERED_0: descriptor = "Tier 0"; break; - case DacpTieredVersionData::TIERED_1: + case DacpTieredVersionData_21::TIERED_1: descriptor = "Tier 1"; break; } @@ -4067,6 +4099,11 @@ HRESULT LoadClrDebugDll(void) #ifdef FEATURE_PAL return hr; #else + // Fail if ExtensionApis wasn't initialized because we are hosted under dotnet-dump + if (Ioctl == nullptr) + { + return hr; + } // Try getting the DAC interface from dbgeng if the above fails on Windows WDBGEXTS_CLR_DATA_INTERFACE Query; @@ -4091,78 +4128,50 @@ HRESULT LoadClrDebugDll(void) #ifndef FEATURE_PAL -// This structure carries some input/output data to the FindFileInPathCallback below -typedef struct _FindFileCallbackData -{ - DWORD timestamp; - DWORD filesize; - HMODULE hModule; -} FindFileCallbackData; - - -// A callback used by SymFindFileInPath - called once for each file that matches -// the initial search criteria and allows the user to do arbitrary processing -// This implementation checks that filesize and timestamp are correct, then -// saves the loaded module handle -// Parameters -// filename - the full path the file which was found -// context - a user specified pointer to arbitrary data, in this case a FindFileCallbackData -// Return Value -// TRUE if the search should continue (the file is no good) -// FALSE if the search should stop (the file is good) -BOOL -FindFileInPathCallback( - ___in PCWSTR filename, - ___in PVOID context - ) -{ - FindFileCallbackData* pCallbackData = (FindFileCallbackData*)context; - if (pCallbackData == NULL) - { - return TRUE; - } - - pCallbackData->hModule = LoadLibraryExW( +HMODULE +LoadLibraryAndCheck( + PCWSTR filename, + DWORD timestamp, + DWORD filesize) +{ + HMODULE hModule = LoadLibraryExW( filename, NULL, // __reserved LOAD_WITH_ALTERED_SEARCH_PATH); // Ensure we check the dir in wszFullPath first - if (pCallbackData->hModule == NULL) + if (hModule == NULL) { ExtOut("Unable to load '%S'. hr = 0x%x.\n", filename, HRESULT_FROM_WIN32(GetLastError())); - return TRUE; + return NULL; } // Did we load the right one? MODULEINFO modInfo = {0}; if (!GetModuleInformation( GetCurrentProcess(), - pCallbackData->hModule, + hModule, &modInfo, sizeof(modInfo))) { ExtOut("Failed to read module information for '%S'. hr = 0x%x.\n", filename, HRESULT_FROM_WIN32(GetLastError())); - FreeLibrary(pCallbackData->hModule); - pCallbackData->hModule = NULL; - return TRUE; + FreeLibrary(hModule); + return NULL; } IMAGE_DOS_HEADER * pDOSHeader = (IMAGE_DOS_HEADER *) modInfo.lpBaseOfDll; IMAGE_NT_HEADERS * pNTHeaders = (IMAGE_NT_HEADERS *) (((LPBYTE) modInfo.lpBaseOfDll) + pDOSHeader->e_lfanew); DWORD dwSizeActual = pNTHeaders->OptionalHeader.SizeOfImage; DWORD dwTimeStampActual = pNTHeaders->FileHeader.TimeDateStamp; - if ((dwSizeActual != pCallbackData->filesize) || (dwTimeStampActual != pCallbackData->timestamp)) + if ((dwSizeActual != filesize) || (dwTimeStampActual != timestamp)) { ExtOut("Found '%S', but it does not match the CLR being debugged.\n", filename); - ExtOut("Size: Expected '0x%x', Actual '0x%x'\n", pCallbackData->filesize, dwSizeActual); - ExtOut("Time stamp: Expected '0x%x', Actual '0x%x'\n", pCallbackData->timestamp, dwTimeStampActual); - FreeLibrary(pCallbackData->hModule); - pCallbackData->hModule = NULL; - return TRUE; + ExtOut("Size: Expected '0x%x', Actual '0x%x'\n", filesize, dwSizeActual); + ExtOut("Time stamp: Expected '0x%x', Actual '0x%x'\n", timestamp, dwTimeStampActual); + FreeLibrary(hModule); + return NULL; } - ExtOut("Loaded %S\n", filename); - return FALSE; + return hModule; } #endif // FEATURE_PAL @@ -4222,25 +4231,6 @@ public: return ref; } - struct CoTaskStringHolder - { - private: - WCHAR* m_string; - public: - const int Length = MAX_LONGPATH; - - CoTaskStringHolder() : m_string((WCHAR*)CoTaskMemAlloc(MAX_LONGPATH + 1)) { } - ~CoTaskStringHolder() { if (m_string != NULL) CoTaskMemFree(m_string); } - operator WCHAR* () { return m_string; } - - WCHAR* Detach() - { - WCHAR* ret = m_string; - m_string = NULL; - return ret; - } - }; - HRESULT ProvideLibraryInternal( const WCHAR* pwszFileName, DWORD dwTimestamp, @@ -4248,92 +4238,6 @@ public: HMODULE* phModule, LPWSTR* ppResolvedModulePath) { -#ifndef FEATURE_PAL - HRESULT hr = S_OK; - FindFileCallbackData callbackData; - callbackData.hModule = NULL; - callbackData.timestamp = dwTimestamp; - callbackData.filesize = dwSizeOfImage; - - // if we are looking for the DAC, just load the one windbg already found - if (_wcsncmp(pwszFileName, MAKEDLLNAME_W(CORECLR_DAC_MODULE_NAME_W), _wcslen(MAKEDLLNAME_W(CORECLR_DAC_MODULE_NAME_W))) == 0) - { - HMODULE dacModule; - if (g_sos == NULL) - { - // we ensure that windbg loads DAC first so that we can be sure to use the same one - return E_UNEXPECTED; - } - if (FAILED(hr = g_sos->GetDacModuleHandle(&dacModule))) - { - ExtErr("Failed to get the dac module handle. hr=0x%x.\n", hr); - return hr; - } - CoTaskStringHolder dacPath; - DWORD len = GetModuleFileNameW(dacModule, dacPath, dacPath.Length); - if (len == 0 || len == MAX_LONGPATH) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - ExtErr("GetModuleFileName(dacModuleHandle) failed. hr=0x%x.\n", hr); - return hr; - } - FindFileInPathCallback(dacPath, &callbackData); - if (ppResolvedModulePath != NULL) - { - *ppResolvedModulePath = dacPath.Detach(); - } - } - else { - ULONG64 hProcess; - hr = g_ExtSystem->GetCurrentProcessHandle(&hProcess); - if (FAILED(hr)) - { - ExtErr("IDebugSystemObjects::GetCurrentProcessHandle hr=0x%x.\n", hr); - return hr; - } - ToRelease spSym3(NULL); - hr = g_ExtSymbols->QueryInterface(__uuidof(IDebugSymbols3), (void**)&spSym3); - if (FAILED(hr)) - { - ExtErr("Unable to query IDebugSymbol3 hr=0x%x.\n", hr); - return hr; - } - ArrayHolder symbolPath = new WCHAR[MAX_LONGPATH + 1]; - hr = spSym3->GetSymbolPathWide(symbolPath, MAX_LONGPATH, NULL); - if (FAILED(hr)) - { - ExtErr("Unable to get symbol path. IDebugSymbols3::GetSymbolPathWide hr=0x%x.\n", hr); - return hr; - } - CoTaskStringHolder foundPath; - if (!SymFindFileInPathW( - (HANDLE)hProcess, - symbolPath, - pwszFileName, - (PVOID)(ULONG_PTR)dwTimestamp, - dwSizeOfImage, - 0, - SSRVOPT_DWORD, - foundPath, - (PFINDFILEINPATHCALLBACKW)&FindFileInPathCallback, - (PVOID)&callbackData)) - { - hr = HRESULT_FROM_WIN32(GetLastError()); - ExtErr("SymFindFileInPath failed for %S. hr=0x%x.\nPlease ensure that %S is on your symbol path.\n", pwszFileName, hr, pwszFileName); - return hr; - } - if (ppResolvedModulePath != NULL) - { - *ppResolvedModulePath = foundPath.Detach(); - } - } - if (phModule != NULL) - { - *phModule = callbackData.hModule; - } - return S_OK; -#else - _ASSERTE(phModule == NULL); const char* filePath = nullptr; if (_wcsncmp(pwszFileName, MAKEDLLNAME_W(CORECLR_DAC_MODULE_NAME_W), _wcslen(MAKEDLLNAME_W(CORECLR_DAC_MODULE_NAME_W))) == 0) @@ -4352,34 +4256,32 @@ public: if (0 >= length) { ExtErr("MultiByteToWideChar(filePath) failed. Last error = 0x%x\n", GetLastError()); - return E_FAIL; + return HRESULT_FROM_WIN32(GetLastError()); } } else { - LPCSTR coreclrDirectory = g_ExtServices->GetCoreClrDirectory(); - if (coreclrDirectory == NULL) - { - ExtErr("Runtime module (%s) not loaded yet\n", MAKEDLLNAME_A("coreclr")); - return E_FAIL; - } - int length = MultiByteToWideChar(CP_ACP, 0, coreclrDirectory, -1, modulePath, MAX_LONGPATH); - if (0 >= length) + HRESULT hr = GetCoreClrDirectory(modulePath, MAX_LONGPATH); + if (FAILED(hr)) { - ExtErr("MultiByteToWideChar(coreclrDirectory) failed. Last error = 0x%x\n", GetLastError()); - return E_FAIL; + return hr; } wcscat_s(modulePath, MAX_LONGPATH, pwszFileName); } ExtOut("Loaded %S\n", modulePath.GetPtr()); +#ifndef FEATURE_PAL + if (phModule != NULL) + { + *phModule = LoadLibraryAndCheck(modulePath.GetPtr(), dwTimestamp, dwSizeOfImage); + } +#endif if (ppResolvedModulePath != NULL) { *ppResolvedModulePath = modulePath.Detach(); } return S_OK; -#endif // FEATURE_PAL } // Called by the shim to locate and load mscordaccore and mscordbi @@ -4568,7 +4470,7 @@ public: ((CONTEXT*) context)->ContextFlags = contextFlags; // Ok, do it! - hr = g_ExtAdvanced3->GetThreadContext((LPVOID) context, contextSize); + hr = g_ExtAdvanced->GetThreadContext((LPVOID) context, contextSize); // This is cleanup; failure here doesn't mean GetThreadContext should fail // (that's determined by hr). @@ -5223,6 +5125,43 @@ size_t CountHexCharacters(CLRDATA_ADDRESS val) } return ret; +} + +HRESULT +OutputVaList( + ULONG mask, + PCSTR format, + va_list args) +{ +#ifndef FEATURE_PAL + if (IsInitializedByDbgEng()) + { + return g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, format, args); + } + else +#endif + { + ArrayHolder str = new char[8192]; + int length = _vsnprintf_s(str, 8192, _TRUNCATE, format, args); + if (length > 0) + { + return g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, str, args); + } + return E_FAIL; + } +} + +HRESULT +OutputText( + ULONG mask, + PCSTR format, + ...) +{ + va_list args; + va_start (args, format); + HRESULT result = OutputVaList(mask, format, args); + va_end (args); + return result; } void WhitespaceOut(int count) @@ -5238,10 +5177,10 @@ void WhitespaceOut(int count) count &= ~0x3F; if (mod > 0) - g_ExtControl->Output(DEBUG_OUTPUT_NORMAL, "%.*s", mod, FixedIndentString); + OutputText(DEBUG_OUTPUT_NORMAL, "%.*s", mod, FixedIndentString); for ( ; count > 0; count -= FixedIndentWidth) - g_ExtControl->Output(DEBUG_OUTPUT_NORMAL, FixedIndentString); + OutputText(DEBUG_OUTPUT_NORMAL, FixedIndentString); } void DMLOut(PCSTR format, ...) @@ -5261,7 +5200,7 @@ void DMLOut(PCSTR format, ...) else #endif { - g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, format, args); + OutputVaList(DEBUG_OUTPUT_NORMAL, format, args); } va_end(args); @@ -5291,7 +5230,7 @@ void ExtOut(PCSTR Format, ...) va_start(Args, Format); ExtOutIndent(); - g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); + OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); va_end(Args); } @@ -5303,7 +5242,7 @@ void ExtWarn(PCSTR Format, ...) va_list Args; va_start(Args, Format); - g_ExtControl->OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args); + OutputVaList(DEBUG_OUTPUT_WARNING, Format, Args); va_end(Args); } @@ -5312,7 +5251,7 @@ void ExtErr(PCSTR Format, ...) va_list Args; va_start(Args, Format); - g_ExtControl->OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args); + OutputVaList(DEBUG_OUTPUT_ERROR, Format, Args); va_end(Args); } @@ -5326,7 +5265,7 @@ void ExtDbgOut(PCSTR Format, ...) va_start(Args, Format); ExtOutIndent(); - g_ExtControl->OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); + OutputVaList(DEBUG_OUTPUT_NORMAL, Format, Args); va_end(Args); } #endif @@ -5512,7 +5451,7 @@ EnableDMLHolder::~EnableDMLHolder() bool IsDMLEnabled() { - return Output::g_DMLEnable > 0; + return IsInitializedByDbgEng() && Output::g_DMLEnable > 0; } NoOutputHolder::NoOutputHolder(BOOL bSuppress) diff --git a/src/SOS/Strike/util.h b/src/SOS/Strike/util.h index d24c9f657..15f7dd939 100644 --- a/src/SOS/Strike/util.h +++ b/src/SOS/Strike/util.h @@ -427,6 +427,8 @@ private: size_t CountHexCharacters(CLRDATA_ADDRESS val); +HRESULT OutputVaList(ULONG mask, PCSTR format, va_list args); + // Normal output. void DMLOut(PCSTR format, ...); /* Prints out DML strings. */ void IfDMLOut(PCSTR format, ...); /* Prints given DML string ONLY if DML is enabled; prints nothing otherwise. */ diff --git a/src/SOS/Strike/xplat/dbgeng.h b/src/SOS/Strike/xplat/dbgeng.h index 1e3928f43..4379aabb2 100644 --- a/src/SOS/Strike/xplat/dbgeng.h +++ b/src/SOS/Strike/xplat/dbgeng.h @@ -84,13 +84,7 @@ public: PCSTR format, va_list args) { - ArrayHolder str = new char[8192]; - int length = _vsnprintf_s(str, 8192, _TRUNCATE, format, args); - if (length > 0) - { - return m_lldbservices->OutputVaList(mask, str, args); - } - return E_FAIL; + return m_lldbservices->OutputVaList(mask, format, args); } // The following methods allow direct control diff --git a/src/SOS/dbgutil/dbgutil.vcxproj b/src/SOS/dbgutil/dbgutil.vcxproj index 9b4f9ff1c..790fce4a2 100644 --- a/src/SOS/dbgutil/dbgutil.vcxproj +++ b/src/SOS/dbgutil/dbgutil.vcxproj @@ -26,7 +26,7 @@ {A9A7C879-C320-3327-BB84-16E1322E17AE} - 10.0.17134.0 + 10.0 Win32Proj x64 dbgutil @@ -36,7 +36,7 @@ StaticLibrary MultiByte - v141 + v142 StaticLibrary @@ -312,4 +312,4 @@ - + \ No newline at end of file diff --git a/src/SOS/debugshim/debugshim.vcxproj b/src/SOS/debugshim/debugshim.vcxproj index 13b4cc5d0..9b7ebbbe5 100644 --- a/src/SOS/debugshim/debugshim.vcxproj +++ b/src/SOS/debugshim/debugshim.vcxproj @@ -20,7 +20,7 @@ {6A94C5FE-8706-3505-834E-DA16242F3864} - 10.0.17134.0 + 10.0 Win32Proj x64 debugshim @@ -30,7 +30,7 @@ StaticLibrary MultiByte - v141 + v142 StaticLibrary @@ -312,4 +312,4 @@ - + \ No newline at end of file diff --git a/src/SOS/gcdump/gcdump.vcxproj b/src/SOS/gcdump/gcdump.vcxproj index 1b3c7d487..411ba8955 100644 --- a/src/SOS/gcdump/gcdump.vcxproj +++ b/src/SOS/gcdump/gcdump.vcxproj @@ -30,17 +30,17 @@ {20EBC3C4-917C-402D-B778-9A6E3742BF5A} - 10.0.17134.0 Win32Proj x64 gcdump NoUpgrade + 10.0 StaticLibrary MultiByte - v141 + v142 StaticLibrary diff --git a/src/SOS/gcdump/gcdump.vcxproj.filters b/src/SOS/gcdump/gcdump.vcxproj.filters index 88745c0cf..0b0c61580 100644 --- a/src/SOS/gcdump/gcdump.vcxproj.filters +++ b/src/SOS/gcdump/gcdump.vcxproj.filters @@ -12,5 +12,9 @@ i386 + + + + \ No newline at end of file diff --git a/src/SOS/lldbplugin/lldbplugin.vcxproj b/src/SOS/lldbplugin/lldbplugin.vcxproj index 5a59f1f2a..42644ea5d 100644 --- a/src/SOS/lldbplugin/lldbplugin.vcxproj +++ b/src/SOS/lldbplugin/lldbplugin.vcxproj @@ -40,7 +40,7 @@ true - v141 + Remote_GCC_1_0 false diff --git a/src/Tools/dotnet-dump/AnalyzeContext.cs b/src/Tools/dotnet-dump/AnalyzeContext.cs index 7b794d39a..3f75566d2 100644 --- a/src/Tools/dotnet-dump/AnalyzeContext.cs +++ b/src/Tools/dotnet-dump/AnalyzeContext.cs @@ -88,31 +88,34 @@ namespace Microsoft.Diagnostics.Tools.Dump } else if (SymbolReader.IsSymbolStoreEnabled()) { - string dacFileName = Path.GetFileName(clrInfo.LocalMatchingDac); - SymbolStoreKey key = null; - - if (clrInfo.ModuleInfo.BuildId != null) + string dacFileName = Path.GetFileName(dac ?? clrInfo.DacInfo.FileName); + if (dacFileName != null) { - IEnumerable keys = ELFFileKeyGenerator.GetKeys( - KeyTypeFlags.ClrKeys, clrInfo.ModuleInfo.FileName, clrInfo.ModuleInfo.BuildId, symbolFile: false, symbolFileName: null); + SymbolStoreKey key = null; - key = keys.SingleOrDefault((k) => Path.GetFileName(k.FullPathName) == dacFileName); - } - else - { - // Use the coreclr.dll's id (timestamp/filesize) to download the the dac module. - key = PEFileKeyGenerator.GetKey(dacFileName, clrInfo.ModuleInfo.TimeStamp, clrInfo.ModuleInfo.FileSize); - } + if (clrInfo.ModuleInfo.BuildId != null) + { + IEnumerable keys = ELFFileKeyGenerator.GetKeys( + KeyTypeFlags.ClrKeys, clrInfo.ModuleInfo.FileName, clrInfo.ModuleInfo.BuildId, symbolFile: false, symbolFileName: null); - if (key != null) - { - if (s_tempDirectory == null) + key = keys.SingleOrDefault((k) => Path.GetFileName(k.FullPathName) == dacFileName); + } + else + { + // Use the coreclr.dll's id (timestamp/filesize) to download the the dac module. + key = PEFileKeyGenerator.GetKey(dacFileName, clrInfo.ModuleInfo.TimeStamp, clrInfo.ModuleInfo.FileSize); + } + + if (key != null) { - int processId = Process.GetCurrentProcess().Id; - s_tempDirectory = Path.Combine(Path.GetTempPath(), "analyze" + processId.ToString()); + if (s_tempDirectory == null) + { + int processId = Process.GetCurrentProcess().Id; + s_tempDirectory = Path.Combine(Path.GetTempPath(), "analyze" + processId.ToString()); + } + // Now download the DAC module from the symbol server + s_dacFilePath = SymbolReader.GetSymbolFile(key, s_tempDirectory); } - // Now download the DAC module from the symbol server - s_dacFilePath = SymbolReader.GetSymbolFile(key, s_tempDirectory); } } diff --git a/src/Tools/dotnet-dump/Analyzer.cs b/src/Tools/dotnet-dump/Analyzer.cs index 6baebb279..7682840f1 100644 --- a/src/Tools/dotnet-dump/Analyzer.cs +++ b/src/Tools/dotnet-dump/Analyzer.cs @@ -6,6 +6,7 @@ using System.CommandLine; using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -29,7 +30,8 @@ namespace Microsoft.Diagnostics.Tools.Dump public Analyzer() { _consoleProvider = new ConsoleProvider(); - _commandProcessor = new CommandProcessor(_consoleProvider, new Assembly[] { typeof(Analyzer).Assembly }); + Type type = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? typeof(SOSCommandForWindows) : typeof(SOSCommand); + _commandProcessor = new CommandProcessor(_consoleProvider, new Assembly[] { typeof(Analyzer).Assembly }, new Type[] { type }); _commandProcessor.AddService(_consoleProvider); } @@ -61,11 +63,8 @@ namespace Microsoft.Diagnostics.Tools.Dump }; _commandProcessor.AddService(analyzeContext); - // Automatically enable symbol server support on Linux and MacOS - //if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - SymbolReader.InitializeSymbolStore(logging: false, msdl: true, symweb: false, symbolServerPath: null, symbolCachePath: null, windowsSymbolPath: null); - } + // Automatically enable symbol server support + SymbolReader.InitializeSymbolStore(logging: false, msdl: true, symweb: false, symbolServerPath: null, symbolCachePath: null, windowsSymbolPath: null); // Run the commands from the dotnet-dump command line if (command != null) diff --git a/src/Tools/dotnet-dump/Commands/SOSCommand.cs b/src/Tools/dotnet-dump/Commands/SOSCommand.cs index 8fdd1a6c3..aff87be78 100644 --- a/src/Tools/dotnet-dump/Commands/SOSCommand.cs +++ b/src/Tools/dotnet-dump/Commands/SOSCommand.cs @@ -37,7 +37,7 @@ namespace Microsoft.Diagnostics.Tools.Dump [Command(Name = "histobjfind", AliasExpansion = "HistObjFind", Help = "Displays all the log entries that reference an object at the specified address.")] [Command(Name = "histroot", AliasExpansion = "HistRoot", Help = "Displays information related to both promotions and relocations of the specified root.")] [Command(Name = "setsymbolserver", AliasExpansion = "SetSymbolServer", Help = "Enables the symbol server support ")] - public class SOSCommand : CommandBase + internal class SOSCommand : CommandBase { [Argument(Name = "arguments", Help = "Arguments to SOS command.")] public string[] Arguments { get; set; } diff --git a/src/Tools/dotnet-dump/Commands/SOSCommandForWindows.cs b/src/Tools/dotnet-dump/Commands/SOSCommandForWindows.cs new file mode 100644 index 000000000..72825a45e --- /dev/null +++ b/src/Tools/dotnet-dump/Commands/SOSCommandForWindows.cs @@ -0,0 +1,24 @@ +using Microsoft.Diagnostic.Repl; +using System.CommandLine; + +namespace Microsoft.Diagnostic.Tools.Dump +{ + [Command(Name = "dumprcw", AliasExpansion = "DumpRCW", Help = "Displays information about a Runtime Callable Wrapper.")] + [Command(Name = "dumpccw", AliasExpansion = "DumpCCW", Help = "Displays information about a COM Callable Wrapper.")] + [Command(Name = "dumppermissionset", AliasExpansion = "DumpPermissionSet", Help = "Displays a PermissionSet object (debug build only).")] + [Command(Name = "traverseheap", AliasExpansion = "TraverseHeap", Help = "Writes out a file in a format understood by the CLR Profiler.")] + [Command(Name = "analyzeoom", AliasExpansion = "AnalyzeOOM", Help = "Displays the info of the last OOM occurred on an allocation request to the GC heap.")] + [Command(Name = "verifyobj", AliasExpansion = "VerifyObj", Help = "Checks the object for signs of corruption.")] + [Command(Name = "listnearobj", AliasExpansion = "ListNearObj", Help = "Displays the object preceeding and succeeding the address specified.")] + [Command(Name = "gcheapstat", AliasExpansion = "GCHeapStat", Help = "Display various GC heap stats.")] + [Command(Name = "watsonbuckets", AliasExpansion = "WatsonBuckets", Help = "Displays the Watson buckets.")] + [Command(Name = "threadpool", AliasExpansion = "ThreadPool", Help = "Lists basic information about the thread pool.")] + [Command(Name = "comstate", AliasExpansion = "COMState", Help = "Lists the COM apartment model for each thread.")] + [Command(Name = "eeversion", AliasExpansion = "EEVersion", Help = "This prints the runtiem and SOS versions.")] + [Command(Name = "gchandles", AliasExpansion = "GCHandles", Help = "Provides statistics about GCHandles in the process.")] + [Command(Name = "objsize", AliasExpansion = "ObjSize", Help = "Lists the sizes of the all the objects found on managed threads.")] + [Command(Name = "gchandleleaks", AliasExpansion = "GCHandleLeaks", Help = "Helps in tracking down GCHandle leaks")] + internal class SOSCommandForWindows : SOSCommand + { + } +} diff --git a/src/inc/dacprivate.h b/src/inc/dacprivate.h index 978d8a8c5..80a616630 100644 --- a/src/inc/dacprivate.h +++ b/src/inc/dacprivate.h @@ -586,6 +586,24 @@ struct MSLAYOUT DacpMethodDescTransparencyData : ZeroInit