Add CLRMA support to SOS. (#4437)
authorMike McLaughlin <mikem@microsoft.com>
Sat, 23 Dec 2023 07:53:38 +0000 (23:53 -0800)
committerGitHub <noreply@github.com>
Sat, 23 Dec 2023 07:53:38 +0000 (23:53 -0800)
Add the CLRMA exports on SOS.dll. Implement the CLRMA interfaces on top
of ICrashInfoServices.

Update ICrashInfoService to be more generic and not JSON crash info
specific.

Renamed IManagedException to IException.

Add IStackFrame.GetMethodName replacing Offset/MethodName.

Cleanup/change name of SOSHost.INativeClient

Change TraceError used in extensions lib not to depend on SOS globals
being initialized

34 files changed:
diagnostics.sln
src/Microsoft.Diagnostics.DebugServices.Implementation/CrashInfoService.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/ModuleServiceFromDataReader.cs
src/Microsoft.Diagnostics.DebugServices.Implementation/SpecialDiagInfo.cs
src/Microsoft.Diagnostics.DebugServices/ICrashInfoService.cs
src/Microsoft.Diagnostics.DebugServices/IException.cs [new file with mode: 0644]
src/Microsoft.Diagnostics.DebugServices/IManagedException.cs [deleted file]
src/Microsoft.Diagnostics.DebugServices/IStack.cs [new file with mode: 0644]
src/Microsoft.Diagnostics.DebugServices/IStackFrame.cs
src/Microsoft.Diagnostics.DebugServices/Microsoft.Diagnostics.DebugServices.csproj
src/Microsoft.Diagnostics.ExtensionCommands/CrashInfoCommand.cs
src/SOS/SOS.Extensions/Clrma/ExceptionWrapper.cs [new file with mode: 0644]
src/SOS/SOS.Extensions/Clrma/ManagedAnalysisWrapper.cs [new file with mode: 0644]
src/SOS/SOS.Extensions/Clrma/ThreadWrapper.cs [new file with mode: 0644]
src/SOS/SOS.Extensions/DebuggerServices.cs
src/SOS/SOS.Extensions/HostServices.cs
src/SOS/SOS.Extensions/TargetFromFromDebuggerServices.cs
src/SOS/SOS.Hosting/LLDBServices.cs
src/SOS/SOS.Hosting/SOSHost.cs
src/SOS/SOS.Hosting/SOSLibrary.cs
src/SOS/SOS.Hosting/ServiceWrapper.cs
src/SOS/SOS.Hosting/TargetWrapper.cs
src/SOS/Strike/CMakeLists.txt
src/SOS/Strike/Strike.vcxproj
src/SOS/Strike/Strike.vcxproj.filters
src/SOS/Strike/clrma.cpp [new file with mode: 0644]
src/SOS/Strike/sos.def
src/SOS/Strike/util.cpp
src/SOS/extensions/extensions.cpp
src/SOS/extensions/hostcoreclr.cpp
src/SOS/inc/clrma.h [new file with mode: 0644]
src/SOS/inc/clrma.idl [new file with mode: 0644]
src/SOS/lldbplugin/services.cpp
src/SOS/lldbplugin/sosplugin.cpp

index 23ae2ff91a3a2062650dc7032e1b6a16bb7abd47..08398b86bf4b531a7471d23ef32cdd00e6738a4a 100644 (file)
@@ -219,6 +219,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Diagnostics.Debug
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "inc", "inc", "{BE45F03E-D700-404F-A890-8ED7D8969958}"
        ProjectSection(SolutionItems) = preProject
+               src\SOS\inc\clrma.h = src\SOS\inc\clrma.h
+               src\SOS\inc\clrma.idl = src\SOS\inc\clrma.idl
                src\SOS\inc\debuggerservices.h = src\SOS\inc\debuggerservices.h
                src\SOS\inc\host.h = src\SOS\inc\host.h
                src\SOS\inc\hostservices.h = src\SOS\inc\hostservices.h
index 2f7282e0ae4d2b4632ec8d519718950fc49ec623..cee810569c64984cd09031c3ac89ab365060890b 100644 (file)
@@ -4,6 +4,8 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
+using System.Linq;
 using System.Text;
 using System.Text.Json;
 using System.Text.Json.Serialization;
@@ -22,7 +24,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
         /// </summary>
         public const uint FAST_FAIL_EXCEPTION_DOTNET_AOT = 0x48;
 
-        public sealed class CrashInfoJson
+        private sealed class CrashInfoJson
         {
             [JsonPropertyName("version")]
             public string Version { get; set; }
@@ -48,10 +50,10 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             public string Message { get; set; }
 
             [JsonPropertyName("exception")]
-            public CrashInfoException Exception { get; set; }
+            public ExceptionJson Exception { get; set; }
         }
 
-        public sealed class CrashInfoException : IManagedException
+        private sealed class ExceptionJson
         {
             [JsonPropertyName("address")]
             [JsonConverter(typeof(HexUInt64Converter))]
@@ -68,17 +70,13 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             public string Type { get; set; }
 
             [JsonPropertyName("stack")]
-            public CrashInfoStackFrame[] Stack { get; set; }
-
-            IEnumerable<IStackFrame> IManagedException.Stack => Stack;
+            public StackFrameJson[] Stack { get; set; }
 
             [JsonPropertyName("inner")]
-            public CrashInfoException[] InnerExceptions { get; set; }
-
-            IEnumerable<IManagedException> IManagedException.InnerExceptions => InnerExceptions;
+            public ExceptionJson[] InnerExceptions { get; set; }
         }
 
-        public sealed class CrashInfoStackFrame : IStackFrame
+        private sealed class StackFrameJson
         {
             [JsonPropertyName("ip")]
             [JsonConverter(typeof(HexUInt64Converter))]
@@ -100,7 +98,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             public string MethodName { get; set; }
         }
 
-        public sealed class HexUInt64Converter : JsonConverter<ulong>
+        private sealed class HexUInt64Converter : JsonConverter<ulong>
         {
             public override ulong Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
             {
@@ -117,7 +115,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             public override void Write(Utf8JsonWriter writer, ulong value, JsonSerializerOptions options) => throw new NotImplementedException();
         }
 
-        public sealed class HexUInt32Converter : JsonConverter<uint>
+        private sealed class HexUInt32Converter : JsonConverter<uint>
         {
             public override uint Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
             {
@@ -134,7 +132,90 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             public override void Write(Utf8JsonWriter writer, uint value, JsonSerializerOptions options) => throw new NotImplementedException();
         }
 
-        public static ICrashInfoService Create(uint hresult, ReadOnlySpan<byte> triageBuffer)
+        private sealed class CrashInfoException : IException
+        {
+            private readonly ExceptionJson _exception;
+            private readonly IModuleService _moduleService;
+            private IStack _stack;
+            private IEnumerable<IException> _inner;
+
+            public CrashInfoException(ExceptionJson exception, IModuleService moduleService)
+            {
+                Debug.Assert(exception != null);
+                Debug.Assert(moduleService != null);
+                _exception = exception;
+                _moduleService = moduleService;
+            }
+
+            public ulong Address => _exception.Address;
+
+            public uint HResult => _exception.HResult;
+
+            public string Message => _exception.Message;
+
+            public string Type => _exception.Type;
+
+            public IStack Stack => _stack ??= new CrashInfoStack(_exception.Stack, _moduleService);
+
+            public IEnumerable<IException> InnerExceptions => _inner ??= _exception.InnerExceptions != null ? _exception.InnerExceptions.Select((inner) => new CrashInfoException(inner, _moduleService)) : Array.Empty<IException>();
+        }
+
+        private sealed class CrashInfoStack : IStack
+        {
+            private readonly IStackFrame[] _stackFrames;
+
+            public CrashInfoStack(StackFrameJson[] stackFrames, IModuleService moduleService)
+            {
+                _stackFrames = stackFrames != null ? stackFrames.Select((frame) => new CrashInfoStackFrame(frame, moduleService)).ToArray() : Array.Empty<IStackFrame>();
+            }
+
+            public int FrameCount => _stackFrames.Length;
+
+            public IStackFrame GetStackFrame(int index) => _stackFrames[index];
+        }
+
+        private sealed class CrashInfoStackFrame : IStackFrame
+        {
+            private readonly StackFrameJson _stackFrame;
+            private readonly IModuleService _moduleService;
+
+            public CrashInfoStackFrame(StackFrameJson stackFrame, IModuleService moduleService)
+            {
+                Debug.Assert(stackFrame != null);
+                Debug.Assert(moduleService != null);
+                _stackFrame = stackFrame;
+                _moduleService = moduleService;
+            }
+
+            public ulong InstructionPointer => _stackFrame.InstructionPointer;
+
+            public ulong StackPointer => _stackFrame.StackPointer;
+
+            public ulong ModuleBase => _stackFrame.ModuleBase;
+
+            public void GetMethodName(out string moduleName, out string methodName, out ulong displacement)
+            {
+                moduleName = null;
+                methodName = _stackFrame.MethodName;
+                displacement = _stackFrame.Offset;
+
+                if (ModuleBase != 0)
+                {
+                    IModule module = _moduleService.GetModuleFromBaseAddress(_stackFrame.ModuleBase);
+                    if (module != null)
+                    {
+                        moduleName = Path.GetFileNameWithoutExtension(module.FileName);
+                        if (string.IsNullOrEmpty(methodName))
+                        {
+                            IModuleSymbols moduleSymbols = module.Services.GetService<IModuleSymbols>();
+                            moduleSymbols?.TryGetSymbolName(_stackFrame.InstructionPointer, out methodName, out displacement);
+                        }
+                    }
+                }
+            }
+        }
+
+        public static ICrashInfoService Create(uint hresult, ReadOnlySpan<byte> triageBuffer, IModuleService moduleService)
         {
             CrashInfoService crashInfoService = null;
             try
@@ -145,7 +226,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                 {
                     if (Version.TryParse(crashInfo.Version, out Version protocolVersion) && protocolVersion.Major >= 1)
                     {
-                        crashInfoService = new(crashInfo.Thread, hresult, crashInfo);
+                        crashInfoService = new(crashInfo.Thread, hresult, crashInfo, moduleService);
                     }
                     else
                     {
@@ -157,14 +238,16 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                     Trace.TraceError($"CrashInfoService: JsonSerializer.Deserialize failed");
                 }
             }
-            catch (Exception ex) when (ex is JsonException or NotSupportedException or DecoderFallbackException or ArgumentException)
+            catch (Exception ex) when (ex is System.Text.Json.JsonException or NotSupportedException or DecoderFallbackException or ArgumentException)
             {
                 Trace.TraceError($"CrashInfoService: {ex}");
             }
             return crashInfoService;
         }
 
-        private CrashInfoService(uint threadId, uint hresult, CrashInfoJson crashInfo)
+        private readonly IException _exception;
+
+        private CrashInfoService(uint threadId, uint hresult, CrashInfoJson crashInfo, IModuleService moduleService)
         {
             ThreadId = threadId;
             HResult = hresult;
@@ -173,7 +256,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             RuntimeVersion = crashInfo.RuntimeVersion;
             RuntimeType = (RuntimeType)crashInfo.RuntimeType;
             Message = crashInfo.Message;
-            Exception = crashInfo.Exception;
+            _exception = crashInfo.Exception != null ? new CrashInfoException(crashInfo.Exception, moduleService) : null;
         }
 
         #region ICrashInfoService
@@ -192,7 +275,60 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
 
         public string Message { get; }
 
-        public IManagedException Exception { get; }
+        public IException GetException(ulong address)
+        {
+            // Only supports getting the "current" exception or the crash exception.
+            if (address != 0)
+            {
+                if (address != _exception.Address)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(address));
+                }
+            }
+            return _exception;
+        }
+
+        public IException GetThreadException(uint threadId)
+        {
+            // Only supports getting the "current" exception or the crash thread's exception
+            if (threadId != 0)
+            {
+                if (threadId != ThreadId)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(threadId));
+                }
+            }
+            return _exception;
+        }
+
+        public IEnumerable<IException> GetNestedExceptions(uint threadId)
+        {
+            // Only supports getting the "current" exception or the crash thread's exception
+            if (threadId != 0)
+            {
+                if (threadId != ThreadId)
+                {
+                    throw new ArgumentOutOfRangeException(nameof(threadId));
+                }
+            }
+
+            List<IException> exceptions = new() {
+                _exception
+            };
+
+            AddExceptions(_exception.InnerExceptions);
+
+            void AddExceptions(IEnumerable<IException> inner)
+            {
+                foreach (IException exception in inner)
+                {
+                    exceptions.Add(exception);
+                    AddExceptions(exception.InnerExceptions);
+                }
+            }
+
+            return exceptions;
+        }
 
         #endregion
     }
