src/Microsoft.Diagnostics.Runtime/DacInterface/SosDac.cs (688 lines of code) (raw):
// 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.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Microsoft.Diagnostics.Runtime.Utilities;
namespace Microsoft.Diagnostics.Runtime.DacInterface
{
/// <summary>
/// This is an undocumented, untested, and unsupported interface. Do not use.
/// </summary>
internal sealed unsafe class SOSDac : CallableCOMWrapper
{
internal static readonly Guid IID_ISOSDac = new("436f00f2-b42a-4b9f-870c-e73db66ae930");
private readonly DacLibrary _library;
private volatile Dictionary<int, string>? _regNames;
private volatile Dictionary<ulong, string>? _frameNames;
public SOSDac(DacLibrary? library, IntPtr ptr)
: base(library?.OwningLibrary, IID_ISOSDac, ptr)
{
_library = library ?? throw new ArgumentNullException(nameof(library));
}
private ref readonly ISOSDacVTable VTable => ref Unsafe.AsRef<ISOSDacVTable>(_vtable);
public SOSDac(DacLibrary lib, CallableCOMWrapper toClone) : base(toClone)
{
_library = lib;
}
public RejitData[] GetRejitData(ulong md, ulong ip = 0)
{
HResult hr = VTable.GetMethodDescData(Self, md, ip, out _, 0, null, out int needed);
if (hr && needed >= 1)
{
RejitData[] result = new RejitData[needed];
hr = VTable.GetMethodDescData(Self, md, ip, out _, result.Length, result, out _);
if (hr)
return result;
}
return Array.Empty<RejitData>();
}
public HResult GetMethodDescData(ulong md, ulong ip, out MethodDescData data)
{
return VTable.GetMethodDescData(Self, md, ip, out data, 0, null, out _);
}
public HResult GetThreadStoreData(out ThreadStoreData data)
{
return VTable.GetThreadStoreData(Self, out data);
}
public string? GetRegisterName(int index)
{
Dictionary<int, string> regNames = _regNames ??= new();
lock (regNames)
if (regNames.TryGetValue(index, out string? cached))
return cached;
// Register names shouldn't be big.
Span<char> buffer = stackalloc char[32];
fixed (char* ptr = buffer)
{
HResult hr = VTable.GetRegisterName(Self, index, buffer.Length, ptr, out int needed);
if (!hr)
return null;
if (needed == 0)
return string.Empty;
int len = buffer.IndexOf((char)0);
if (len >= 0)
buffer = buffer.Slice(0, len);
string result = new(ptr, 0, buffer.Length);
lock (regNames)
regNames[index] = result;
return result;
}
}
public uint GetTlsIndex()
{
HResult hr = VTable.GetTLSIndex(Self, out uint index);
if (hr)
return index;
return uint.MaxValue;
}
public ClrDataAddress GetThreadFromThinlockId(uint id)
{
HResult hr = VTable.GetThreadFromThinlockID(Self, id, out ClrDataAddress thread);
if (hr)
return thread;
return default;
}
public string? GetMethodDescName(ulong md)
{
if (md == 0)
return null;
HResult hr = VTable.GetMethodDescName(Self, md, 0, null, out int needed);
if (!hr)
return null;
byte[] buffer = ArrayPool<byte>.Shared.Rent(needed * sizeof(char));
try
{
int actuallyNeeded;
fixed (byte* bufferPtr = buffer)
{
hr = VTable.GetMethodDescName(Self, md, needed, bufferPtr, out actuallyNeeded);
if (!hr)
return null;
}
// Patch for a bug on sos side :
// Sometimes, when the target method has parameters with generic types
// the first call to GetMethodDescName sets an incorrect value into pNeeded.
// In those cases, a second call directly after the first returns the correct value.
if (needed != actuallyNeeded)
{
ArrayPool<byte>.Shared.Return(buffer);
buffer = ArrayPool<byte>.Shared.Rent(actuallyNeeded * sizeof(char));
fixed (byte* bufferPtr = buffer)
{
hr = VTable.GetMethodDescName(Self, md, actuallyNeeded, bufferPtr, out actuallyNeeded);
if (!hr)
return null;
}
}
return Encoding.Unicode.GetString(buffer, 0, (actuallyNeeded - 1) * sizeof(char));
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
public ulong GetMethodTableSlot(ulong mt, uint slot)
{
if (mt == 0)
return 0;
HResult hr = VTable.GetMethodTableSlot(Self, mt, slot, out ClrDataAddress ip);
if (hr)
return ip;
return 0;
}
public HResult GetThreadLocalModuleData(ulong thread, uint index, out ThreadLocalModuleData data)
{
return VTable.GetThreadLocalModuleData(Self, thread, index, out data);
}
public ulong GetILForModule(ulong moduleAddr, uint rva)
{
HResult hr = VTable.GetILForModule(Self, moduleAddr, rva, out ClrDataAddress result);
if (hr)
return result;
return 0;
}
public COMInterfacePointerData[]? GetCCWInterfaces(ulong ccw, int count)
{
COMInterfacePointerData[] data = new COMInterfacePointerData[count];
fixed (COMInterfacePointerData* ptr = data)
{
HResult hr = VTable.GetCCWInterfaces(Self, ccw, count, ptr, out int pNeeded);
if (hr)
return data;
}
return null;
}
public COMInterfacePointerData[]? GetRCWInterfaces(ulong ccw, int count)
{
COMInterfacePointerData[] data = new COMInterfacePointerData[count];
fixed (COMInterfacePointerData* ptr = data)
{
HResult hr = VTable.GetRCWInterfaces(Self, ccw, count, ptr, out int pNeeded);
if (hr)
return data;
}
return null;
}
public HResult GetDomainLocalModuleDataFromModule(ulong module, out DomainLocalModuleData data)
{
return VTable.GetDomainLocalModuleDataFromModule(Self, module, out data);
}
public HResult GetDomainLocalModuleDataFromAppDomain(ulong appDomain, int id, out DomainLocalModuleData data)
{
return VTable.GetDomainLocalModuleDataFromAppDomain(Self, appDomain, id, out data);
}
public HResult GetWorkRequestData(ulong request, out WorkRequestData data)
{
return VTable.GetWorkRequestData(Self, request, out data);
}
public HResult GetThreadPoolData(out ThreadPoolData data)
{
return VTable.GetThreadpoolData(Self, out data);
}
public HResult GetSyncBlockData(int index, out SyncBlockData data)
{
return VTable.GetSyncBlockData(Self, index, out data);
}
public string? GetAppBase(ulong domain)
{
return GetString(VTable.GetApplicationBase, domain);
}
public string? GetConfigFile(ulong domain)
{
return GetString(VTable.GetAppDomainConfigFile, domain);
}
public HResult GetCodeHeaderData(ulong ip, out CodeHeaderData codeHeaderData)
{
if (ip == 0)
{
codeHeaderData = default;
return HResult.E_INVALIDARG;
}
return VTable.GetCodeHeaderData(Self, ip, out codeHeaderData);
}
public ClrDataAddress GetMethodDescPtrFromFrame(ulong frame)
{
HResult hr = VTable.GetMethodDescPtrFromFrame(Self, frame, out ClrDataAddress data);
if (hr)
return data;
return default;
}
public ClrDataAddress GetMethodDescPtrFromIP(ulong frame)
{
HResult hr = VTable.GetMethodDescPtrFromIP(Self, frame, out ClrDataAddress data);
if (hr)
return data;
return default;
}
public string GetFrameName(ulong vtable)
{
Dictionary<ulong, string> frameNames = _frameNames ??= new();
lock (frameNames)
{
if (_frameNames.TryGetValue(vtable, out string? cached))
return cached;
}
string? result = GetString(VTable.GetFrameName, vtable, false);
if (result is not null)
{
lock (frameNames)
_frameNames[vtable] = result;
return result;
}
// Don't cache failed lookups. We might have a bad stackwalk where we get 1000s of bad
// frame vtables and we won't want to eat up memory storing those in the cache.
return "Unknown Frame";
}
public HResult GetFieldInfo(ulong mt, out MethodTableFieldInfo data)
{
return VTable.GetMethodTableFieldData(Self, mt, out data);
}
public HResult GetFieldData(ulong fieldDesc, out FieldData data)
{
return VTable.GetFieldDescData(Self, fieldDesc, out data);
}
public HResult GetObjectData(ulong obj, out ObjectData data)
{
return VTable.GetObjectData(Self, obj, out data);
}
public HResult GetCCWData(ulong ccw, out CcwData data)
{
return VTable.GetCCWData(Self, ccw, out data);
}
public HResult GetRCWData(ulong rcw, out RcwData data)
{
return VTable.GetRCWData(Self, rcw, out data);
}
public IEnumerable<(ulong Rcw, ulong Context, ulong Thread, bool IsFreeThreaded)> EnumerateRCWCleanup(ulong cleanupList)
{
List<(ulong, ulong, ulong, bool)> result = new();
RcwCleanupTraverse traverse = (rcw, context, thread, freeThreaded, token) =>
{
result.Add((rcw, context, thread, freeThreaded != 0));
return result.Count > 16384 ? 0 : 1u;
};
VTable.TraverseRCWCleanupList(Self, cleanupList, Marshal.GetFunctionPointerForDelegate(traverse), 0);
GC.KeepAlive(traverse);
return result;
}
public HResult GetSyncBlockCleanupData(ulong syncBlockCleanupPointer, out SyncBlockCleanupData data)
{
return VTable.GetSyncBlockCleanupData(Self, syncBlockCleanupPointer, out data);
}
public delegate uint RcwCleanupTraverse(ClrDataAddress rcw, ClrDataAddress context, ClrDataAddress thread, uint isFreeThreaded, IntPtr token);
public ClrDataModule? GetClrDataModule(ulong module)
{
if (module == 0)
return null;
HResult hr = VTable.GetModule(Self, module, out IntPtr iunk);
if (hr)
return new ClrDataModule(_library, iunk);
return null;
}
public MetadataImport? GetMetadataImport(ulong module)
{
if (module == 0)
return null;
HResult hr = VTable.GetModule(Self, module, out IntPtr iunk);
if (!hr)
return null;
// Make sure we can successfully QueryInterface for IMetaDataImport. This may fail if
// we do not have all of the relevant metadata mapped into memory either through the dump
// or via the binary locator.
if (QueryInterface(iunk, MetadataImport.IID_IMetaDataImport, out IntPtr pTmp))
Release(pTmp);
else
return null;
try
{
return new MetadataImport(_library, iunk);
}
catch (InvalidCastException)
{
return null;
}
}
public HResult GetCommonMethodTables(out CommonMethodTables commonMTs)
{
return VTable.GetUsefulGlobals(Self, out commonMTs);
}
public ClrDataAddress[] GetAssemblyList(ulong appDomain) => GetAssemblyList(appDomain, 0);
public ClrDataAddress[] GetAssemblyList(ulong appDomain, int count) => GetModuleOrAssembly(appDomain, count, VTable.GetAssemblyList);
public ClrDataAddress[] GetModuleList(ulong assembly) => GetModuleList(assembly, 0);
public ClrDataAddress[] GetModuleList(ulong assembly, int count) => GetModuleOrAssembly(assembly, count, VTable.GetAssemblyModuleList);
public HResult GetAssemblyData(ulong domain, ulong assembly, out AssemblyData data)
{
// The dac seems to have an issue where the assembly data can be filled in for a minidump.
// If the data is partially filled in, we'll use it.
HResult hr = VTable.GetAssemblyData(Self, domain, assembly, out data);
if (!hr && data.Address == assembly)
return HResult.S_FALSE;
return hr;
}
public HResult GetAppDomainData(ulong addr, out AppDomainData data)
{
// We can face an exception while walking domain data if we catch the process
// at a bad state. As a workaround we will return partial data if data.Address
// and data.StubHeap are set.
HResult hr = VTable.GetAppDomainData(Self, addr, out data);
if (!hr && data.Address == addr && data.StubHeap != 0)
return HResult.S_FALSE;
return hr;
}
public string? GetAppDomainName(ulong appDomain)
{
return GetString(VTable.GetAppDomainName, appDomain);
}
public string? GetAssemblyName(ulong assembly)
{
return GetString(VTable.GetAssemblyName, assembly);
}
public HResult GetAppDomainStoreData(out AppDomainStoreData data)
{
return VTable.GetAppDomainStoreData(Self, out data);
}
public HResult GetMethodTableData(ulong addr, out MethodTableData data)
{
// If the 2nd bit is set it means addr is actually a TypeHandle (which GetMethodTable does not support).
if ((addr & 2) == 2)
{
data = default;
return HResult.E_INVALIDARG;
}
return VTable.GetMethodTableData(Self, addr, out data);
}
public string? GetMethodTableName(ulong mt)
{
return GetString(VTable.GetMethodTableName, mt);
}
public string? GetJitHelperFunctionName(ulong addr)
{
return GetAsciiString(VTable.GetJitHelperFunctionName, addr);
}
public string? GetPEFileName(ulong pefile)
{
return GetString(VTable.GetPEFileName, pefile);
}
private string? GetString(delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> func, ulong addr, bool skipNull = true)
{
HResult hr = func(Self, addr, 0, null, out int needed);
if (!hr)
return null;
if (needed == 0)
return string.Empty;
byte[]? array = null;
int size = needed * sizeof(char);
Span<byte> buffer = size <= 32 ? stackalloc byte[size] : (array = ArrayPool<byte>.Shared.Rent(size)).AsSpan(0, size);
try
{
fixed (byte* bufferPtr = buffer)
hr = func(Self, addr, needed, bufferPtr, out needed);
if (!hr)
return null;
if (skipNull)
needed--;
return Encoding.Unicode.GetString(buffer.Slice(0, needed * sizeof(char)));
}
finally
{
if (array != null)
ArrayPool<byte>.Shared.Return(array);
}
}
private string? GetAsciiString(delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> func, ulong addr)
{
HResult hr = func(Self, addr, 0, null, out int needed);
if (!hr)
return null;
if (needed == 0)
return string.Empty;
byte[]? array = null;
Span<byte> buffer = needed <= 32 ? stackalloc byte[needed] : (array = ArrayPool<byte>.Shared.Rent(needed)).AsSpan(0, needed);
try
{
fixed (byte* bufferPtr = buffer)
hr = func(Self, addr, needed, bufferPtr, out needed);
if (!hr)
return null;
int len = buffer.IndexOf((byte)'\0');
if (len >= 0)
needed = len;
return Encoding.ASCII.GetString(buffer.Slice(0, needed));
}
finally
{
if (array != null)
ArrayPool<byte>.Shared.Return(array);
}
}
public ClrDataAddress GetMethodTableByEEClass(ulong eeclass)
{
HResult hr = VTable.GetMethodTableForEEClass(Self, eeclass, out ClrDataAddress data);
if (hr)
return data;
return default;
}
public HResult GetModuleData(ulong module, out ModuleData data)
{
return VTable.GetModuleData(Self, module, out data);
}
private ClrDataAddress[] GetModuleOrAssembly(ulong address, int count, delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, ClrDataAddress*, out int, int> func)
{
int needed;
if (count <= 0)
{
if (func(Self, address, 0, null, out needed) < 0)
return Array.Empty<ClrDataAddress>();
count = needed;
}
// We ignore the return value here since the list may be partially filled
ClrDataAddress[] modules = new ClrDataAddress[count];
fixed (ClrDataAddress* ptr = modules)
func(Self, address, modules.Length, ptr, out needed);
return modules;
}
public ClrDataAddress[] GetAppDomainList(int count = 0)
{
if (count <= 0)
{
if (!GetAppDomainStoreData(out AppDomainStoreData addata))
return Array.Empty<ClrDataAddress>();
count = addata.AppDomainCount;
}
ClrDataAddress[] data = new ClrDataAddress[count];
fixed (ClrDataAddress* ptr = data)
{
HResult hr = VTable.GetAppDomainList(Self, data.Length, ptr, out int needed);
return hr ? data : Array.Empty<ClrDataAddress>();
}
}
public HResult GetThreadData(ulong address, out ThreadData data)
{
if (address == 0)
{
data = default;
return HResult.E_INVALIDARG;
}
return VTable.GetThreadData(Self, address, out data);
}
public HResult GetGCHeapData(out GCInfo data)
{
return VTable.GetGCHeapData(Self, out data);
}
public HResult GetOOMData(out DacOOMData oomData) => VTable.GetOOMStaticData(Self, out oomData);
public HResult GetOOMData(ulong address, out DacOOMData oomData) => VTable.GetOOMData(Self, address, out oomData);
public HResult GetHeapAnalyzeData(out DacHeapAnalyzeData analyzeData) => VTable.GetHeapAnalyzeStaticData(Self, out analyzeData);
public HResult GetHeapAnalyzeData(ulong address, out DacHeapAnalyzeData analyzeData) => VTable.GetHeapAnalyzeData(Self, address, out analyzeData);
public HResult GetSegmentData(ulong addr, out SegmentData data)
{
return VTable.GetHeapSegmentData(Self, addr, out data);
}
public ClrDataAddress[] GetHeapList(int heapCount)
{
ClrDataAddress[] refs = new ClrDataAddress[heapCount];
fixed (ClrDataAddress* ptr = refs)
{
HResult hr = VTable.GetGCHeapList(Self, heapCount, ptr, out int needed);
return hr ? refs : Array.Empty<ClrDataAddress>();
}
}
public HResult GetServerHeapDetails(ulong addr, out HeapDetails data)
{
return VTable.GetGCHeapDetails(Self, addr, out data);
}
public HResult GetWksHeapDetails(out HeapDetails data)
{
return VTable.GetGCHeapStaticData(Self, out data);
}
public JitManagerData[] GetJitManagers()
{
HResult hr = VTable.GetJitManagerList(Self, 0, null, out int needed);
if (!hr || needed == 0)
return Array.Empty<JitManagerData>();
JitManagerData[] result = new JitManagerData[needed];
fixed (JitManagerData* ptr = result)
{
hr = VTable.GetJitManagerList(Self, result.Length, ptr, out needed);
return hr ? result : Array.Empty<JitManagerData>();
}
}
public JitCodeHeapInfo[] GetCodeHeapList(ulong jitManager)
{
HResult hr = VTable.GetCodeHeapList(Self, jitManager, 0, null, out int needed);
if (!hr || needed == 0)
return Array.Empty<JitCodeHeapInfo>();
JitCodeHeapInfo[] result = new JitCodeHeapInfo[needed];
fixed (JitCodeHeapInfo* ptr = result)
{
hr = VTable.GetCodeHeapList(Self, jitManager, result.Length, ptr, out needed);
return hr ? result : Array.Empty<JitCodeHeapInfo>();
}
}
public enum ModuleMapTraverseKind
{
TypeDefToMethodTable,
TypeRefToMethodTable
}
public delegate void ModuleMapTraverse(int index, ulong methodTable, IntPtr token);
public HResult TraverseModuleMap(ModuleMapTraverseKind mt, ulong module, ModuleMapTraverse traverse)
{
HResult hr = VTable.TraverseModuleMap(Self, mt, module, Marshal.GetFunctionPointerForDelegate(traverse), IntPtr.Zero);
GC.KeepAlive(traverse);
return hr;
}
public delegate void LoaderHeapTraverse(ulong address, IntPtr size, int isCurrent);
public HResult TraverseLoaderHeap(ulong heap, LoaderHeapTraverse callback)
{
HResult hr = VTable.TraverseLoaderHeap(Self, heap, Marshal.GetFunctionPointerForDelegate(callback));
GC.KeepAlive(callback);
return hr;
}
public enum VCSHeapType
{
IndcellHeap,
LookupHeap,
ResolveHeap,
DispatchHeap,
CacheEntryHeap,
VtableHeap
}
public HResult TraverseStubHeap(ulong heap, VCSHeapType type, LoaderHeapTraverse callback)
{
HResult hr = VTable.TraverseVirtCallStubHeap(Self, heap, type, Marshal.GetFunctionPointerForDelegate(callback));
GC.KeepAlive(callback);
return hr;
}
public SOSHandleEnum? EnumerateHandles(params ClrHandleKind[] types)
{
fixed (ClrHandleKind* ptr = types)
{
HResult hr = VTable.GetHandleEnumForTypes(Self, ptr, types.Length, out IntPtr ptrEnum);
if (hr)
{
SOSHandleEnum result = new(_library, ptrEnum);
int count = result.Release();
if (count == 0)
throw new InvalidOperationException($"We expected to borrow a reference from GetHandleEnumForTypes, but instead fully released the object!");
return result;
}
}
return null;
}
public SOSHandleEnum? EnumerateHandles()
{
HResult hr = VTable.GetHandleEnum(Self, out IntPtr ptrEnum);
if (hr)
{
SOSHandleEnum result = new(_library, ptrEnum);
int count = result.Release();
if (count == 0)
throw new InvalidOperationException($"We expected to borrow a reference from GetHandleEnum, but instead fully released the object!");
return result;
}
return null;
}
public SOSStackRefEnum? EnumerateStackRefs(uint osThreadId)
{
HResult hr = VTable.GetStackReferences(Self, osThreadId, out IntPtr ptrEnum);
if (hr)
{
SOSStackRefEnum result = new(_library, ptrEnum);
int count = result.Release();
if (count == 0)
throw new InvalidOperationException($"We expected to borrow a reference from GetStackReferences, but instead fully released the object!");
return result;
}
else
{
Trace.TraceInformation($"EnumerateStackRefs for OSThreadId:{osThreadId:x} failed with hr={hr}");
}
return null;
}
public ulong GetMethodDescFromToken(ulong module, int token)
{
HResult hr = VTable.GetMethodDescFromToken(Self, module, token, out ClrDataAddress md);
if (hr)
return md;
return 0;
}
private delegate HResult DacGetJitManagerInfo(IntPtr self, ClrDataAddress addr, out JitManagerData data);
}
[StructLayout(LayoutKind.Sequential)]
internal readonly unsafe struct ISOSDacVTable
{
// ThreadStore
public readonly delegate* unmanaged[Stdcall]<IntPtr, out ThreadStoreData, int> GetThreadStoreData;
// AppDomains
public readonly delegate* unmanaged[Stdcall]<IntPtr, out AppDomainStoreData, int> GetAppDomainStoreData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, int, ClrDataAddress*, out int, int> GetAppDomainList;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out AppDomainData, int> GetAppDomainData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetAppDomainName;
public readonly IntPtr GetDomainFromContext;
// Assemblies
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, ClrDataAddress*, out int, int> GetAssemblyList;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, ClrDataAddress, out AssemblyData, int> GetAssemblyData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetAssemblyName;
// Modules
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out IntPtr, int> GetModule;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ModuleData, int> GetModuleData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, SOSDac.ModuleMapTraverseKind, ClrDataAddress, IntPtr, IntPtr, int> TraverseModuleMap;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, ClrDataAddress*, out int, int> GetAssemblyModuleList;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, uint, out ClrDataAddress, int> GetILForModule;
// Threads
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ThreadData, int> GetThreadData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, uint, out ClrDataAddress, int> GetThreadFromThinlockID;
public readonly IntPtr GetStackLimits;
// MethodDescs
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, ulong, out MethodDescData, int, RejitData[]?, out int, int> GetMethodDescData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ClrDataAddress, int> GetMethodDescPtrFromIP;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetMethodDescName;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ClrDataAddress, int> GetMethodDescPtrFromFrame;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, out ClrDataAddress, int> GetMethodDescFromToken;
private readonly IntPtr GetMethodDescTransparencyData;
// JIT Data
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out CodeHeaderData, int> GetCodeHeaderData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, int, JitManagerData*, out int, int> GetJitManagerList;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetJitHelperFunctionName;
private readonly IntPtr GetJumpThunkTarget;
// ThreadPool
public readonly delegate* unmanaged[Stdcall]<IntPtr, out ThreadPoolData, int> GetThreadpoolData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out WorkRequestData, int> GetWorkRequestData;
private readonly IntPtr GetHillClimbingLogEntry;
// Objects
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ObjectData, int> GetObjectData;
public readonly IntPtr GetObjectStringData;
public readonly IntPtr GetObjectClassName;
// MethodTable
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetMethodTableName;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out MethodTableData, int> GetMethodTableData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, uint, out ClrDataAddress, int> GetMethodTableSlot;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out MethodTableFieldInfo, int> GetMethodTableFieldData;
private readonly IntPtr GetMethodTableTransparencyData;
// EEClass
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out ClrDataAddress, int> GetMethodTableForEEClass;
// FieldDesc
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out FieldData, int> GetFieldDescData;
// Frames
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetFrameName;
// PEFiles
public readonly IntPtr GetPEFileBase;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetPEFileName;
// GC
public readonly delegate* unmanaged[Stdcall]<IntPtr, out GCInfo, int> GetGCHeapData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, int, ClrDataAddress*, out int, int> GetGCHeapList; // svr only
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out HeapDetails, int> GetGCHeapDetails; // wks only
public readonly delegate* unmanaged[Stdcall]<IntPtr, out HeapDetails, int> GetGCHeapStaticData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out SegmentData, int> GetHeapSegmentData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out DacOOMData, int> GetOOMData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, out DacOOMData, int> GetOOMStaticData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out DacHeapAnalyzeData, int> GetHeapAnalyzeData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, out DacHeapAnalyzeData, int> GetHeapAnalyzeStaticData;
// DomainLocal
private readonly IntPtr GetDomainLocalModuleData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, out DomainLocalModuleData, int> GetDomainLocalModuleDataFromAppDomain;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out DomainLocalModuleData, int> GetDomainLocalModuleDataFromModule;
// ThreadLocal
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, uint, out ThreadLocalModuleData, int> GetThreadLocalModuleData;
// SyncBlock
public readonly delegate* unmanaged[Stdcall]<IntPtr, int, out SyncBlockData, int> GetSyncBlockData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ulong, out SyncBlockCleanupData, int> GetSyncBlockCleanupData;
// Handles
public readonly delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int> GetHandleEnum;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrHandleKind*, int, out IntPtr, int> GetHandleEnumForTypes;
private readonly IntPtr GetHandleEnumForGC;
// EH
private readonly IntPtr TraverseEHInfo;
private readonly IntPtr GetNestedExceptionData;
// StressLog
public readonly IntPtr GetStressLogAddress;
// Heaps
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, IntPtr, int> TraverseLoaderHeap;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, JitCodeHeapInfo*, out int, int> GetCodeHeapList;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, SOSDac.VCSHeapType, IntPtr, int> TraverseVirtCallStubHeap;
// Other
public readonly delegate* unmanaged[Stdcall]<IntPtr, out CommonMethodTables, int> GetUsefulGlobals;
public readonly IntPtr GetClrWatsonBuckets;
public readonly delegate* unmanaged[Stdcall]<IntPtr, out uint, int> GetTLSIndex;
public readonly IntPtr GetDacModuleHandle;
// COM
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out RcwData, int> GetRCWData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, COMInterfacePointerData*, out int, int> GetRCWInterfaces;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, out CcwData, int> GetCCWData;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, COMInterfacePointerData*, out int, int> GetCCWInterfaces;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, nint, nint, int> TraverseRCWCleanupList;
// GC Reference Functions
public readonly delegate* unmanaged[Stdcall]<IntPtr, uint, out IntPtr, int> GetStackReferences;
public readonly delegate* unmanaged[Stdcall]<IntPtr, int, int, char*, out int, int> GetRegisterName;
public readonly IntPtr GetThreadAllocData;
public readonly IntPtr GetHeapAllocData;
// For BindingDisplay plugin
public readonly IntPtr GetFailedAssemblyList;
public readonly IntPtr GetPrivateBinPaths;
public readonly IntPtr GetAssemblyLocation;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetAppDomainConfigFile;
public readonly delegate* unmanaged[Stdcall]<IntPtr, ClrDataAddress, int, byte*, out int, int> GetApplicationBase;
public readonly IntPtr GetFailedAssemblyData;
public readonly IntPtr GetFailedAssemblyLocation;
public readonly IntPtr GetFailedAssemblyDisplayName;
}
}