{41351955-16D5-48D7-AF4C-AF25F5FB2E78}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
{41351955-16D5-48D7-AF4C-AF25F5FB2E78}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
{41351955-16D5-48D7-AF4C-AF25F5FB2E78}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|Any CPU.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|ARM.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|ARM.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|ARM64.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|ARM64.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|x64.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|x64.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|x86.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Checked|x86.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|ARM.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|ARM.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|ARM64.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|x64.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Debug|x86.Build.0 = Debug|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|ARM.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|ARM.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|ARM64.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|ARM64.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|x64.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|x64.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|x86.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.Release|x86.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|ARM.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|ARM.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|ARM64.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|ARM64.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|x86.ActiveCfg = Release|Any CPU
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503}.RelWithDebInfo|x86.Build.0 = Release|Any CPU
{90CF2633-58F0-44EE-943B-D70207455F20}.Checked|Any CPU.ActiveCfg = Debug|Any CPU
{90CF2633-58F0-44EE-943B-D70207455F20}.Checked|Any CPU.Build.0 = Debug|Any CPU
{90CF2633-58F0-44EE-943B-D70207455F20}.Checked|ARM.ActiveCfg = Debug|Any CPU
{20EBC3C4-917C-402D-B778-9A6E3742BF5A} = {41638A4C-0DAF-47ED-A774-ECBBAC0315D7}
{1F012743-941B-4915-8C55-02097894CF3F} = {41638A4C-0DAF-47ED-A774-ECBBAC0315D7}
{41351955-16D5-48D7-AF4C-AF25F5FB2E78} = {B62728C8-1267-4043-B46F-5537BBAEC692}
+ {ED27F39F-DF5C-4E22-87E0-EC5B5873B503} = {41638A4C-0DAF-47ED-A774-ECBBAC0315D7}
{90CF2633-58F0-44EE-943B-D70207455F20} = {19FAB78C-3351-4911-8F0C-8C6056401740}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
endlocal
)
+REM Copy the native SOS binaries to where these tools expect for testing
+
+set "__dotnet_sos=%__RootBinDir%\bin\dotnet-sos\%__BuildType%\netcoreapp2.1\publish\win-%__BuildArch%"
+set "__dotnet_dump=%__RootBinDir%\bin\dotnet-dump\%__BuildType%\netcoreapp2.1\publish\win-%__BuildArch%"
+xcopy /y /q /i /s %__BinDir% %__dotnet_sos%
+xcopy /y /q /i /s %__BinDir% %__dotnet_dump%
+
REM =========================================================================================
REM ===
REM === All builds complete!
fi
build_native "$__BuildArch" "$__IntermediatesDir" "$__ExtraCmakeArgs"
+
+ # Copy the native SOS binaries to where these tools expect for testing
+ __dotnet_sos=$__RootBinDir/bin/dotnet-sos/$__BuildType/netcoreapp2.1/publish/$__DistroRid
+ __dotnet_dump=$__RootBinDir/bin/dotnet-dump/$__BuildType/netcoreapp2.1/publish/$__DistroRid
+ mkdir -p "$__dotnet_sos"
+ mkdir -p "$__dotnet_dump"
+ cp "$__BinDir"/* "$__dotnet_sos"
+ cp "$__BinDir"/* "$__dotnet_dump"
fi
# Run SOS/lldbplugin tests
--- /dev/null
+// 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 System.Runtime.InteropServices;
+
+namespace SOS
+{
+ [StructLayout(LayoutKind.Explicit)]
+ internal struct AMD64Context
+ {
+ [FieldOffset(0x0)]
+ public ulong P1Home;
+ [FieldOffset(0x8)]
+ public ulong P2Home;
+ [FieldOffset(0x10)]
+ public ulong P3Home;
+ [FieldOffset(0x18)]
+ public ulong P4Home;
+ [FieldOffset(0x20)]
+ public ulong P5Home;
+ [FieldOffset(0x28)]
+ public ulong P6Home;
+
+ [FieldOffset(0x30)]
+ public int ContextFlags;
+
+ [FieldOffset(0x34)]
+ public int MxCsr;
+
+ [FieldOffset(0x38)]
+ public short SegCs;
+ [FieldOffset(0x3a)]
+ public short SegDs;
+ [FieldOffset(0x3c)]
+ public short SegEs;
+ [FieldOffset(0x3e)]
+ public short SegFs;
+ [FieldOffset(0x40)]
+ public short SegGs;
+ [FieldOffset(0x42)]
+ public short SegSs;
+ [FieldOffset(0x44)]
+ public int EFlags;
+
+ [FieldOffset(0x48)]
+ public ulong Dr0;
+ [FieldOffset(0x50)]
+ public ulong Dr1;
+ [FieldOffset(0x58)]
+ public ulong Dr2;
+ [FieldOffset(0x60)]
+ public ulong Dr3;
+ [FieldOffset(0x68)]
+ public ulong Dr6;
+ [FieldOffset(0x70)]
+ public ulong Dr7;
+
+ [FieldOffset(0x78)]
+ public ulong Rax;
+ [FieldOffset(0x80)]
+ public ulong Rcx;
+ [FieldOffset(0x88)]
+ public ulong Rdx;
+ [FieldOffset(0x90)]
+ public ulong Rbx;
+ [FieldOffset(0x98)]
+ public ulong Rsp;
+ [FieldOffset(0xa0)]
+ public ulong Rbp;
+ [FieldOffset(0xa8)]
+ public ulong Rsi;
+ [FieldOffset(0xb0)]
+ public ulong Rdi;
+ [FieldOffset(0xb8)]
+ public ulong R8;
+ [FieldOffset(0xc0)]
+ public ulong R9;
+ [FieldOffset(0xc8)]
+ public ulong R10;
+ [FieldOffset(0xd0)]
+ public ulong R11;
+ [FieldOffset(0xd8)]
+ public ulong R12;
+ [FieldOffset(0xe0)]
+ public ulong R13;
+ [FieldOffset(0xe8)]
+ public ulong R14;
+ [FieldOffset(0xf0)]
+ public ulong R15;
+
+ [FieldOffset(0xf8)]
+ public ulong Rip;
+
+ //[FieldOffset(0x100)]
+ //public XmmSaveArea FltSave;
+
+ //[FieldOffset(0x300)]
+ //public VectorRegisterArea VectorRegisters;
+
+ [FieldOffset(0x4a8)]
+ public ulong DebugControl;
+ [FieldOffset(0x4b0)]
+ public ulong LastBranchToRip;
+ [FieldOffset(0x4b8)]
+ public ulong LastBranchFromRip;
+ [FieldOffset(0x4c0)]
+ public ulong LastExceptionToRip;
+ [FieldOffset(0x4c8)]
+ public ulong LastExceptionFromRip;
+
+ public static int Size => Marshal.SizeOf(typeof(AMD64Context));
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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 System;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+
+namespace SOS
+{
+ /// <summary>
+ /// Used to enable app-local assembly unification.
+ /// </summary>
+ internal static class AssemblyResolver
+ {
+ static AssemblyResolver()
+ {
+ AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
+ }
+
+ /// <summary>
+ /// Call to enable the assembly resolver for the current AppDomain.
+ /// </summary>
+ public static void Enable()
+ {
+ // intentionally empty. This is just meant to ensure the static constructor
+ // has run.
+ }
+
+ private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
+ {
+ // apply any existing policy
+ AssemblyName referenceName = new AssemblyName(AppDomain.CurrentDomain.ApplyPolicy(args.Name));
+
+ string fileName = referenceName.Name + ".dll";
+ string assemblyPath = null;
+ string probingPath = null;
+ Assembly assm = null;
+
+ // look next to requesting assembly
+ assemblyPath = args.RequestingAssembly?.Location;
+ if (!String.IsNullOrEmpty(assemblyPath))
+ {
+ probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName);
+ Debug.WriteLine($"Considering {probingPath} based on RequestingAssembly");
+ if (Probe(probingPath, referenceName.Version, out assm))
+ {
+ return assm;
+ }
+ }
+
+ // look next to the executing assembly
+ assemblyPath = Assembly.GetExecutingAssembly().Location;
+ if (!String.IsNullOrEmpty(assemblyPath))
+ {
+ probingPath = Path.Combine(Path.GetDirectoryName(assemblyPath), fileName);
+
+ Debug.WriteLine($"Considering {probingPath} based on ExecutingAssembly");
+ if (Probe(probingPath, referenceName.Version, out assm))
+ {
+ return assm;
+ }
+ }
+
+ // look in AppDomain base directory
+ probingPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
+ Debug.WriteLine($"Considering {probingPath} based on BaseDirectory");
+ if (Probe(probingPath, referenceName.Version, out assm))
+ {
+ return assm;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Considers a path to load for satisfying an assembly ref and loads it
+ /// if the file exists and version is sufficient.
+ /// </summary>
+ /// <param name="filePath">Path to consider for load</param>
+ /// <param name="minimumVersion">Minimum version to consider</param>
+ /// <param name="assembly">loaded assembly</param>
+ /// <returns>true if assembly was loaded</returns>
+ private static bool Probe(string filePath, Version minimumVersion, out Assembly assembly)
+ {
+ if (File.Exists(filePath))
+ {
+ AssemblyName name = AssemblyName.GetAssemblyName(filePath);
+
+ if (name.Version >= minimumVersion)
+ {
+ assembly = Assembly.LoadFile(filePath);
+ return true;
+ }
+ }
+
+ assembly = null;
+ return false;
+ }
+ }
+}
--- /dev/null
+// 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 System.Threading;
+
+namespace SOS
+{
+ /// <summary>
+ /// Context/services provided to the SOS host.
+ /// </summary>
+ public interface ISOSHostContext
+ {
+ /// <summary>
+ /// Display text on the console
+ /// </summary>
+ /// <param name="text">message</param>
+ void Write(string text);
+
+ /// <summary>
+ /// Get/set the current native thread id
+ /// </summary>
+ int CurrentThreadId { get; set; }
+
+ /// <summary>
+ /// Cancellation token for current operation
+ /// </summary>
+ CancellationToken CancellationToken { get; }
+ }
+}
\ No newline at end of file
--- /dev/null
+// 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; }
+
+ #region SOS.NETCore function delegates
+
+ private delegate bool InitializeSymbolStoreDelegate(
+ bool logging,
+ bool msdl,
+ bool symweb,
+ string symbolServerPath,
+ string symbolCachePath,
+ string windowsSymbolPath);
+
+ private delegate void DisplaySymbolStoreDelegate();
+
+ private delegate void DisableSymbolStoreDelegate();
+
+ private delegate void LoadNativeSymbolsDelegate(
+ SymbolReader.SymbolFileCallback callback,
+ IntPtr parameter,
+ string tempDirectory,
+ string moduleFilePath,
+ ulong address,
+ int size,
+ SymbolReader.ReadMemoryDelegate readMemory);
+
+ private delegate IntPtr LoadSymbolsForModuleDelegate(
+ string assemblyPath,
+ bool isFileLayout,
+ ulong loadedPeAddress,
+ int loadedPeSize,
+ ulong inMemoryPdbAddress,
+ int inMemoryPdbSize,
+ SymbolReader.ReadMemoryDelegate readMemory);
+
+ private delegate void DisposeDelegate(IntPtr symbolReaderHandle);
+
+ private delegate bool ResolveSequencePointDelegate(
+ IntPtr symbolReaderHandle,
+ string filePath,
+ int lineNumber,
+ out int methodToken,
+ out int ilOffset);
+
+ private delegate bool GetLineByILOffsetDelegate(
+ IntPtr symbolReaderHandle,
+ int methodToken,
+ long ilOffset,
+ out int lineNumber,
+ out IntPtr fileName);
+
+ private delegate bool GetLocalVariableNameDelegate(
+ IntPtr symbolReaderHandle,
+ int methodToken,
+ int localIndex,
+ out IntPtr localVarName);
+
+ #endregion
+
+ /// <summary>
+ /// Used by ISOSHostServices.GetSOSNETCoreCallbacks.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ struct SOSNetCoreCallbacks
+ {
+ public InitializeSymbolStoreDelegate InitializeSymbolStoreDelegate;
+ public DisplaySymbolStoreDelegate DisplaySymbolStoreDelegate;
+ public DisableSymbolStoreDelegate DisableSymbolStoreDelegate;
+ public LoadNativeSymbolsDelegate LoadNativeSymbolsDelegate;
+ public LoadSymbolsForModuleDelegate LoadSymbolsForModuleDelegate;
+ public DisposeDelegate DisposeDelegate;
+ public ResolveSequencePointDelegate ResolveSequencePointDelegate;
+ public GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
+ public GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
+ }
+
+ static SOSNetCoreCallbacks s_callbacks = new SOSNetCoreCallbacks {
+ InitializeSymbolStoreDelegate = SymbolReader.InitializeSymbolStore,
+ DisplaySymbolStoreDelegate = SymbolReader.DisplaySymbolStore,
+ DisableSymbolStoreDelegate = SymbolReader.DisableSymbolStore,
+ LoadNativeSymbolsDelegate = SymbolReader.LoadNativeSymbols,
+ LoadSymbolsForModuleDelegate = SymbolReader.LoadSymbolsForModule,
+ DisposeDelegate = SymbolReader.Dispose,
+ ResolveSequencePointDelegate = SymbolReader.ResolveSequencePoint,
+ GetLineByILOffsetDelegate = SymbolReader.GetLineByILOffset,
+ GetLocalVariableNameDelegate = SymbolReader.GetLocalVariableName,
+ };
+
+ static readonly string s_coreclrModuleName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "coreclr" : "libcoreclr.so";
+
+ readonly SOSHost _sosHost;
+ readonly IDataReader _dataReader;
+ readonly ISOSHostContext _context;
+
+ /// <summary>
+ /// Create an instance of the service wrapper SOS uses.
+ /// </summary>
+ /// <param name="dataReader">clrmd data reader instance</param>
+ /// <param name="context">sos hosting context</param>
+ 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();
+
+ builder = AddInterface(IID_SOSHostServices, validate: false);
+ builder.AddMethod(new GetSOSNETCoreCallbacksDelegate(GetSOSNETCoreCallbacks));
+ 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)
+ {
+ type = 0;
+ processId = 0;
+ threadId = 0;
+ extraInformationSize = 0;
+ extraInformationUsed = 0;
+ descriptionUsed = 0;
+ return E_NOTIMPL;
+ }
+
+ int Disassemble(
+ IntPtr self,
+ ulong offset,
+ DEBUG_DISASM flags,
+ StringBuilder buffer,
+ uint bufferSize,
+ out uint disassemblySize,
+ out ulong endOffset)
+ {
+ disassemblySize = 0;
+ endOffset = 0;
+ 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)
+ {
+ return E_NOTIMPL;
+ }
+
+ int ReadVirtual(
+ IntPtr self,
+ ulong address,
+ IntPtr buffer,
+ int bytesRequested,
+ IntPtr pbytesRead)
+ {
+ if (_dataReader.ReadMemory(address, buffer, bytesRequested, out int bytesRead))
+ {
+ if (pbytesRead != IntPtr.Zero)
+ {
+ Marshal.WriteInt32(pbytesRead, 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.
+ if (pbytesWritten != IntPtr.Zero) {
+ Marshal.WriteInt32(pbytesWritten, (int)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,
+ out uint nameSize,
+ out ulong displacement)
+ {
+ nameSize = 0;
+ displacement = 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,
+ out uint index,
+ out ulong baseAddress)
+ {
+ index = 0;
+ baseAddress = 0;
+ return E_NOTIMPL;
+ }
+
+ int GetModuleNames(
+ IntPtr self,
+ uint index,
+ ulong baseAddress,
+ StringBuilder imageNameBuffer,
+ uint imageNameBufferSize,
+ out uint imageNameSize,
+ StringBuilder moduleNameBuffer,
+ uint ModuleNameBufferSize,
+ out uint moduleNameSize,
+ StringBuilder loadedImageNameBuffer,
+ uint loadedImageNameBufferSize,
+ out uint loadedImageNameSize)
+ {
+ imageNameSize = 0;
+ moduleNameSize = 0;
+ loadedImageNameSize = 0;
+ return E_NOTIMPL;
+ }
+
+ int GetLineByOffset(
+ IntPtr self,
+ ulong offset,
+ out uint line,
+ StringBuilder fileBuffer,
+ uint fileBufferSize,
+ out uint fileSize,
+ out ulong displacement)
+ {
+ line = 0;
+ fileSize = 0;
+ displacement = 0;
+ return E_NOTIMPL;
+ }
+
+ int GetSourceFileLineOffsets(
+ IntPtr self,
+ string file,
+ ulong[] buffer,
+ uint bufferLines,
+ out uint fileLines)
+ {
+ fileLines = 0;
+ return E_NOTIMPL;
+ }
+
+ int FindSourceFile(
+ IntPtr self,
+ uint startElement,
+ string file,
+ uint flags,
+ out uint foundElement,
+ StringBuilder buffer,
+ uint bufferSize,
+ out uint foundSize)
+ {
+ foundElement = 0;
+ foundSize = 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
+
+ // 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 ISOSHostServices
+
+ int GetSOSNETCoreCallbacks(
+ IntPtr self,
+ int version,
+ IntPtr pCallbacks)
+ {
+ if (version < 1)
+ {
+ return E_FAIL;
+ }
+ try
+ {
+ Marshal.StructureToPtr(s_callbacks, pCallbacks, false);
+ }
+ catch (ArgumentException)
+ {
+ return E_FAIL;
+ }
+ 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,
+ 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,
+ 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,
+ 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,
+ IntPtr index,
+ out ulong baseAddress);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ private delegate int GetModuleByOffsetDelegate(
+ IntPtr self,
+ ulong offset,
+ uint startIndex,
+ out uint index,
+ out ulong baseAddress);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ private delegate int GetModuleNamesDelegate(
+ IntPtr self,
+ uint index,
+ ulong baseAddress,
+ [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder imageNameBuffer,
+ uint imageNameBufferSize,
+ out uint imageNameSize,
+ [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder moduleNameBuffer,
+ uint ModuleNameBufferSize,
+ out uint moduleNameSize,
+ [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder loadedImageNameBuffer,
+ uint loadedImageNameBufferSize,
+ out uint loadedImageNameSize);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ private delegate int GetLineByOffsetDelegate(
+ IntPtr self,
+ ulong offset,
+ out uint line,
+ [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder fileBuffer,
+ uint fileBufferSize,
+ out uint fileSize,
+ out 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,
+ out uint fileLines);
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ private delegate int FindSourceFileDelegate(
+ IntPtr self,
+ uint startElement,
+ [In, MarshalAs(UnmanagedType.LPStr)] string file,
+ uint flags,
+ out uint foundElement,
+ [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder buffer,
+ uint bufferSize,
+ out uint 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
+
+ /// <summary>
+ /// The LoadNativeSymbolsDelegate2 callback
+ /// </summary>
+ 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
+
+ #region ISOSHostServices delegates
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ private delegate int GetSOSNETCoreCallbacksDelegate(
+ IntPtr self,
+ int version,
+ IntPtr pCallbacks);
+
+ #endregion
+ }
+}
\ No newline at end of file
--- /dev/null
+<!-- Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -->
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <TargetFramework>netstandard2.0</TargetFramework>
+ <AssemblyName>SOS.Hosting</AssemblyName>
+ <NoWarn>;1591;1701</NoWarn>
+ <Description>SOS Hosting support</Description>
+ <DebugSymbols>true</DebugSymbols>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Microsoft.Diagnostics.Runtime" Version="$(MicrosoftDiagnosticsRuntimeVersion)" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\Microsoft.Diagnostic.Repl\Microsoft.Diagnostic.Repl.csproj" />
+ <ProjectReference Include="..\SOS.NETCore\SOS.NETCore.csproj" />
+ </ItemGroup>
+</Project>
--- /dev/null
+// 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 System;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace SOS
+{
+ /// <summary>
+ /// Helper code to hosting SOS under ClrMD
+ /// </summary>
+ public sealed class SOSHost
+ {
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ delegate int SOSCommandDelegate(IntPtr ILLDBServices, [In, MarshalAs(UnmanagedType.LPStr)] string args);
+
+ readonly LLDBServicesWrapper _wrapper;
+ IntPtr _sosLibrary = IntPtr.Zero;
+
+ /// <summary>
+ /// Enable the assembly resolver to get the right SOS.NETCore version (the one
+ /// in the same directory as SOS.Hosting).
+ /// </summary>
+ static SOSHost()
+ {
+ AssemblyResolver.Enable();
+ }
+
+ /// <summary>
+ /// The native SOS binaries path. Default is OS/architecture (RID) named directory in the same directory as this assembly.
+ /// </summary>
+ public string SOSPath { get; set; }
+
+ /// <summary>
+ /// Create an instance of the hosting class
+ /// </summary>
+ public SOSHost(IDataReader dataReader, ISOSHostContext context)
+ {
+ string os = null;
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
+ os = "win";
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
+ os = "linux";
+ }
+ if (os == null) {
+ throw new PlatformNotSupportedException($"{RuntimeInformation.OSDescription} not supported");
+ }
+ string architecture = RuntimeInformation.OSArchitecture.ToString().ToLowerInvariant();
+ string rid = os + "-" + architecture;
+ SOSPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), rid);
+
+ _wrapper = new LLDBServicesWrapper(this, dataReader, context);
+ }
+
+ public void ExecuteCommand(string commandLine)
+ {
+ string command = "Help";
+ string arguments = null;
+
+ if (commandLine != null)
+ {
+ int firstSpace = commandLine.IndexOf(' ');
+ command = firstSpace == -1 ? commandLine : commandLine.Substring(0, firstSpace);
+ arguments = firstSpace == -1 ? null : commandLine.Substring(firstSpace);
+ }
+ ExecuteCommand(command, arguments);
+ }
+
+ public void ExecuteCommand(string command, string arguments)
+ {
+ if (_sosLibrary == IntPtr.Zero)
+ {
+ string sosPath = Path.Combine(SOSPath, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "sos.dll" : "libsos.so");
+ _sosLibrary = DataTarget.PlatformFunctions.LoadLibrary(sosPath);
+ if (_sosLibrary == IntPtr.Zero)
+ {
+ throw new FileNotFoundException($"SOS module {sosPath} not found");
+ }
+ }
+ IntPtr commandAddress = DataTarget.PlatformFunctions.GetProcAddress(_sosLibrary, command);
+ if (commandAddress == IntPtr.Zero)
+ {
+ throw new EntryPointNotFoundException($"Can not find SOS command: {command}");
+ }
+ var commandFunc = (SOSCommandDelegate)Marshal.GetDelegateForFunctionPointer(commandAddress, typeof(SOSCommandDelegate));
+
+ int result = commandFunc(_wrapper.ILLDBServices, arguments ?? "");
+ if (result != 0)
+ {
+ throw new InvalidOperationException($"SOS command FAILED 0x{result:X8}");
+ }
+ }
+ }
+}
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
-using System.Text;
using System.Threading;
namespace SOS
{
- internal class SymbolReader
+ public class SymbolReader
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
internal struct DebugInfo
/// Read memory callback
/// </summary>
/// <returns>number of bytes read or 0 for error</returns>
- internal unsafe delegate int ReadMemoryDelegate(ulong address, byte* buffer, int count);
+ public unsafe delegate int ReadMemoryDelegate(ulong address, byte* buffer, int count);
/// <summary>
/// Writeline delegate for symbol store logging
/// </summary>
/// <param name="message"></param>
- internal delegate void WriteLine([MarshalAs(UnmanagedType.LPStr)] string message);
+ public delegate void WriteLine([MarshalAs(UnmanagedType.LPStr)] string message);
/// <summary>
/// The LoadNativeSymbols callback
/// <param name="symbolCachePath">symbol cache directory path (optional)</param>
/// <param name="windowsSymbolPath">windows symbol path (optional)</param>
/// <returns></returns>
- internal static bool InitializeSymbolStore(bool logging, bool msdl, bool symweb, string symbolServerPath, string symbolCachePath, string windowsSymbolPath)
+ public static bool InitializeSymbolStore(bool logging, bool msdl, bool symweb, string symbolServerPath, string symbolCachePath, string windowsSymbolPath)
{
if (s_tracer == null) {
s_tracer = new Tracer(enabled: logging, enabledVerbose: logging, Console.WriteLine);
/// <summary>
/// Displays the symbol server and cache configuration
/// </summary>
- internal static void DisplaySymbolStore()
+ public static void DisplaySymbolStore()
{
if (s_tracer != null)
{
/// <summary>
/// This function disables any symbol downloading support.
/// </summary>
- internal static void DisableSymbolStore()
+ public static void DisableSymbolStore()
{
s_tracer = null;
s_symbolStore = null;
/// <param name="inMemoryPdbAddress">in memory PDB address or zero</param>
/// <param name="inMemoryPdbSize">in memory PDB size</param>
/// <returns>Symbol reader handle or zero if error</returns>
- internal static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, ulong loadedPeAddress, int loadedPeSize,
+ public static IntPtr LoadSymbolsForModule(string assemblyPath, bool isFileLayout, ulong loadedPeAddress, int loadedPeSize,
ulong inMemoryPdbAddress, int inMemoryPdbSize, ReadMemoryDelegate readMemory)
{
try
/// Cleanup and dispose of symbol reader handle
/// </summary>
/// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param>
- internal static void Dispose(IntPtr symbolReaderHandle)
+ public static void Dispose(IntPtr symbolReaderHandle)
{
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
try
/// <param name="methodToken">method token return</param>
/// <param name="ilOffset">IL offset return</param>
/// <returns> true if information is available</returns>
- internal static bool ResolveSequencePoint(IntPtr symbolReaderHandle, string filePath, int lineNumber, out int methodToken, out int ilOffset)
+ public static bool ResolveSequencePoint(IntPtr symbolReaderHandle, string filePath, int lineNumber, out int methodToken, out int ilOffset)
{
Debug.Assert(symbolReaderHandle != IntPtr.Zero);
methodToken = 0;
/// <param name="lineNumber">source line number return</param>
/// <param name="fileName">source file name return</param>
/// <returns> true if information is available</returns>
- internal static bool GetLineByILOffset(IntPtr symbolReaderHandle, int methodToken, long ilOffset, out int lineNumber, out IntPtr fileName)
+ public static bool GetLineByILOffset(IntPtr symbolReaderHandle, int methodToken, long ilOffset, out int lineNumber, out IntPtr fileName)
{
lineNumber = 0;
fileName = IntPtr.Zero;
/// <param name="localIndex">local variable index</param>
/// <param name="localVarName">local variable name return</param>
/// <returns>true if name has been found</returns>
- internal static bool GetLocalVariableName(IntPtr symbolReaderHandle, int methodToken, int localIndex, out IntPtr localVarName)
+ public static bool GetLocalVariableName(IntPtr symbolReaderHandle, int methodToken, int localIndex, out IntPtr localVarName)
{
localVarName = IntPtr.Zero;
/// <returns>stream or null</returns>
private static SymbolStoreFile GetSymbolStoreFile(SymbolStoreKey key)
{
- // Add the default symbol cache if it hasn't already been added
- if (!s_symbolCacheAdded) {
- s_symbolStore = new CacheSymbolStore(s_tracer, s_symbolStore, GetDefaultSymbolCache());
- s_symbolCacheAdded = true;
+ try
+ {
+ // Add the default symbol cache if it hasn't already been added
+ if (!s_symbolCacheAdded) {
+ s_symbolStore = new CacheSymbolStore(s_tracer, s_symbolStore, GetDefaultSymbolCache());
+ s_symbolCacheAdded = true;
+ }
+ return s_symbolStore.GetFile(key, CancellationToken.None).GetAwaiter().GetResult();
+ }
+ catch (Exception ex) when (ex is UnauthorizedAccessException || ex is BadImageFormatException || ex is IOException)
+ {
+ s_tracer.Error("Exception: {0}", ex.ToString());
+ return null;
}
- return s_symbolStore.GetFile(key, CancellationToken.None).GetAwaiter().GetResult();
}
/// <summary>
public void WriteLine(string message)
{
- m_output?.Invoke(message);
+ lock (this) {
+ m_output?.Invoke(message);
+ }
}
public void WriteLine(string format, params object[] arguments)
<ClInclude Include="ntinfo.h" />
<ClInclude Include="platformspecific.h" />
<ClInclude Include="sos.h" />
+ <ClInclude Include="soshostservices.h" />
<ClInclude Include="sos_md.h" />
<ClInclude Include="sos_stacktrace.h" />
<ClInclude Include="strike.h" />
<Filter>inc</Filter>
</ClInclude>
<ClInclude Include="hostcoreclr.h" />
+ <ClInclude Include="soshostservices.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Native.rc" />
{
return S_OK;
}
+#ifdef FEATURE_PAL
+ ToRelease<ISOSHostServices> hostServices(NULL);
+ if (SUCCEEDED(g_ExtServices->QueryInterface(__uuidof(ISOSHostServices), (void**)&hostServices)))
+ {
+ if (SUCCEEDED(hostServices->GetSOSNETCoreCallbacks(SOSNetCoreCallbacksVersion, &g_SOSNetCoreCallbacks)))
+ {
+ g_hostingInitialized = true;
+ return S_OK;
+ }
+ }
+#endif // FEATURE_PAL
coreclr_initialize_ptr initializeCoreCLR = nullptr;
coreclr_create_delegate_ptr createDelegate = nullptr;
std::string hostRuntimeDirectory;
return Status;
}
-/**********************************************************************\
- * Public entry point to set the managed callbacks (unused).
-\**********************************************************************/
-extern "C" void InitializeSymbolReaderCallbacks(SOSNetCoreCallbacks sosNetCoreCallbacks)
-{
- g_SOSNetCoreCallbacks = sosNetCoreCallbacks;
- g_hostingInitialized = true;
-}
-
//
// Pass to managed helper code to read in-memory PEs/PDBs.
// Returns the number of bytes read.
#ifndef __hostcoreclr_h__
#define __hostcoreclr_h__
+#include <soshostservices.h>
+
static const char *SymbolReaderDllName = "SOS.NETCore";
static const char *SymbolReaderClassName = "SOS.SymbolReader";
-typedef void (*OutputDelegate)(const char*);
-typedef int (*ReadMemoryDelegate)(ULONG64, uint8_t*, int);
-typedef void (*SymbolFileCallbackDelegate)(void*, const char* moduleFileName, const char* symbolFileName);
-
-typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, const char*);
-typedef void (*DisplaySymbolStoreDelegate)();
-typedef void (*DisableSymbolStoreDelegate)();
-typedef void (*LoadNativeSymbolsDelegate)(SymbolFileCallbackDelegate, void*, const char*, const char*, const char*, ULONG64, int, ReadMemoryDelegate);
-typedef PVOID (*LoadSymbolsForModuleDelegate)(const char*, BOOL, ULONG64, int, ULONG64, int, ReadMemoryDelegate);
-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*);
-
-struct SOSNetCoreCallbacks
-{
- InitializeSymbolStoreDelegate InitializeSymbolStoreDelegate;
- DisplaySymbolStoreDelegate DisplaySymbolStoreDelegate;
- DisableSymbolStoreDelegate DisableSymbolStoreDelegate;
- LoadNativeSymbolsDelegate LoadNativeSymbolsDelegate;
- LoadSymbolsForModuleDelegate LoadSymbolsForModuleDelegate;
- DisposeDelegate DisposeDelegate;
- ResolveSequencePointDelegate ResolveSequencePointDelegate;
- GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
- GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
-};
-
extern HMODULE g_hInstance;
extern LPCSTR g_hostRuntimeDirectory;
extern SOSNetCoreCallbacks g_SOSNetCoreCallbacks;
getCodeTypeFlags=GetCodeTypeFlags
TraceToCode
tracetocode=TraceToCode
-#endif
-
- InitializeSymbolReaderCallbacks
\ No newline at end of file
+#endif
\ No newline at end of file
Token2EE
u
VerifyHeap
-
-InitializeSymbolReaderCallbacks
\ No newline at end of file
--- /dev/null
+// 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.
+
+//----------------------------------------------------------------------------
+//
+// LLDB debugger services for sos
+//
+//----------------------------------------------------------------------------
+
+#ifndef __SOSHOSTSERVICES_H__
+#define __SOSHOSTSERVICES_H__
+
+#include <stdarg.h>
+#include <unknwn.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct SymbolModuleInfo;
+
+typedef void (*OutputDelegate)(const char*);
+typedef int (*ReadMemoryDelegate)(ULONG64, uint8_t*, int);
+typedef void (*SymbolFileCallbackDelegate)(void*, const char* moduleFileName, const char* symbolFilePath);
+
+typedef BOOL (*InitializeSymbolStoreDelegate)(BOOL, BOOL, BOOL, const char*, const char*, const char*);
+typedef void (*DisplaySymbolStoreDelegate)();
+typedef void (*DisableSymbolStoreDelegate)();
+typedef void (*LoadNativeSymbolsDelegate)(SymbolFileCallbackDelegate, void*, const char*, const char*, ULONG64, int, ReadMemoryDelegate);
+typedef PVOID (*LoadSymbolsForModuleDelegate)(const char*, BOOL, ULONG64, int, ULONG64, int, ReadMemoryDelegate);
+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*);
+
+#define SOSNetCoreCallbacksVersion 1
+
+struct SOSNetCoreCallbacks
+{
+ InitializeSymbolStoreDelegate InitializeSymbolStoreDelegate;
+ DisplaySymbolStoreDelegate DisplaySymbolStoreDelegate;
+ DisableSymbolStoreDelegate DisableSymbolStoreDelegate;
+ LoadNativeSymbolsDelegate LoadNativeSymbolsDelegate;
+ LoadSymbolsForModuleDelegate LoadSymbolsForModuleDelegate;
+ DisposeDelegate DisposeDelegate;
+ ResolveSequencePointDelegate ResolveSequencePointDelegate;
+ GetLineByILOffsetDelegate GetLineByILOffsetDelegate;
+ GetLocalVariableNameDelegate GetLocalVariableNameDelegate;
+};
+
+MIDL_INTERFACE("D13608FB-AD14-4B49-990A-80284F934C41")
+ISOSHostServices : public IUnknown
+{
+public:
+ //----------------------------------------------------------------------------
+ // ISOSHostServices
+ //----------------------------------------------------------------------------
+
+ virtual HRESULT GetSOSNETCoreCallbacks(
+ int version,
+ SOSNetCoreCallbacks* callbacks) = 0;
+};
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // #ifndef __SOSHOSTSERVICES_H__