index e7fad8aead9b75c76fe0fe27d65899361780f26b..075636ec9c0b2804d6fe2cf18d69ae0682c0bd71 100644 (file)
@@ -65,7 +65,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
             {
                 if (InitializeValue(Module.Flags.InitializeVersion))
                 {
-                    if (!_moduleInfo.Version.Equals(Utilities.EmptyVersion))
+                    if (_moduleInfo.Version != null && !_moduleInfo.Version.Equals(Utilities.EmptyVersion))
                     {
                         _version = _moduleInfo.Version;
                     }
index 32d7989a93bc4abd20a29a24722f198a839beaa5..74a5093b9e88d4fd0cfda79ea87e5e999b7d304c 100644 (file)
@@ -102,7 +102,7 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
                 Span<byte> buffer = new byte[triageBufferSize];
                 if (services.GetService<IMemoryService>().ReadMemory(triageBufferAddress, buffer, out int bytesRead) && bytesRead == triageBufferSize)
                 {
-                    return CrashInfoService.Create(hresult, buffer);
+                    return CrashInfoService.Create(hresult, buffer, services.GetService<IModuleService>());
                 }
                 else
                 {
index 1d04cab52088e6c9a6d17fa65d7039dd915e374e..143532cdc3a58a04c6361e1988efa48733cef06c 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
 
 namespace Microsoft.Diagnostics.DebugServices
 {
@@ -57,8 +58,27 @@ namespace Microsoft.Diagnostics.DebugServices
         string Message { get; }
 
         /// <summary>
-        /// The exception that caused the crash or null
+        /// The exception at the address
         /// </summary>
-        IManagedException Exception { get; }
+        /// <param name="address">address of exception object or 0 for current exception</param>
+        /// <returns>exception or null if none</returns>
+        /// <exception cref="ArgumentOutOfRangeException">invalid exception address</exception>
+        IException GetException(ulong address);
+
+        /// <summary>
+        /// Returns the thread's current exception.
+        /// </summary>
+        /// <param name="threadId">OS thread id</param>
+        /// <returns>exception or null if none</returns>
+        /// <exception cref="ArgumentOutOfRangeException">invalid thread id</exception>
+        IException GetThreadException(uint threadId);
+
+        /// <summary>
+        /// Returns all the thread's nested exception.
+        /// </summary>
+        /// <param name="threadId">OS thread id</param>
+        /// <returns>array of nested exceptions</returns>
+        /// <exception cref="ArgumentOutOfRangeException">invalid thread id</exception>
+        IEnumerable<IException> GetNestedExceptions(uint threadId);
     }
 }
diff --git a/src/Microsoft.Diagnostics.DebugServices/IException.cs b/src/Microsoft.Diagnostics.DebugServices/IException.cs
new file mode 100644 (file)
index 0000000..13c3493
--- /dev/null
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+    /// <summary>
+    /// Describes a managed exception
+    /// </summary>
+    public interface IException
+    {
+        /// <summary>
+        /// Exception object address
+        /// </summary>
+        ulong Address { get; }
+
+        /// <summary>
+        /// The exception type name
+        /// </summary>
+        string Type { get; }
+
+        /// <summary>
+        /// The exception message
+        /// </summary>
+        string Message { get; }
+
+        /// <summary>
+        /// Exception.HResult
+        /// </summary>
+        uint HResult { get; }
+
+        /// <summary>
+        /// Stack trace of exception or null
+        /// </summary>
+        IStack Stack { get; }
+
+        /// <summary>
+        /// The inner exception or exceptions in the AggregateException case
+        /// </summary>
+        IEnumerable<IException> InnerExceptions { get; }
+    }
+}
diff --git a/src/Microsoft.Diagnostics.DebugServices/IManagedException.cs b/src/Microsoft.Diagnostics.DebugServices/IManagedException.cs
deleted file mode 100644 (file)
index f73b172..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System.Collections.Generic;
-
-namespace Microsoft.Diagnostics.DebugServices
-{
-    /// <summary>
-    /// Describes a managed exception
-    /// </summary>
-    public interface IManagedException
-    {
-        /// <summary>
-        /// Exception object address
-        /// </summary>
-        ulong Address { get; }
-
-        /// <summary>
-        /// The exception type name
-        /// </summary>
-        string Type { get; }
-
-        /// <summary>
-        /// The exception message
-        /// </summary>
-        string Message { get; }
-
-        /// <summary>
-        /// Exception.HResult
-        /// </summary>
-        uint HResult { get; }
-
-        /// <summary>
-        /// Stack trace of exception
-        /// </summary>
-        IEnumerable<IStackFrame> Stack { get; }
-
-        /// <summary>
-        /// The inner exception or exceptions in the AggregateException case
-        /// </summary>
-        IEnumerable<IManagedException> InnerExceptions { get; }
-    }
-}
diff --git a/src/Microsoft.Diagnostics.DebugServices/IStack.cs b/src/Microsoft.Diagnostics.DebugServices/IStack.cs
new file mode 100644 (file)
index 0000000..b8d0a77
--- /dev/null
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Diagnostics.DebugServices
+{
+    /// <summary>
+    /// Native or managed stack
+    /// </summary>
+    public interface IStack
+    {
+        /// <summary>
+        /// Number of total stack frames
+        /// </summary>
+        int FrameCount { get; }
+
+        /// <summary>
+        /// Get an individual stack frame
+        /// </summary>
+        /// <param name="index">stack frame index</param>
+        /// <returns>frame</returns>
+        /// <exception cref="ArgumentOutOfRangeException">invalid index</exception>
+        IStackFrame GetStackFrame(int index);
+    }
+}
index 42f33eb7f6456fa7c0f955dc26165eeeb327ef9e..2fd8a6e7d1c62645589dbe491f5e23ed965cab8b 100644 (file)
@@ -21,16 +21,14 @@ namespace Microsoft.Diagnostics.DebugServices
         /// <summary>
         /// The module base of the IP
         /// </summary>
-        public ulong ModuleBase { get; }
+        ulong ModuleBase { get; }
 
         /// <summary>
-        /// Offset from beginning of method
+        /// Returns the module, method name and displacement
         /// </summary>
-        uint Offset { get; }
-
-        /// <summary>
-        /// The exception type name
-        /// </summary>
-        string MethodName { get; }
+        /// <param name="moduleName">the module name of the method or null</param>
+        /// <param name="methodName">the method name or null</param>
+        /// <param name="displacement">the offset from the beginning of the function</param>
+        void GetMethodName(out string moduleName, out string methodName, out ulong displacement);
     }
 }
index e550154f292f110d761a7f7c1020b702fa1268a2..1c547c5c6aaa138b247a65f9405d7bb2ed312904 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFramework>netstandard2.0</TargetFramework>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
index 67c69b3aed100d8ef39a9c483eac7eca09e9c01c..41ad047e6c9e448e54817011fa1a3e539774002a 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 using System.Linq;
 using System.Runtime.InteropServices;
@@ -15,17 +16,12 @@ namespace Microsoft.Diagnostics.ExtensionCommands
         [ServiceImport(Optional = true)]
         public ICrashInfoService CrashInfo { get; set; }
 
-        [ServiceImport]
-        public IModuleService ModuleService { get; set; }
-
         public override void Invoke()
         {
             if (CrashInfo == null)
             {
                 throw new DiagnosticsException("No crash info to display");
             }
-            WriteLine();
-
             WriteLine($"CrashReason:        {CrashInfo.CrashReason}");
             WriteLine($"ThreadId:           {CrashInfo.ThreadId:X4}");
             WriteLine($"HResult:            {CrashInfo.HResult:X4}");
@@ -34,47 +30,64 @@ namespace Microsoft.Diagnostics.ExtensionCommands
             WriteLine($"RuntimeVersion:     {CrashInfo.RuntimeVersion}");
             WriteLine($"Message:            {CrashInfo.Message}");
 
-            if (CrashInfo.Exception != null)
+            WriteLine();
+            WriteLine("** Current Exception **");
+            WriteLine();
+            IException exception = CrashInfo.GetException(0);
+            if (exception != null)
+            {
+                WriteLine("-----------------------------------------------");
+                PrintException(exception, string.Empty);
+            }
+
+            WriteLine();
+            WriteLine($"** Thread {CrashInfo.ThreadId} Exception **");
+            WriteLine();
+            exception = CrashInfo.GetThreadException(CrashInfo.ThreadId);
+            if (exception != null)
+            {
+                WriteLine("-----------------------------------------------");
+                PrintException(exception, string.Empty);
+            }
+
+            WriteLine();
+            WriteLine("** Nested Exceptions **");
+            WriteLine();
+            IEnumerable<IException> exceptions = CrashInfo.GetNestedExceptions(CrashInfo.ThreadId);
+            foreach (IException ex in exceptions)
             {
                 WriteLine("-----------------------------------------------");
-                PrintException(CrashInfo.Exception, string.Empty);
+                PrintException(ex, string.Empty);
             }
         }
 
