src/Microsoft.Diagnostics.Runtime/DacInterface/SOSDac13Old.cs (87 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.Runtime.CompilerServices; using System.Runtime.InteropServices; using Microsoft.Diagnostics.Runtime.Utilities; using static Microsoft.Diagnostics.Runtime.DacInterface.SOSDac; using static Microsoft.Diagnostics.Runtime.DacInterface.SOSDac13; namespace Microsoft.Diagnostics.Runtime.DacInterface { /// <summary> /// This is an undocumented, untested, and unsupported interface. Do not use directly. /// </summary> internal sealed unsafe class SOSDac13Old : CallableCOMWrapper, ISOSDac13 { internal static readonly Guid IID_ISOSDac13 = new("3176a8ed-597b-4f54-a71f-83695c6a8c5d"); public SOSDac13Old(DacLibrary library, IntPtr ptr) : base(library?.OwningLibrary, IID_ISOSDac13, ptr) { } private ref readonly ISOSDac13VTable VTable => ref Unsafe.AsRef<ISOSDac13VTable>(_vtable); public HResult TraverseLoaderHeap(ulong heap, LoaderHeapKind kind, LoaderHeapTraverse callback) { HResult hr = VTable.TraverseLoaderHeap(Self, heap, kind, Marshal.GetFunctionPointerForDelegate(callback)); GC.KeepAlive(callback); return hr; } public ClrDataAddress GetDomainLoaderAllocator(ClrDataAddress domainAddress) { if (domainAddress == 0) return 0; HResult hr = VTable.GetDomainLoaderAllocator(Self, domainAddress, out ClrDataAddress loaderAllocator); return hr ? loaderAllocator : 0; } public string[] GetLoaderAllocatorHeapNames() { HResult hr = VTable.GetLoaderAllocatorHeapNames(Self, 0, null, out int needed); if (hr && needed > 0) { nint[] pointers = new nint[needed]; fixed (nint* ptr = pointers) { if (hr = VTable.GetLoaderAllocatorHeapNames(Self, needed, ptr, out _)) { string[] result = new string[needed]; for (int i = 0; i < needed; i++) result[i] = Marshal.PtrToStringAnsi(pointers[i]) ?? ""; return result; } } } return Array.Empty<string>(); } public (ClrDataAddress Address, LoaderHeapKind Kind)[] GetLoaderAllocatorHeaps(ClrDataAddress loaderAllocator) { if (loaderAllocator != 0) { HResult hr = VTable.GetLoaderAllocatorHeaps(Self, loaderAllocator, 0, null, null, out int needed); if (hr && needed > 0) { ClrDataAddress[] addresses = new ClrDataAddress[needed]; LoaderHeapKind[] kinds = new LoaderHeapKind[needed]; fixed (ClrDataAddress* ptrAddresses = addresses) fixed (LoaderHeapKind* ptrKinds = kinds) { if (hr = VTable.GetLoaderAllocatorHeaps(Self, loaderAllocator, addresses.Length, ptrAddresses, ptrKinds, out _)) { (ClrDataAddress, LoaderHeapKind)[] result = new (ClrDataAddress, LoaderHeapKind)[needed]; for (int i = 0; i < needed; i++) result[i] = (addresses[i], kinds[i]); return result; } } } } return Array.Empty<(ClrDataAddress, LoaderHeapKind)>(); } SosMemoryEnum? ISOSDac13.GetGCBookkeepingMemoryRegions() => null; SosMemoryEnum? ISOSDac13.GetGCFreeRegions() => null; SosMemoryEnum? ISOSDac13.GetHandleTableRegions() => null; bool ISOSDac13.LockedFlush() => false; [StructLayout(LayoutKind.Sequential)] private readonly unsafe struct ISOSDac13VTable { public readonly delegate* unmanaged[Stdcall]<nint, ClrDataAddress, LoaderHeapKind, nint, int> TraverseLoaderHeap; public readonly delegate* unmanaged[Stdcall]<nint, ClrDataAddress, out ClrDataAddress, int> GetDomainLoaderAllocator; public readonly delegate* unmanaged[Stdcall]<nint, int, nint*, out int, int> GetLoaderAllocatorHeapNames; public readonly delegate* unmanaged[Stdcall]<nint, ClrDataAddress, int, ClrDataAddress*, LoaderHeapKind*, out int, int> GetLoaderAllocatorHeaps; } } }