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
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;
/// </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; }
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))]
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))]
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)
{
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)
{
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
{
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
{
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;
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
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
}
{
if (InitializeValue(Module.Flags.InitializeVersion))
{
- if (!_moduleInfo.Version.Equals(Utilities.EmptyVersion))
+ if (_moduleInfo.Version != null && !_moduleInfo.Version.Equals(Utilities.EmptyVersion))
{
_version = _moduleInfo.Version;
}
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
{
// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections.Generic;
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);
}
}
--- /dev/null
+// 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; }
+ }
+}
+++ /dev/null
-// 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; }
- }
-}
--- /dev/null
+// 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);
+ }
+}
/// <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);
}
}
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
// 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;
[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}");
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} ");
}
}
}
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
+ }
+}
--- /dev/null
+// 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
+ }
+}
namespace SOS.Extensions
{
- internal sealed unsafe class DebuggerServices : CallableCOMWrapper, SOSHost.INativeClient
+ internal sealed unsafe class DebuggerServices : CallableCOMWrapper, SOSHost.INativeDebugger
{
internal enum OperatingSystem
{
: 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))
}
}
- #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
_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);
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;
}
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)
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
{
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; }
/// <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
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
{
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>
public sealed class SOSLibrary : IDisposable
{
/// <summary>
- /// Provides the SOS module handle
+ /// Provides the SOS module path and handle
/// </summary>
public interface ISOSModule
{
wrapper.ReleaseWithCheck();
}
_wrappers.Clear();
+ _factories.Clear();
}
/// <summary>
}
/// <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);
}
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;
protected override void Destroy()
{
Trace.TraceInformation("TargetWrapper.Destroy");
- ServiceWrapper.RemoveServiceWrapper(SymbolServiceWrapper.IID_ISymbolService);
ServiceWrapper.Dispose();
}
add_definitions(-DUSE_STL)
set(SOS_SOURCES
+ clrma.cpp
disasm.cpp
dllsext.cpp
eeheap.cpp
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="clrma.cpp" />
<ClCompile Include="dbgengservices.cpp" />
<ClCompile Include="disasm.cpp" />
<ClCompile Include="dllsext.cpp" />
<Filter>platform</Filter>
</ClCompile>
<ClCompile Include="managedcommands.cpp" />
+ <ClCompile Include="clrma.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="data.h" />
--- /dev/null
+#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;
+}
TraceToCode
tracetocode=TraceToCode
+ CLRMACreateInstance
+ CLRMAReleaseInstance
+
SOSInitializeByHost
SOSUninitializeByHost
InitializeHostServices
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)
}
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);
+}
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;
}
--- /dev/null
+
+
+/* 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
+
+
--- /dev/null
+//
+// 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
goto exit;
}
- address = module.ResolveFileAddress(offset);
+ address = target.ResolveLoadAddress(offset);
if (!address.IsValid())
{
hr = E_INVALIDARG;
/* 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++)
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.
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);
-}