-        private void PrintException(IManagedException exception, string indent)
+        private void PrintException(IException exception, string indent)
         {
             WriteLine($"{indent}Exception object:   {exception.Address:X16}");
             WriteLine($"{indent}Exception type:     {exception.Type}");
             WriteLine($"{indent}HResult:            {exception.HResult:X8}");
             WriteLine($"{indent}Message:            {exception.Message}");
 
-            if (exception.Stack != null && exception.Stack.Any())
+            IStack stack = exception.Stack;
+            if (stack.FrameCount > 0)
             {
                 WriteLine($"{indent}StackTrace:");
                 WriteLine($"{indent}    IP               Function");
-                foreach (IStackFrame frame in exception.Stack)
+                for (int index = 0; index < stack.FrameCount; index++)
                 {
-                    string moduleName = "<unknown_module>";
-                    if (frame.ModuleBase != 0)
-                    {
-                        IModule module = ModuleService.GetModuleFromBaseAddress(frame.ModuleBase);
-                        if (module != null)
-                        {
-                            moduleName = Path.GetFileName(module.FileName);
-                        }
-                    }
-                    string methodName = frame.MethodName ?? "<unknown>";
-                    WriteLine($"{indent}    {frame.InstructionPointer:X16} {moduleName}!{methodName} + 0x{frame.Offset:X}");
+                    IStackFrame frame = stack.GetStackFrame(index);
+                    frame.GetMethodName(out string moduleName, out string methodName, out ulong displacement);
+                    WriteLine($"{indent}    {frame.InstructionPointer:X16} {moduleName ?? "<unknown_module>"}!{methodName ?? "<unknown>"} + 0x{displacement:X}");
                 }
             }
 
-            if (exception.InnerExceptions != null)
+            if (exception.InnerExceptions.Any())
             {
-                WriteLine("InnerExceptions:");
-                foreach (IManagedException inner in exception.InnerExceptions)
+                WriteLine($"{indent}InnerExceptions:");
+                foreach (IException inner in exception.InnerExceptions)
                 {
-                    WriteLine("-----------------------------------------------");
-                    PrintException(inner, "    ");
+                    WriteLine($"{indent}-----------------------------------------------");
+                    PrintException(inner, $"{indent}    ");
                 }
             }
         }
diff --git a/src/SOS/SOS.Extensions/Clrma/ExceptionWrapper.cs b/src/SOS/SOS.Extensions/Clrma/ExceptionWrapper.cs
new file mode 100644 (file)
index 0000000..7380306
--- /dev/null
@@ -0,0 +1,211 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Microsoft.Diagnostics.DebugServices;
+using Microsoft.Diagnostics.Runtime.Utilities;
+
+namespace SOS.Extensions.Clrma
+{
+    public sealed class ExceptionWrapper : COMCallableIUnknown
+    {
+        public static readonly Guid IID_ICLRMAClrException = new("7C165652-D539-472e-A6CF-F657FFF31751");
+
+        public IException Exception { get; }
+
+        public IntPtr ICLRMACClrException { get; }
+
+        private ExceptionWrapper[] _innerExceptions;
+
+        public ExceptionWrapper(IException exception)
+        {
+            Debug.Assert(exception != null);
+            Exception = exception;
+
+            VTableBuilder builder = AddInterface(IID_ICLRMAClrException, validate: false);
+            builder.AddMethod(new DebuggerCommandDelegate(DebuggerCommand));
+            builder.AddMethod(new AddressDelegate(GetAddress));
+            builder.AddMethod(new HResultDelegate(GetHResult));
+            builder.AddMethod(new TypeDelegate(GetType));
+            builder.AddMethod(new MessageDelegate(GetMessage));
+            builder.AddMethod(new FrameCountDelegate(FrameCount));
+            builder.AddMethod(new FrameDelegate(Frame));
+            builder.AddMethod(new InnerExceptionCountDelegate(InnerExceptionCount));
+            builder.AddMethod(new InnerExceptionDelegate(InnerException));
+            ICLRMACClrException = builder.Complete();
+
+            AddRef();
+        }
+
+        protected override void Destroy()
+        {
+            Trace.TraceInformation("ExceptionWrapper.Destroy");
+        }
+
+        private int DebuggerCommand(
+            IntPtr self,
+            out string command)
+        {
+            command = null;
+            return HResult.S_FALSE;
+        }
+
+        private int GetAddress(
+            IntPtr self,
+            out ulong address)
+        {
+            address = Exception.Address;
+            return HResult.S_OK;
+        }
+
+        private int GetHResult(
+            IntPtr self,
+            out uint hresult)
+        {
+            hresult = Exception.HResult;
+            return HResult.S_OK;
+        }
+
+        private int GetType(
+            IntPtr self,
+            out string type)
+        {
+            type = Exception.Type;
+            return HResult.S_OK;
+        }
+
+        private int GetMessage(
+            IntPtr self,
+            out string message)
+        {
+            message = Exception.Message;
+            return HResult.S_OK;
+        }
+
+        private int FrameCount(
+            IntPtr self,
+            out int count)
+        {
+            count = Exception.Stack.FrameCount;
+            return count > 0 ? HResult.S_OK : HResult.S_FALSE;
+        }
+
+        private int Frame(
+            IntPtr self,
+            int nFrame,
+            out ulong ip,
+            out ulong sp,
+            out string moduleName,
+            out string functionName,
+            out ulong displacement)
+        {
+            ip = 0;
+            sp = 0;
+            moduleName = null;
+            functionName = null;
+            displacement = 0;
+            IStackFrame frame;
+            try
+            {
+                frame = Exception.Stack.GetStackFrame(nFrame);
+            }
+            catch (ArgumentOutOfRangeException)
+            {
+                return ManagedAnalysisWrapper.E_BOUNDS;
+            }
+            ip = frame.InstructionPointer;
+            sp = frame.StackPointer;
+            frame.GetMethodName(out moduleName, out functionName, out displacement);
+            moduleName ??= $"module_{frame.ModuleBase:X16}";
+            functionName ??= $"function_{frame.InstructionPointer:X16}";
+            return HResult.S_OK;
+        }
+
+        private int InnerExceptionCount(
+            IntPtr self,
+            out ushort count)
+        {
+            count = (ushort)InnerExceptions.Length;
+            return count > 0 ? HResult.S_OK : HResult.S_FALSE;
+        }
+
+        private int InnerException(
+            IntPtr self,
+            ushort index,
+            out IntPtr clrmaClrException)
+        {
+            clrmaClrException = IntPtr.Zero;
+            if (index >= InnerExceptions.Length)
+            {
+                return ManagedAnalysisWrapper.E_BOUNDS;
+            }
+            ExceptionWrapper exception = InnerExceptions[index];
+            exception.AddRef();
+            clrmaClrException = exception.ICLRMACClrException;
+            return HResult.S_OK;
+        }
+
+        private ExceptionWrapper[] InnerExceptions
+        {
+            get { return _innerExceptions ??= Exception.InnerExceptions.Select((exception) => new ExceptionWrapper(exception)).ToArray(); }
+        }
+
+        #region ICLRMAClrException delegates
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int DebuggerCommandDelegate(
+            [In] IntPtr self,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string command);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int AddressDelegate(
+            [In] IntPtr self,
+            [Out] out ulong address);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int HResultDelegate(
+            [In] IntPtr self,
+            [Out] out uint hresult);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int TypeDelegate(
+            [In] IntPtr self,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string type);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int MessageDelegate(
+            [In] IntPtr self,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string message);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int FrameCountDelegate(
+            [In] IntPtr self,
+            [Out] out int count);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int FrameDelegate(
+            [In] IntPtr self,
+            [In] int nFrame,
+            [Out] out ulong ip,
+            [Out] out ulong sp,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string moduleName,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string functionName,
+            [Out] out ulong displacement);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int InnerExceptionCountDelegate(
+            [In] IntPtr self,
+            [Out] out ushort count);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int InnerExceptionDelegate(
+            [In] IntPtr self,
+            [In] ushort index,
+            [Out] out IntPtr clrmaClrException);
+
+        #endregion
+    }
+}
diff --git a/src/SOS/SOS.Extensions/Clrma/ManagedAnalysisWrapper.cs b/src/SOS/SOS.Extensions/Clrma/ManagedAnalysisWrapper.cs
new file mode 100644 (file)
index 0000000..9e4fb30
--- /dev/null
@@ -0,0 +1,245 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Microsoft.Diagnostics.DebugServices;
+using Microsoft.Diagnostics.Runtime.Utilities;
+using SOS.Hosting;
+using SOS.Hosting.DbgEng.Interop;
+
+namespace SOS.Extensions.Clrma
+{
+    public sealed class ManagedAnalysisWrapper : COMCallableIUnknown
+    {
+        public static readonly Guid IID_ICLRManagedAnalysis = new("8CA73A16-C017-4c8f-AD51-B758727478CA");
+
+        public const int E_BOUNDS = unchecked((int)0x8000000B);
+        public const uint DEBUG_ANY_ID = uint.MaxValue;
+
+        private readonly IServiceProvider _serviceProvider;
+        private readonly ServiceWrapper _serviceWrapper;
+        private ICrashInfoService _crashInfoService;
+        private IDebugClient _debugClient;
+        private ThreadWrapper _thread;
+        private ExceptionWrapper _exception;
+
+        public ManagedAnalysisWrapper(ITarget target, IServiceProvider serviceProvider, ServiceWrapper serviceWrapper)
+        {
+            _serviceProvider = serviceProvider;
+            _serviceWrapper = serviceWrapper;
+
+            target.OnFlushEvent.Register(Flush);
+
+            VTableBuilder builder = AddInterface(IID_ICLRManagedAnalysis, validate: false);
+            builder.AddMethod(new GetProviderNameDelegate(GetProviderName));
+            builder.AddMethod(new AssociateClientDelegate(AssociateClient));
+            builder.AddMethod(new GetThreadDelegate(GetThread));
+            builder.AddMethod(new GetExceptionDelegate(GetException));
+            builder.AddMethod(new ObjectInspectionDelegate(ObjectInspection));
+            builder.Complete();
+            // Since this wrapper is only created through a ServiceWrapper factory, no AddRef() is needed.
+        }
+
+        protected override void Destroy()
+        {
+            Trace.TraceInformation("ManagedAnalysisWrapper.Destroy");
+            _serviceWrapper.RemoveServiceWrapper(ManagedAnalysisWrapper.IID_ICLRManagedAnalysis);
+            Flush();
+        }
+
+        private void Flush()
+        {
+            _crashInfoService = null;
+            FlushDebugClient();
+            FlushThread();
+            FlushException();
+        }
+
+        private void FlushDebugClient()
+        {
+            if (_debugClient != null)
+            {
+                int count = Marshal.ReleaseComObject(_debugClient);
+                Debug.Assert(count >= 0);
+                _debugClient = null;
+            }
+        }
+
+        private void FlushThread()
+        {
+            _thread?.ReleaseWithCheck();
+            _thread = null;
+        }
+
+        private void FlushException()
+        {
+            _exception?.ReleaseWithCheck();
+            _exception = null;
+        }
+
+        private int GetProviderName(
+            IntPtr self,
+            out string provider)
+        {
+            provider = "SOSCLRMA";
+            return HResult.S_OK;
+        }
+
+        private int AssociateClient(
+            IntPtr self,
+            IntPtr punk)
+        {
+            // If the crash info service doesn't exist, then tell Watson/CLRMA to go on to the next provider
+            if (CrashInfoService is null)
+            {
+                return HResult.E_NOINTERFACE;
+            }
+            FlushDebugClient();
+            _debugClient = Marshal.GetObjectForIUnknown(punk) as IDebugClient;
+            if (_debugClient == null)
+            {
+                return HResult.E_NOINTERFACE;
+            }
+            // We don't currently need the IDebugClient instance passed this this function.
+            return HResult.S_OK;
+        }
+
+        private int GetThread(
+            IntPtr self,
+            uint osThreadId,
+            out IntPtr clrmaClrThread)
+        {
+            clrmaClrThread = IntPtr.Zero;
+            if (CrashInfoService is null)
+            {
+                return HResult.E_FAIL;
+            }
+            // osThreadId == 0 is current thread and -1 is "last event thread". The only thread
+            // information we have currently is the crashing thread id so always return it.
+            if (osThreadId == 0)
+            {
+                HResult hr = ((IDebugSystemObjects)_debugClient).GetCurrentThreadSystemId(out osThreadId);
+                if (!hr.IsOK)
+                {
+                    return hr;
+                }
+            }
+            else if (osThreadId == uint.MaxValue)
+            {
+                HResult hr = ((IDebugControl)_debugClient).GetLastEventInformation(
+                    out DEBUG_EVENT _,
+                    out uint _,
+                    out uint threadIndex,
+                    IntPtr.Zero,
+                    0,
+                    out uint _,
+                    null,
+                    0,
+                    out uint _);
+
+                if (!hr.IsOK)
+                {
+                    return hr;
+                }
+                if (threadIndex == DEBUG_ANY_ID)
+                {
+                    return HResult.E_INVALIDARG;
+                }
+                uint[] ids = new uint[1];
+                uint[] sysIds = new uint[1];
+                hr = ((IDebugSystemObjects)_debugClient).GetThreadIdsByIndex(threadIndex, 1, ids, sysIds);
+                if (!hr.IsOK)
+                {
+                    return hr;
+                }
+                osThreadId = sysIds[0];
+            }
+            if (_thread is null || _thread.ThreadId != osThreadId)
+            {
+                IThread thread = ThreadService?.GetThreadFromId(osThreadId);
+                if (thread is null)
+                {
+                    return HResult.E_INVALIDARG;
+                }
+                FlushThread();
+                _thread = new ThreadWrapper(CrashInfoService, thread);
+            }
+            _thread.AddRef();
+            clrmaClrThread = _thread.ICLRMACClrThread;
+            return HResult.S_OK;
+        }
+
+        private int GetException(
+            IntPtr self,
+            ulong address,
+            out IntPtr clrmaClrException)
+        {
+            clrmaClrException = IntPtr.Zero;
+            if (_exception is null || _exception.Exception.Address != address)
+            {
+                IException exception = null;
+                try
+                {
+                    exception = CrashInfoService?.GetException(address);
+                }
+                catch (ArgumentOutOfRangeException)
+                {
+                }
+                if (exception is null)
+                {
+                    return HResult.E_INVALIDARG;
+                }
+                FlushException();
+                _exception = new ExceptionWrapper(exception);
+            }
+            _exception.AddRef();
+            clrmaClrException = _exception.ICLRMACClrException;
+            return HResult.S_OK;
+        }
+
+        private int ObjectInspection(
+            IntPtr self,
+            out IntPtr clrmaObjectInspection)
+        {
+            clrmaObjectInspection = IntPtr.Zero;
+            return HResult.E_NOTIMPL;
+        }
+
+        private ICrashInfoService CrashInfoService => _crashInfoService ??= _serviceProvider.GetService<ICrashInfoService>();
+
+        private IThreadService ThreadService => _serviceProvider.GetService<IThreadService>();
+
+        #region ICLRManagedAnalysis delegates
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int GetProviderNameDelegate(
+            [In] IntPtr self,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string provider);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int AssociateClientDelegate(
+            [In] IntPtr self,
+            [In] IntPtr punk);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int GetThreadDelegate(
+            [In] IntPtr self,
+            [In] uint osThreadId,
+            [Out] out IntPtr clrmaClrThread);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int GetExceptionDelegate(
+            [In] IntPtr self,
+            [In] ulong address,
+            [Out] out IntPtr clrmaClrException);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int ObjectInspectionDelegate(
+            [In] IntPtr self,
+            [Out] out IntPtr objectInspection);
+
+        #endregion
+    }
+}
diff --git a/src/SOS/SOS.Extensions/Clrma/ThreadWrapper.cs b/src/SOS/SOS.Extensions/Clrma/ThreadWrapper.cs
new file mode 100644 (file)
index 0000000..5c797ea
--- /dev/null
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.InteropServices;
+using Microsoft.Diagnostics.DebugServices;
+using Microsoft.Diagnostics.Runtime.Utilities;
+using SOS.Hosting;
+
+namespace SOS.Extensions.Clrma
+{
+    public sealed class ThreadWrapper : COMCallableIUnknown
+    {
+        public static readonly Guid IID_ICLRMAClrThread = new("9849CFC9-0868-406e-9059-6B04E9ADBBB8");
+
+        public uint ThreadId => _thread.ThreadId;
+
+        public IntPtr ICLRMACClrThread { get; }
+
+        private readonly ICrashInfoService _crashInfoService;
+        private readonly IThread _thread;
+        private ExceptionWrapper _currentException;
+        private ExceptionWrapper[] _nestedExceptions;
+
+        public ThreadWrapper(ICrashInfoService crashInfoService, IThread thread)
+        {
+            Debug.Assert(crashInfoService != null);
+            _crashInfoService = crashInfoService;
+            _thread = thread;
+
+            VTableBuilder builder = AddInterface(IID_ICLRMAClrThread, validate: false);
+            builder.AddMethod(new DebuggerCommandDelegate(DebuggerCommand));
+            builder.AddMethod(new OSThreadIdDelegate(OSThreadId));
+            builder.AddMethod(new FrameCountDelegate(FrameCount));
+            builder.AddMethod(new FrameDelegate(Frame));
+            builder.AddMethod(new CurrentExceptionDelegate(CurrentException));
+            builder.AddMethod(new NestedExceptionCountDelegate(NestedExceptionCount));
+            builder.AddMethod(new NestedExceptionDelegate(NestedException));
+            ICLRMACClrThread = builder.Complete();
+
+            AddRef();
+        }
+
+        protected override void Destroy()
+        {
+            Trace.TraceInformation("ThreadWrapper.Destroy");
+            _currentException?.ReleaseWithCheck();
+            _currentException = null;
+        }
+
+        private int DebuggerCommand(
+            IntPtr self,
+            out string command)
+        {
+            command = null;
+            return HResult.S_FALSE;
+        }
+
+        private int OSThreadId(
+            IntPtr self,
+            out uint osThreadId)
+        {
+            osThreadId = ThreadId;
+            return osThreadId > 0 ? HResult.S_OK : HResult.S_FALSE;
+        }
+
+        private int FrameCount(
+            IntPtr self,
+            out int count)
+        {
+            count = 0;
+            return HResult.E_NOTIMPL;
+        }
+
+        private int Frame(
+            IntPtr self,
+            int nFrame,
+            out ulong ip,
+            out ulong sp,
+            out string moduleName,
+            out string functionName,
+            out ulong displacement)
+        {
+            ip = 0;
+            sp = 0;
+            moduleName = null;
+            functionName = null;
+            displacement = 0;
+            return HResult.E_NOTIMPL;
+        }
+
+        private int CurrentException(
+            IntPtr self,
+            out IntPtr clrmaClrException)
+        {
+            clrmaClrException = IntPtr.Zero;
+            if (_currentException is null)
+            {
+                IException exception = null;
+                try
+                {
+                    exception = _crashInfoService.GetThreadException(ThreadId);
+                }
+                catch (ArgumentOutOfRangeException)
+                {
+                }
+                if (exception is null)
+                {
+                    return HResult.S_FALSE;
+                }
+                _currentException ??= new ExceptionWrapper(exception);
+            }
+            _currentException.AddRef();
+            clrmaClrException = _currentException.ICLRMACClrException;
+            return HResult.S_OK;
+        }
+
+        private int NestedExceptionCount(
+            IntPtr self,
+            out ushort count)
+        {
+            count = (ushort)NestedExceptions.Length;
+            return count > 0 ? HResult.S_OK : HResult.S_FALSE;
+        }
+
+        private int NestedException(
+            IntPtr self,
+            ushort index,
+            out IntPtr clrmaClrException)
+        {
+            clrmaClrException = IntPtr.Zero;
+            if (index >= NestedExceptions.Length)
+            {
+                return ManagedAnalysisWrapper.E_BOUNDS;
+            }
+            ExceptionWrapper exception = NestedExceptions[index];
+            exception.AddRef();
+            clrmaClrException = exception.ICLRMACClrException;
+            return HResult.S_OK;
+        }
+
+        private ExceptionWrapper[] NestedExceptions
+        {
+            get
+            {
+                if (_nestedExceptions is null)
+                {
+                    try
+                    {
+                        _nestedExceptions = _crashInfoService.GetNestedExceptions(ThreadId).Select((exception) => new ExceptionWrapper(exception)).ToArray();
+                    }
+                    catch (ArgumentOutOfRangeException)
+                    {
+                        _nestedExceptions = Array.Empty<ExceptionWrapper>();
+                    }
+                }
+                return _nestedExceptions;
+            }
+        }
+
+        #region ICLRMAClrThread delegates
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int DebuggerCommandDelegate(
+            [In] IntPtr self,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string command);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int OSThreadIdDelegate(
+            [In] IntPtr self,
+            [Out] out uint osThreadId);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int FrameCountDelegate(
+            [In] IntPtr self,
+            [Out] out int count);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int FrameDelegate(
+            [In] IntPtr self,
+            [In] int nFrame,
+            [Out] out ulong ip,
+            [Out] out ulong sp,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string moduleName,
+            [Out, MarshalAs(UnmanagedType.BStr)] out string functionName,
+            [Out] out ulong displacement);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int CurrentExceptionDelegate(
+            [In] IntPtr self,
+            [Out] out IntPtr clrmaClrException);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int NestedExceptionCountDelegate(
+            [In] IntPtr self,
+            [Out] out ushort count);
+
+        [UnmanagedFunctionPointer(CallingConvention.Winapi)]
+        private delegate int NestedExceptionDelegate(
+            [In] IntPtr self,
+            [In] ushort index,
+            [Out] out IntPtr clrmaClrException);
+
+        #endregion
+    }
+}
index b5702a7a8280b95d845b3c4825e238179721dbf7..9f4fe231f15cb1b1cce9801deacfe247389f7e24 100644 (file)
@@ -16,7 +16,7 @@ using SOS.Hosting.DbgEng.Interop;
 
 namespace SOS.Extensions
 {
-    internal sealed unsafe class DebuggerServices : CallableCOMWrapper, SOSHost.INativeClient
+    internal sealed unsafe class DebuggerServices : CallableCOMWrapper, SOSHost.INativeDebugger
     {
         internal enum OperatingSystem
         {
@@ -41,7 +41,6 @@ namespace SOS.Extensions
             : base(new RefCountedFreeLibrary(IntPtr.Zero), IID_IDebuggerServices, punk)
         {
             _hostType = hostType;
-            Client = punk;
 
             // This uses COM marshalling code, so we also check that the OSPlatform is Windows.
             if (hostType == HostType.DbgEng && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@@ -54,9 +53,20 @@ namespace SOS.Extensions
             }
         }
 
-        #region INativeClient
+        #region SOSHost.INativeDebugger
 
-        public IntPtr Client { get; }
+        public IntPtr GetNativeClient()
+        {
+            if (_hostType == HostType.DbgEng)
+            {
+                return QueryInterface(typeof(IDebugClient).GUID);
+            }
+            else if (_hostType == HostType.Lldb)
+            {
+                return QueryInterface(LLDBServices.IID_ILLDBServices);
+            }
+            throw new InvalidOperationException($"DebuggerServices.GetNativeClient: invalid host type {_hostType}");
+        }
 
         #endregion
 
index 9ee85d194225b4bb1d359bfebe64a95d73e6840e..c5c042ce555ebbd83472f0b502acffc35e572e71 100644 (file)
@@ -223,7 +223,7 @@ namespace SOS.Extensions
                 _serviceContainer.AddService<IServiceManager>(_serviceManager);
                 _serviceContainer.AddService<IHost>(this);
                 _serviceContainer.AddService<SOSLibrary.ISOSModule>(this);
-                _serviceContainer.AddService<SOSHost.INativeClient>(DebuggerServices);
+                _serviceContainer.AddService<SOSHost.INativeDebugger>(DebuggerServices);
                 _serviceContainer.AddService<ICommandService>(_commandService);
                 _serviceContainer.AddService<ISymbolService>(_symbolService);
                 _serviceContainer.AddService<IConsoleService>(fileLoggingConsoleService);
index 6e29077ef1a87660d7ab09f155cced4b7d512218..fd4a8648c42f374bf65cc0201567ec8dc7356d7f 100644 (file)
@@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
 using Microsoft.Diagnostics.DebugServices;
 using Microsoft.Diagnostics.DebugServices.Implementation;
 using Microsoft.Diagnostics.Runtime.Utilities;
+using SOS.Extensions.Clrma;
 using SOS.Hosting;
 using SOS.Hosting.DbgEng.Interop;
 using Architecture = System.Runtime.InteropServices.Architecture;
@@ -106,6 +107,9 @@ namespace SOS.Extensions
             }
 
             Finished();
+
+            TargetWrapper targetWrapper = Services.GetService<TargetWrapper>();
+            targetWrapper?.ServiceWrapper.AddServiceWrapper(ManagedAnalysisWrapper.IID_ICLRManagedAnalysis, () => new ManagedAnalysisWrapper(this, Services, targetWrapper.ServiceWrapper));
         }
 
         private unsafe ICrashInfoService CreateCrashInfoService(IServiceProvider services, DebuggerServices debuggerServices)
@@ -129,7 +133,7 @@ namespace SOS.Extensions
                     Span<byte> buffer = new byte[triageBufferSize];
                     if (services.GetService<IMemoryService>().ReadMemory(triageBufferAddress, buffer, out int bytesRead) && bytesRead == triageBufferSize)
                     {
-                        return CrashInfoService.Create(hresult, buffer);
+                        return CrashInfoService.Create(hresult, buffer, services.GetService<IModuleService>());
                     }
                     else
                     {
index 5ac39d92a0dc68003d2ac903f14f56752f91774a..1e6b127090caad212087ffc2cbbe62694ed25427 100644 (file)
@@ -13,10 +13,10 @@ using SOS.Hosting.DbgEng.Interop;
 
 namespace SOS.Hosting
 {
-    internal sealed unsafe class LLDBServices : COMCallableIUnknown
+    public sealed unsafe class LLDBServices : COMCallableIUnknown
     {
-        private static readonly Guid IID_ILLDBServices = new("2E6C569A-9E14-4DA4-9DFC-CDB73A532566");
-        private static readonly Guid IID_ILLDBServices2 = new("012F32F0-33BA-4E8E-BC01-037D382D8A5E");
+        public static readonly Guid IID_ILLDBServices = new("2E6C569A-9E14-4DA4-9DFC-CDB73A532566");
+        public static readonly Guid IID_ILLDBServices2 = new("012F32F0-33BA-4E8E-BC01-037D382D8A5E");
 
         public IntPtr ILLDBServices { get; }
 
index 3891c006390ff1004141821c8ef030e19c156bd6..5d23b98c3f6e5b61f1bff09e74758adca50c4010 100644 (file)
@@ -24,12 +24,12 @@ namespace SOS.Hosting
        /// <summary>
        /// Provides the native debugger's debug client instance
        /// </summary>
-       public interface INativeClient
+       public interface INativeDebugger
        {
-           /// <summary>
-           /// Native debugger client interface
-           /// </summary>
-           IntPtr Client { get; }
+            /// <summary>
+            /// Get the native SOS client for commands (IDebugClient under dbgeng, ILLDBServices under lldb)
+            /// </summary>
+            public IntPtr GetNativeClient();
        }
 
         // This is what dbgeng/IDebuggerServices returns for non-PE modules that don't have a timestamp
@@ -58,21 +58,20 @@ namespace SOS.Hosting
 
         private readonly IntPtr _client;
         private readonly ulong _ignoreAddressBitsMask;
-        private readonly bool _releaseClient;
 
         /// <summary>
         /// Create an instance of the hosting class. Has the lifetime of the target.
         /// </summary>
-        public SOSHost(ITarget target, IMemoryService memoryService, [ServiceImport(Optional = true)] INativeClient client)
+        public SOSHost(ITarget target, IMemoryService memoryService, [ServiceImport(Optional = true)] INativeDebugger nativeDebugger)
         {
             Target = target;
             MemoryService = memoryService;
             _ignoreAddressBitsMask = memoryService.SignExtensionMask();
 
             // If running under a native debugger, use the client instance supplied by the debugger for commands
-            if (client != null)
+            if (nativeDebugger != null)
             {
-                _client = client.Client;
+                _client = nativeDebugger.GetNativeClient();
             }
             else
             {
@@ -86,17 +85,14 @@ namespace SOS.Hosting
                     LLDBServices lldbServices = new(this);
                     _client = lldbServices.ILLDBServices;
                 }
-                _releaseClient = true;
             }
+            Debug.Assert(_client != IntPtr.Zero);
         }
 
         void IDisposable.Dispose()
         {
             Trace.TraceInformation($"SOSHost.Dispose");
-            if (_releaseClient)
-            {
-                ComWrapper.ReleaseWithCheck(_client);
-            }
+            ComWrapper.ReleaseWithCheck(_client);
         }
 
         /// <summary>
index 42e1f3e42562ba168457741cee80d2456c01aeec..c8d4fc70af44189bde3f9e91cf4fe562c2ad17c9 100644 (file)
@@ -17,7 +17,7 @@ namespace SOS.Hosting
     public sealed class SOSLibrary : IDisposable
     {
        /// <summary>
-       /// Provides the SOS module handle
+       /// Provides the SOS module path and handle
        /// </summary>
        public interface ISOSModule
        {
index 125fda0994ced5d6821ced4b55c77f6bc23fd824..78300591ea24bb4eb288b2b0cb21718f20bf3df7 100644 (file)
@@ -25,6 +25,7 @@ namespace SOS.Hosting
                 wrapper.ReleaseWithCheck();
             }
             _wrappers.Clear();
+            _factories.Clear();
         }
 
         /// <summary>
@@ -48,12 +49,11 @@ namespace SOS.Hosting
         }
 
         /// <summary>
-        /// Remove the service instance
+        /// Remove the service instance (doesn't release it) but not the factory.
         /// </summary>
         /// <param name="serviceId">guid</param>
         public void RemoveServiceWrapper(in Guid serviceId)
         {
-            _factories.Remove(serviceId);
             _wrappers.Remove(serviceId);
         }
 
index daf13d8519d87978842586f5137508a93f8dfa2e..8960df57c0abdba80605fba06af37f114d920c0a 100644 (file)
@@ -30,11 +30,12 @@ namespace SOS.Hosting
         private readonly ITarget _target;
         private readonly IContextService _contextService;
 
-        public TargetWrapper(ITarget target, IContextService contextService, ISymbolService symbolService, IMemoryService memoryService)
+        public TargetWrapper(
+            ITarget target,
+            IContextService contextService,
+            ISymbolService symbolService,
+            IMemoryService memoryService)
         {
-            Debug.Assert(target != null);
-            Debug.Assert(contextService != null);
-            Debug.Assert(symbolService != null);
             _target = target;
             _contextService = contextService;
 
@@ -62,7 +63,6 @@ namespace SOS.Hosting
         protected override void Destroy()
         {
             Trace.TraceInformation("TargetWrapper.Destroy");
-            ServiceWrapper.RemoveServiceWrapper(SymbolServiceWrapper.IID_ISymbolService);
             ServiceWrapper.Dispose();
         }
 
index 8b095e69ac6be7d4d5739bad276a9db584006892..19551ab0a8d3a5db3f04c5835df4bb8f7a1c2bad 100644 (file)
@@ -82,6 +82,7 @@ if (CLR_CMAKE_HOST_WIN32)
   add_definitions(-DUSE_STL)
 
   set(SOS_SOURCES
+    clrma.cpp
     disasm.cpp
     dllsext.cpp
     eeheap.cpp
index 29dde66bfac5eb547c37fa2b29e34b48454c45fe..609d90ec029c4d17a557ad547e47e7fd50b70b79 100644 (file)
     </ProjectReference>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="clrma.cpp" />
     <ClCompile Include="dbgengservices.cpp" />
     <ClCompile Include="disasm.cpp" />
     <ClCompile Include="dllsext.cpp" />
index e7b14e9eaff37ebe60d9c917c9bf87d9da315c7d..53a91f82dda68622498502658e3adeaa58acf2b6 100644 (file)
@@ -33,6 +33,7 @@
       <Filter>platform</Filter>
     </ClCompile>
     <ClCompile Include="managedcommands.cpp" />
+    <ClCompile Include="clrma.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="data.h" />
diff --git a/src/SOS/Strike/clrma.cpp b/src/SOS/Strike/clrma.cpp
new file mode 100644 (file)
index 0000000..7ffc2fe
--- /dev/null
@@ -0,0 +1,59 @@
+#include <windows.h>
+#include <unknwn.h>
+#include <clrma.h> // IDL
+#include "exts.h"
+
+HRESULT CLRMACreateInstance(ICLRManagedAnalysis** ppCLRMA);
+HRESULT CLRMAReleaseInstance();
+
+ICLRManagedAnalysis* g_managedAnalysis = nullptr;
+
+//
+// Exports
+//
+
+HRESULT CLRMACreateInstance(ICLRManagedAnalysis** ppCLRMA)
+{
+    HRESULT hr = E_UNEXPECTED;
+
+    if (ppCLRMA == nullptr)
+    {
+        return E_INVALIDARG;
+    }
+    *ppCLRMA = nullptr;
+
+    if (g_managedAnalysis == nullptr)
+    {
+        Extensions* extensions = Extensions::GetInstance();
+        if (extensions == nullptr || extensions->GetDebuggerServices() == nullptr)
+        {
+            return E_FAIL;
+        }
+        ITarget* target = extensions->GetTarget();
+        if (target == nullptr)
+        {
+            return E_FAIL;
+        }
+        hr = target->GetService(__uuidof(ICLRManagedAnalysis), (void**)&g_managedAnalysis);
+        if (FAILED(hr))
+        {
+            return hr;
+        }
+    }
+    else
+    {
+        g_managedAnalysis->AddRef();
+    }
+    *ppCLRMA = g_managedAnalysis;
+    return S_OK;
+}
+
+HRESULT CLRMAReleaseInstance()
+{
+    if (g_managedAnalysis != nullptr)
+    {
+        g_managedAnalysis->Release();
+        g_managedAnalysis = nullptr;
+    }
+    return S_OK;
+}
index f298a3f9fd1e11f8167360768d1bb45debb75468..7f594e187a21c2735b6f17bd4efcd405428dc542 100644 (file)
@@ -253,6 +253,9 @@ EXPORTS
     TraceToCode
     tracetocode=TraceToCode
 
+    CLRMACreateInstance
+    CLRMAReleaseInstance
+
     SOSInitializeByHost
     SOSUninitializeByHost
     InitializeHostServices
index ec384ea237a180da27aab5a885c9db5253cc93ae..9fa4c8d86e46ffe929e8d34ece43a41d4f841492 100644 (file)
@@ -4416,20 +4416,6 @@ void ExtErr(PCSTR Format, ...)
     va_end(Args);
 }
 
-/// <summary>
-/// Internal trace output for extensions library
-/// </summary>
-void TraceError(PCSTR format, ...)
-{
-    if (Output::g_bDbgOutput)
-    {
-        va_list args;
-        va_start(args, format);
-        OutputVaList(DEBUG_OUTPUT_ERROR, format, args);
-        va_end(args);
-    }
-}
-
 void ExtDbgOut(PCSTR Format, ...)
 {
     if (Output::g_bDbgOutput)
index 18660889326758f288da739b5a29c85d7f4ea291..a3f48bfcd577863454301b3a2e60f048658015fe 100644 (file)
@@ -234,3 +234,45 @@ bool GetAbsolutePath(const char* path, std::string& absolutePath)
     }
     return false;
 }
+
+/// <summary>
+/// Internal output helper function
+/// </summary>
+void InternalOutputVaList(
+    ULONG mask,
+    PCSTR format,
+    va_list args)
+{
+    char str[1024];
+    va_list argsCopy;
+    va_copy(argsCopy, args);
+
+    // Try and format our string into a fixed buffer first and see if it fits
+    size_t length = vsnprintf(str, sizeof(str), format, args);
+    if (length < sizeof(str))
+    {
+        Extensions::GetInstance()->GetDebuggerServices()->OutputString(mask, str);
+    }
+    else
+    {
+        // Our stack buffer wasn't big enough to contain the entire formatted string
+        char *str_ptr = (char*)::malloc(length + 1);
+        if (str_ptr != nullptr)
+        {
+            vsnprintf(str_ptr, length + 1, format, argsCopy);
+            Extensions::GetInstance()->GetDebuggerServices()->OutputString(mask, str_ptr);
+            ::free(str_ptr);
+        }
+    }
+}
+
+/// <summary>
+/// Internal trace output for extensions library
+/// </summary>
+void TraceError(PCSTR format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    InternalOutputVaList(DEBUG_OUTPUT_ERROR, format, args);
+    va_end(args);
+}
index 025d6a3f9ec07595a3cea332696ace6169f0e941..0ec62b486ce0c730bab2970ab0650bccb18c6c81 100644 (file)
@@ -640,7 +640,7 @@ static HRESULT InitializeNetCoreHost()
         char* exePath = minipal_getexepath();
         if (!exePath)
         {
-            TraceError("Could not get full path to current executable");
+            TraceError("Could not get full path to current executable\n");
             return E_FAIL;
         }
 
diff --git a/src/SOS/inc/clrma.h b/src/SOS/inc/clrma.h
new file mode 100644 (file)
index 0000000..34f6944
--- /dev/null
@@ -0,0 +1,735 @@
+
+
+/* this ALWAYS GENERATED file contains the definitions for the interfaces */
+
+
+ /* File created by MIDL compiler version 8.01.0628 */
+/* at Mon Jan 18 19:14:07 2038
+ */
+/* Compiler settings for C:\ssd\reliability.banganalyze\src\CLRMA\Interface\idl\CLRMA.idl:
+    Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 
+    protocol : dce , ms_ext, c_ext, robust
+    error checks: allocation ref bounds_check enum stub_data 
+    VC __declspec() decoration level: 
+         __declspec(uuid()), __declspec(selectany), __declspec(novtable)
+         DECLSPEC_UUID(), MIDL_INTERFACE()
+*/
+/* @@MIDL_FILE_HEADING(  ) */
+
+#pragma warning( disable: 4049 )  /* more than 64k source lines */
+
+
+/* verify that the <rpcndr.h> version is high enough to compile this file*/
+#ifndef __REQUIRED_RPCNDR_H_VERSION__
+#define __REQUIRED_RPCNDR_H_VERSION__ 475
+#endif
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#ifndef __RPCNDR_H_VERSION__
+#error this stub requires an updated version of <rpcndr.h>
+#endif /* __RPCNDR_H_VERSION__ */
+
+
+#ifndef __CLRMA_h__
+#define __CLRMA_h__
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+#pragma once
+#endif
+
+#ifndef DECLSPEC_XFGVIRT
+#if defined(_CONTROL_FLOW_GUARD_XFG)
+#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func))
+#else
+#define DECLSPEC_XFGVIRT(base, func)
+#endif
+#endif
+
+/* Forward Declarations */ 
+
+#ifndef __ICLRManagedAnalysis_FWD_DEFINED__
+#define __ICLRManagedAnalysis_FWD_DEFINED__
+typedef interface ICLRManagedAnalysis ICLRManagedAnalysis;
+
+#endif         /* __ICLRManagedAnalysis_FWD_DEFINED__ */
+
+
+#ifndef __ICLRMAClrThread_FWD_DEFINED__
+#define __ICLRMAClrThread_FWD_DEFINED__
+typedef interface ICLRMAClrThread ICLRMAClrThread;
+
+#endif         /* __ICLRMAClrThread_FWD_DEFINED__ */
+
+
+#ifndef __ICLRMAClrException_FWD_DEFINED__
+#define __ICLRMAClrException_FWD_DEFINED__
+typedef interface ICLRMAClrException ICLRMAClrException;
+
+#endif         /* __ICLRMAClrException_FWD_DEFINED__ */
+
+
+#ifndef __ICLRMAObjectInspection_FWD_DEFINED__
+#define __ICLRMAObjectInspection_FWD_DEFINED__
+typedef interface ICLRMAObjectInspection ICLRMAObjectInspection;
+
+#endif         /* __ICLRMAObjectInspection_FWD_DEFINED__ */
+
+
+/* header files for imported files */
+#include "unknwn.h"
+
+#ifdef __cplusplus
+extern "C"{
+#endif 
+
+
+
+#ifndef __CLRMA_LIBRARY_DEFINED__
+#define __CLRMA_LIBRARY_DEFINED__
+
+/* library CLRMA */
+/* [helpstring][version][uuid] */ 
+
+
+
+
+
+
+EXTERN_C const IID LIBID_CLRMA;
+
+#ifndef __ICLRManagedAnalysis_INTERFACE_DEFINED__
+#define __ICLRManagedAnalysis_INTERFACE_DEFINED__
+
+/* interface ICLRManagedAnalysis */
+/* [object][helpstring][uuid] */ 
+
+
+EXTERN_C const IID IID_ICLRManagedAnalysis;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("8CA73A16-C017-4c8f-AD51-B758727478CA")
+    ICLRManagedAnalysis : public IUnknown
+    {
+    public:
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_ProviderName( 
+            /* [retval][out] */ BSTR *bstrProvider) = 0;
+        
+        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE AssociateClient( 
+            /* [in] */ IUnknown *pUnknown) = 0;
+        
+        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetThread( 
+            /* [in] */ ULONG osThreadID,
+            /* [retval][out] */ ICLRMAClrThread **ppClrThread) = 0;
+        
+        virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetException( 
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ ICLRMAClrException **ppClrException) = 0;
+        
+        virtual /* [propget][helpstring] */ HRESULT STDMETHODCALLTYPE get_ObjectInspection( 
+            /* [retval][out] */ ICLRMAObjectInspection **ppObjectInspection) = 0;
+        
+    };
+    
+    
+#else  /* C style interface */
+
+    typedef struct ICLRManagedAnalysisVtbl
+    {
+        BEGIN_INTERFACE
+        
+        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICLRManagedAnalysis * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        DECLSPEC_XFGVIRT(IUnknown, AddRef)
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICLRManagedAnalysis * This);
+        
+        DECLSPEC_XFGVIRT(IUnknown, Release)
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICLRManagedAnalysis * This);
+        
+        DECLSPEC_XFGVIRT(ICLRManagedAnalysis, get_ProviderName)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_ProviderName )( 
+            ICLRManagedAnalysis * This,
+            /* [retval][out] */ BSTR *bstrProvider);
+        
+        DECLSPEC_XFGVIRT(ICLRManagedAnalysis, AssociateClient)
+        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *AssociateClient )( 
+            ICLRManagedAnalysis * This,
+            /* [in] */ IUnknown *pUnknown);
+        
+        DECLSPEC_XFGVIRT(ICLRManagedAnalysis, GetThread)
+        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetThread )( 
+            ICLRManagedAnalysis * This,
+            /* [in] */ ULONG osThreadID,
+            /* [retval][out] */ ICLRMAClrThread **ppClrThread);
+        
+        DECLSPEC_XFGVIRT(ICLRManagedAnalysis, GetException)
+        /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetException )( 
+            ICLRManagedAnalysis * This,
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ ICLRMAClrException **ppClrException);
+        
+        DECLSPEC_XFGVIRT(ICLRManagedAnalysis, get_ObjectInspection)
+        /* [propget][helpstring] */ HRESULT ( STDMETHODCALLTYPE *get_ObjectInspection )( 
+            ICLRManagedAnalysis * This,
+            /* [retval][out] */ ICLRMAObjectInspection **ppObjectInspection);
+        
+        END_INTERFACE
+    } ICLRManagedAnalysisVtbl;
+
+    interface ICLRManagedAnalysis
+    {
+        CONST_VTBL struct ICLRManagedAnalysisVtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICLRManagedAnalysis_QueryInterface(This,riid,ppvObject)        \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICLRManagedAnalysis_AddRef(This)       \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICLRManagedAnalysis_Release(This)      \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICLRManagedAnalysis_get_ProviderName(This,bstrProvider)        \
+    ( (This)->lpVtbl -> get_ProviderName(This,bstrProvider) ) 
+
+#define ICLRManagedAnalysis_AssociateClient(This,pUnknown)     \
+    ( (This)->lpVtbl -> AssociateClient(This,pUnknown) ) 
+
+#define ICLRManagedAnalysis_GetThread(This,osThreadID,ppClrThread)     \
+    ( (This)->lpVtbl -> GetThread(This,osThreadID,ppClrThread) ) 
+
+#define ICLRManagedAnalysis_GetException(This,addr,ppClrException)     \
+    ( (This)->lpVtbl -> GetException(This,addr,ppClrException) ) 
+
+#define ICLRManagedAnalysis_get_ObjectInspection(This,ppObjectInspection)      \
+    ( (This)->lpVtbl -> get_ObjectInspection(This,ppObjectInspection) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif         /* C style interface */
+
+
+
+
+#endif         /* __ICLRManagedAnalysis_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICLRMAClrThread_INTERFACE_DEFINED__
+#define __ICLRMAClrThread_INTERFACE_DEFINED__
+
+/* interface ICLRMAClrThread */
+/* [object][helpstring][uuid] */ 
+
+
+EXTERN_C const IID IID_ICLRMAClrThread;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("9849CFC9-0868-406e-9059-6B04E9ADBBB8")
+    ICLRMAClrThread : public IUnknown
+    {
+    public:
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DebuggerCommand( 
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_OSThreadId( 
+            /* [retval][out] */ ULONG *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_FrameCount( 
+            /* [retval][out] */ UINT *pCount) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE Frame( 
+            /* [in] */ UINT nFrame,
+            /* [out] */ ULONG64 *pAddrIP,
+            /* [out] */ ULONG64 *pAddrSP,
+            /* [out] */ BSTR *bstrModule,
+            /* [out] */ BSTR *bstrFunction,
+            /* [out] */ ULONG64 *pDisplacement) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_CurrentException( 
+            /* [retval][out] */ ICLRMAClrException **ppClrException) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_NestedExceptionCount( 
+            /* [retval][out] */ USHORT *pCount) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE NestedException( 
+            /* [in] */ USHORT nIndex,
+            /* [retval][out] */ ICLRMAClrException **ppClrException) = 0;
+        
+    };
+    
+    
+#else  /* C style interface */
+
+    typedef struct ICLRMAClrThreadVtbl
+    {
+        BEGIN_INTERFACE
+        
+        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICLRMAClrThread * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        DECLSPEC_XFGVIRT(IUnknown, AddRef)
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICLRMAClrThread * This);
+        
+        DECLSPEC_XFGVIRT(IUnknown, Release)
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICLRMAClrThread * This);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, get_DebuggerCommand)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DebuggerCommand )( 
+            ICLRMAClrThread * This,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, get_OSThreadId)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_OSThreadId )( 
+            ICLRMAClrThread * This,
+            /* [retval][out] */ ULONG *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, get_FrameCount)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_FrameCount )( 
+            ICLRMAClrThread * This,
+            /* [retval][out] */ UINT *pCount);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, Frame)
+        HRESULT ( STDMETHODCALLTYPE *Frame )( 
+            ICLRMAClrThread * This,
+            /* [in] */ UINT nFrame,
+            /* [out] */ ULONG64 *pAddrIP,
+            /* [out] */ ULONG64 *pAddrSP,
+            /* [out] */ BSTR *bstrModule,
+            /* [out] */ BSTR *bstrFunction,
+            /* [out] */ ULONG64 *pDisplacement);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, get_CurrentException)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_CurrentException )( 
+            ICLRMAClrThread * This,
+            /* [retval][out] */ ICLRMAClrException **ppClrException);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, get_NestedExceptionCount)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_NestedExceptionCount )( 
+            ICLRMAClrThread * This,
+            /* [retval][out] */ USHORT *pCount);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrThread, NestedException)
+        HRESULT ( STDMETHODCALLTYPE *NestedException )( 
+            ICLRMAClrThread * This,
+            /* [in] */ USHORT nIndex,
+            /* [retval][out] */ ICLRMAClrException **ppClrException);
+        
+        END_INTERFACE
+    } ICLRMAClrThreadVtbl;
+
+    interface ICLRMAClrThread
+    {
+        CONST_VTBL struct ICLRMAClrThreadVtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICLRMAClrThread_QueryInterface(This,riid,ppvObject)    \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICLRMAClrThread_AddRef(This)   \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICLRMAClrThread_Release(This)  \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICLRMAClrThread_get_DebuggerCommand(This,pValue)       \
+    ( (This)->lpVtbl -> get_DebuggerCommand(This,pValue) ) 
+
+#define ICLRMAClrThread_get_OSThreadId(This,pValue)    \
+    ( (This)->lpVtbl -> get_OSThreadId(This,pValue) ) 
+
+#define ICLRMAClrThread_get_FrameCount(This,pCount)    \
+    ( (This)->lpVtbl -> get_FrameCount(This,pCount) ) 
+
+#define ICLRMAClrThread_Frame(This,nFrame,pAddrIP,pAddrSP,bstrModule,bstrFunction,pDisplacement)       \
+    ( (This)->lpVtbl -> Frame(This,nFrame,pAddrIP,pAddrSP,bstrModule,bstrFunction,pDisplacement) ) 
+
+#define ICLRMAClrThread_get_CurrentException(This,ppClrException)      \
+    ( (This)->lpVtbl -> get_CurrentException(This,ppClrException) ) 
+
+#define ICLRMAClrThread_get_NestedExceptionCount(This,pCount)  \
+    ( (This)->lpVtbl -> get_NestedExceptionCount(This,pCount) ) 
+
+#define ICLRMAClrThread_NestedException(This,nIndex,ppClrException)    \
+    ( (This)->lpVtbl -> NestedException(This,nIndex,ppClrException) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif         /* C style interface */
+
+
+
+
+#endif         /* __ICLRMAClrThread_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICLRMAClrException_INTERFACE_DEFINED__
+#define __ICLRMAClrException_INTERFACE_DEFINED__
+
+/* interface ICLRMAClrException */
+/* [object][helpstring][uuid] */ 
+
+
+EXTERN_C const IID IID_ICLRMAClrException;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("7C165652-D539-472e-A6CF-F657FFF31751")
+    ICLRMAClrException : public IUnknown
+    {
+    public:
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_DebuggerCommand( 
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Address( 
+            /* [retval][out] */ ULONG64 *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_HResult( 
+            /* [retval][out] */ HRESULT *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Type( 
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Message( 
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_FrameCount( 
+            /* [retval][out] */ UINT *pCount) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE Frame( 
+            /* [in] */ UINT nFrame,
+            /* [out] */ ULONG64 *pAddrIP,
+            /* [out] */ ULONG64 *pAddrSP,
+            /* [out] */ BSTR *pModule,
+            /* [out] */ BSTR *pFunction,
+            /* [out] */ ULONG64 *pDisplacement) = 0;
+        
+        virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_InnerExceptionCount( 
+            /* [retval][out] */ USHORT *pCount) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE InnerException( 
+            /* [in] */ USHORT nIndex,
+            /* [retval][out] */ ICLRMAClrException **ppClrException) = 0;
+        
+    };
+    
+    
+#else  /* C style interface */
+
+    typedef struct ICLRMAClrExceptionVtbl
+    {
+        BEGIN_INTERFACE
+        
+        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICLRMAClrException * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        DECLSPEC_XFGVIRT(IUnknown, AddRef)
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICLRMAClrException * This);
+        
+        DECLSPEC_XFGVIRT(IUnknown, Release)
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICLRMAClrException * This);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_DebuggerCommand)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_DebuggerCommand )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_Address)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Address )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ ULONG64 *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_HResult)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_HResult )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ HRESULT *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_Type)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Type )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_Message)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_Message )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_FrameCount)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_FrameCount )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ UINT *pCount);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, Frame)
+        HRESULT ( STDMETHODCALLTYPE *Frame )( 
+            ICLRMAClrException * This,
+            /* [in] */ UINT nFrame,
+            /* [out] */ ULONG64 *pAddrIP,
+            /* [out] */ ULONG64 *pAddrSP,
+            /* [out] */ BSTR *pModule,
+            /* [out] */ BSTR *pFunction,
+            /* [out] */ ULONG64 *pDisplacement);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, get_InnerExceptionCount)
+        /* [propget] */ HRESULT ( STDMETHODCALLTYPE *get_InnerExceptionCount )( 
+            ICLRMAClrException * This,
+            /* [retval][out] */ USHORT *pCount);
+        
+        DECLSPEC_XFGVIRT(ICLRMAClrException, InnerException)
+        HRESULT ( STDMETHODCALLTYPE *InnerException )( 
+            ICLRMAClrException * This,
+            /* [in] */ USHORT nIndex,
+            /* [retval][out] */ ICLRMAClrException **ppClrException);
+        
+        END_INTERFACE
+    } ICLRMAClrExceptionVtbl;
+
+    interface ICLRMAClrException
+    {
+        CONST_VTBL struct ICLRMAClrExceptionVtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICLRMAClrException_QueryInterface(This,riid,ppvObject) \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICLRMAClrException_AddRef(This)        \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICLRMAClrException_Release(This)       \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICLRMAClrException_get_DebuggerCommand(This,pValue)    \
+    ( (This)->lpVtbl -> get_DebuggerCommand(This,pValue) ) 
+
+#define ICLRMAClrException_get_Address(This,pValue)    \
+    ( (This)->lpVtbl -> get_Address(This,pValue) ) 
+
+#define ICLRMAClrException_get_HResult(This,pValue)    \
+    ( (This)->lpVtbl -> get_HResult(This,pValue) ) 
+
+#define ICLRMAClrException_get_Type(This,pValue)       \
+    ( (This)->lpVtbl -> get_Type(This,pValue) ) 
+
+#define ICLRMAClrException_get_Message(This,pValue)    \
+    ( (This)->lpVtbl -> get_Message(This,pValue) ) 
+
+#define ICLRMAClrException_get_FrameCount(This,pCount) \
+    ( (This)->lpVtbl -> get_FrameCount(This,pCount) ) 
+
+#define ICLRMAClrException_Frame(This,nFrame,pAddrIP,pAddrSP,pModule,pFunction,pDisplacement)  \
+    ( (This)->lpVtbl -> Frame(This,nFrame,pAddrIP,pAddrSP,pModule,pFunction,pDisplacement) ) 
+
+#define ICLRMAClrException_get_InnerExceptionCount(This,pCount)        \
+    ( (This)->lpVtbl -> get_InnerExceptionCount(This,pCount) ) 
+
+#define ICLRMAClrException_InnerException(This,nIndex,ppClrException)  \
+    ( (This)->lpVtbl -> InnerException(This,nIndex,ppClrException) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif         /* C style interface */
+
+
+
+
+#endif         /* __ICLRMAClrException_INTERFACE_DEFINED__ */
+
+
+#ifndef __ICLRMAObjectInspection_INTERFACE_DEFINED__
+#define __ICLRMAObjectInspection_INTERFACE_DEFINED__
+
+/* interface ICLRMAObjectInspection */
+/* [object][helpstring][uuid] */ 
+
+
+EXTERN_C const IID IID_ICLRMAObjectInspection;
+
+#if defined(__cplusplus) && !defined(CINTERFACE)
+    
+    MIDL_INTERFACE("836259DB-7452-4b2b-95C4-4BC52CB9ABC7")
+    ICLRMAObjectInspection : public IUnknown
+    {
+    public:
+        virtual HRESULT STDMETHODCALLTYPE GetType( 
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE GetAddressFromCcwAddress( 
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ ULONG64 *pAddress) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE GetField_SystemString( 
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ BSTR *pValue) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE GetField_SystemUInt32( 
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ ULONG *pValue) = 0;
+        
+        virtual HRESULT STDMETHODCALLTYPE GetField_SystemInt32( 
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ LONG *pValue) = 0;
+        
+    };
+    
+    
+#else  /* C style interface */
+
+    typedef struct ICLRMAObjectInspectionVtbl
+    {
+        BEGIN_INTERFACE
+        
+        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
+        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ REFIID riid,
+            /* [annotation][iid_is][out] */ 
+            _COM_Outptr_  void **ppvObject);
+        
+        DECLSPEC_XFGVIRT(IUnknown, AddRef)
+        ULONG ( STDMETHODCALLTYPE *AddRef )( 
+            ICLRMAObjectInspection * This);
+        
+        DECLSPEC_XFGVIRT(IUnknown, Release)
+        ULONG ( STDMETHODCALLTYPE *Release )( 
+            ICLRMAObjectInspection * This);
+        
+        DECLSPEC_XFGVIRT(ICLRMAObjectInspection, GetType)
+        HRESULT ( STDMETHODCALLTYPE *GetType )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAObjectInspection, GetAddressFromCcwAddress)
+        HRESULT ( STDMETHODCALLTYPE *GetAddressFromCcwAddress )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ ULONG64 addr,
+            /* [retval][out] */ ULONG64 *pAddress);
+        
+        DECLSPEC_XFGVIRT(ICLRMAObjectInspection, GetField_SystemString)
+        HRESULT ( STDMETHODCALLTYPE *GetField_SystemString )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ BSTR *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAObjectInspection, GetField_SystemUInt32)
+        HRESULT ( STDMETHODCALLTYPE *GetField_SystemUInt32 )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ ULONG *pValue);
+        
+        DECLSPEC_XFGVIRT(ICLRMAObjectInspection, GetField_SystemInt32)
+        HRESULT ( STDMETHODCALLTYPE *GetField_SystemInt32 )( 
+            ICLRMAObjectInspection * This,
+            /* [in] */ ULONG64 addr,
+            /* [in] */ BSTR bstrField,
+            /* [retval][out] */ LONG *pValue);
+        
+        END_INTERFACE
+    } ICLRMAObjectInspectionVtbl;
+
+    interface ICLRMAObjectInspection
+    {
+        CONST_VTBL struct ICLRMAObjectInspectionVtbl *lpVtbl;
+    };
+
+    
+
+#ifdef COBJMACROS
+
+
+#define ICLRMAObjectInspection_QueryInterface(This,riid,ppvObject)     \
+    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) 
+
+#define ICLRMAObjectInspection_AddRef(This)    \
+    ( (This)->lpVtbl -> AddRef(This) ) 
+
+#define ICLRMAObjectInspection_Release(This)   \
+    ( (This)->lpVtbl -> Release(This) ) 
+
+
+#define ICLRMAObjectInspection_GetType(This,addr,pValue)       \
+    ( (This)->lpVtbl -> GetType(This,addr,pValue) ) 
+
+#define ICLRMAObjectInspection_GetAddressFromCcwAddress(This,addr,pAddress)    \
+    ( (This)->lpVtbl -> GetAddressFromCcwAddress(This,addr,pAddress) ) 
+
+#define ICLRMAObjectInspection_GetField_SystemString(This,addr,bstrField,pValue)       \
+    ( (This)->lpVtbl -> GetField_SystemString(This,addr,bstrField,pValue) ) 
+
+#define ICLRMAObjectInspection_GetField_SystemUInt32(This,addr,bstrField,pValue)       \
+    ( (This)->lpVtbl -> GetField_SystemUInt32(This,addr,bstrField,pValue) ) 
+
+#define ICLRMAObjectInspection_GetField_SystemInt32(This,addr,bstrField,pValue)        \
+    ( (This)->lpVtbl -> GetField_SystemInt32(This,addr,bstrField,pValue) ) 
+
+#endif /* COBJMACROS */
+
+
+#endif         /* C style interface */
+
+
+
+
+#endif         /* __ICLRMAObjectInspection_INTERFACE_DEFINED__ */
+
+#endif /* __CLRMA_LIBRARY_DEFINED__ */
+
+/* Additional Prototypes for ALL interfaces */
+
+/* end of Additional Prototypes */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/src/SOS/inc/clrma.idl b/src/SOS/inc/clrma.idl
new file mode 100644 (file)
index 0000000..bd88006
--- /dev/null
@@ -0,0 +1,103 @@
+//
+// CLRMA.idl
+//
+
+import "unknwn.idl";
+
+[
+    uuid(511BCC9D-5B25-4d15-8F00-4DDFB0C142D5),
+    version(3.0),
+    helpstring("CLR Managed Analysis")
+]
+library CLRMA
+{
+    //
+    // Forward declarations
+    //
+
+    interface ICLRManagedAnalysis;
+    interface ICLRMAClrThread;
+    interface ICLRMAClrException;
+    interface ICLRMAObjectInspection;
+
+    //
+    // Interface declarations
+    //
+
+    // ICLRManagedAnalysis
+    [
+        uuid(8CA73A16-C017-4c8f-AD51-B758727478CA),
+        helpstring("ICLRManagedAnalysis interface")
+    ]
+    interface ICLRManagedAnalysis : IUnknown
+    {
+        [propget] HRESULT ProviderName([out, retval] BSTR* bstrProvider);
+
+        [helpstring("Associate a debug engine (usually an IDebugClient) with the CLRMA Provider.")]
+        HRESULT AssociateClient([in] IUnknown* pUnknown);
+
+        [helpstring("-1 : Last Event Thread, 0 : Current Thread, NN : OS Thread ID (TID)")]
+        HRESULT GetThread([in] ULONG osThreadID, [out, retval] ICLRMAClrThread** ppClrThread);
+
+        [helpstring(" 0 : Current Thread's Current Exception\nNN : Exception Object Address")]
+        HRESULT GetException([in] ULONG64 addr, [out, retval] ICLRMAClrException** ppClrException);
+
+        [helpstring("Interface to Inspect Objects")]
+        [propget] HRESULT ObjectInspection([out, retval] ICLRMAObjectInspection** ppObjectInspection);
+    };
+
+    // ICLRMAClrThread
+    [
+        uuid(9849CFC9-0868-406e-9059-6B04E9ADBBB8),
+            helpstring("ICLRMAClrThread interface")
+    ]
+        interface ICLRMAClrThread : IUnknown
+    {
+        [propget] HRESULT DebuggerCommand([out, retval] BSTR* pValue);
+        [propget] HRESULT OSThreadId([out, retval] ULONG* pValue);
+
+        [propget] HRESULT FrameCount([out, retval] UINT* pCount);
+        HRESULT Frame([in] UINT nFrame, [out] ULONG64* pAddrIP, [out] ULONG64* pAddrSP, [out] BSTR* bstrModule, [out] BSTR* bstrFunction, [out] ULONG64* pDisplacement);
+
+        [propget] HRESULT CurrentException([out, retval] ICLRMAClrException** ppClrException);
+
+        [propget] HRESULT NestedExceptionCount([out, retval] USHORT* pCount);
+        HRESULT NestedException([in] USHORT nIndex, [out, retval] ICLRMAClrException** ppClrException);
+    };
+
+    // ICLRMAClrException
+    [
+        uuid(7C165652-D539-472e-A6CF-F657FFF31751),
+        helpstring("ICLRMAClrException interface")
+    ]
+    interface ICLRMAClrException : IUnknown
+    {
+        [propget] HRESULT DebuggerCommand([out, retval] BSTR* pValue);
+        [propget] HRESULT Address([out, retval] ULONG64* pValue);
+        [propget] HRESULT HResult([out, retval] HRESULT* pValue);
+        [propget] HRESULT Type([out, retval] BSTR* pValue);
+        [propget] HRESULT Message([out, retval] BSTR* pValue);
+
+        [propget] HRESULT FrameCount([out, retval] UINT* pCount);
+        HRESULT Frame([in] UINT nFrame, [out] ULONG64* pAddrIP, [out] ULONG64* pAddrSP, [out] BSTR* pModule, [out] BSTR* pFunction, [out] ULONG64* pDisplacement) ;
+
+        [propget] HRESULT InnerExceptionCount([out, retval] USHORT* pCount);
+        HRESULT InnerException([in] USHORT nIndex, [out, retval] ICLRMAClrException** ppClrException);
+    };
+
+    // ICLRMAObjectInspection
+    [
+        uuid(836259DB-7452-4b2b-95C4-4BC52CB9ABC7),
+        helpstring("ICLRMAObjectInspection interface")
+    ]
+    interface ICLRMAObjectInspection : IUnknown
+    {
+        HRESULT GetType([in] ULONG64 addr, [out, retval] BSTR* pValue);
+        HRESULT GetAddressFromCcwAddress([in] ULONG64 addr, [out, retval] ULONG64* pAddress);
+
+        HRESULT GetField_SystemString([in] ULONG64 addr, [in] BSTR bstrField, [out, retval] BSTR* pValue);
+        HRESULT GetField_SystemUInt32([in] ULONG64 addr, [in] BSTR bstrField, [out, retval] ULONG* pValue);
+        HRESULT GetField_SystemInt32([in] ULONG64 addr, [in] BSTR bstrField, [out, retval] LONG* pValue);
+    };
+
+}; // CLRMA Library
index 1ecc0957107ac5a0a4e92ed239fe60d4ad8db317..f340a069ad714d98f1b8e13d6d2d001c814994a9 100644 (file)
@@ -973,7 +973,7 @@ LLDBServices::GetNameByOffset(
             goto exit;
         }
 
-        address = module.ResolveFileAddress(offset);
+        address = target.ResolveLoadAddress(offset);
         if (!address.IsValid())
         {
             hr = E_INVALIDARG;
@@ -1445,16 +1445,7 @@ LLDBServices::GetModuleSize(
     /* const */ lldb::SBModule& module)
 {
     ULONG64 size = 0;
-#if defined(__APPLE__)
-    mach_header_64 header;
-    ULONG read;
-    HRESULT hr = ReadVirtual(baseAddress, &header, sizeof(mach_header_64), &read) == S_OK;
-    if (SUCCEEDED(hr))
-    {
-           // Since MachO segments are not contiguous the image size is just the headers/commands
-           size = sizeof(mach_header_64) + header.sizeofcmds;
-    }
-#else
+
     // Find the first section with an valid base address
     int numSections = module.GetNumSections();
     for (int si = 0; si < numSections; si++)
@@ -1462,10 +1453,15 @@ LLDBServices::GetModuleSize(
         lldb::SBSection section = module.GetSectionAtIndex(si);
         if (section.IsValid())
         {
+#if defined(__APPLE__)
+            if (strcmp(section.GetName(), "__LINKEDIT") == 0)
+            {
+                continue;
+            }
+ #endif
             size += section.GetByteSize();
         }
     }
-#endif
     // For core dumps lldb doesn't return the section sizes when it 
     // doesn't have access to the actual module file, but SOS (like 
     // the SymbolReader code) still needs a non-zero module size.
index 2c39d5034b8f8ff95644560e6d9f4e71749d95f8..f4ef26e1c9ea687e0314ce045b92e0dc4a66b5b7 100644 (file)
@@ -19,14 +19,3 @@ bool lldb::PluginInitialize(lldb::SBDebugger debugger)
     sethostruntimeCommandInitialize(debugger);
     return true;
 }
-
-/// <summary>
-/// Internal trace output for extensions library
-/// </summary>
-void TraceError(PCSTR format, ...)
-{
-    va_list args;
-    va_start(args, format);
-    g_services->InternalOutputVaList(DEBUG_OUTPUT_ERROR, format, args);
-    va_end(args);
-}