<commit_before>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Diagnostics.Runtime.Utilities;

namespace Microsoft.Diagnostics.Runtime.DacInterface
{
    /// <summary>
    /// This is an undocumented, untested, and unsupported interface.  Do not use.
    /// </summary>
    public sealed unsafe class SOSDac : CallableCOMWrapper
    {
        internal static readonly Guid IID_ISOSDac = new Guid("436f00f2-b42a-4b9f-870c-e73db66ae930");

        private readonly DacLibrary _library;

        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;
        }

        private DacGetIntPtr? _getHandleEnum;
        private GetHandleEnumForTypesDelegate? _getHandleEnumForTypes;
        private DacGetIntPtrWithArg? _getStackRefEnum;
        private DacGetThreadData? _getThreadData;
        private DacGetHeapDetailsWithArg? _getGCHeapDetails;
        private DacGetHeapDetails? _getGCHeapStaticData;
        private DacGetAddrArray? _getGCHeapList;
        private DacGetAddrArray? _getAppDomainList;
        private DacGetAddrArrayWithArg? _getAssemblyList;
        private DacGetAddrArrayWithArg? _getModuleList;
        private DacGetAssemblyData? _getAssemblyData;
        private DacGetADStoreData? _getAppDomainStoreData;
        private DacGetMTData? _getMethodTableData;
        private DacGetAddrWithArg? _getMTForEEClass;
        private DacGetGCInfoData? _getGCHeapData;
        private DacGetCommonMethodTables? _getCommonMethodTables;
        private DacGetCharArrayWithArg? _getMethodTableName;
        private DacGetByteArrayWithArg? _getJitHelperFunctionName;
        private DacGetCharArrayWithArg? _getPEFileName;
        private DacGetCharArrayWithArg? _getAppDomainName;
        private DacGetCharArrayWithArg? _getAssemblyName;
        private DacGetCharArrayWithArg? _getAppBase;
        private DacGetCharArrayWithArg? _getConfigFile;
        private DacGetModuleData? _getModuleData;
        private DacGetSegmentData? _getSegmentData;
        private DacGetAppDomainData? _getAppDomainData;
        private DacGetJitManagers? _getJitManagers;
        private DacTraverseLoaderHeap? _traverseLoaderHeap;
        private DacTraverseStubHeap? _traverseStubHeap;
        private DacTraverseModuleMap? _traverseModuleMap;
        private DacGetFieldInfo? _getFieldInfo;
        private DacGetFieldData? _getFieldData;
        private DacGetObjectData? _getObjectData;
        private DacGetCCWData? _getCCWData;
        private DacGetRCWData? _getRCWData;
        private DacGetCharArrayWithArg? _getFrameName;
        private DacGetAddrWithArg? _getMethodDescPtrFromFrame;
        private DacGetAddrWithArg? _getMethodDescPtrFromIP;
        private DacGetCodeHeaderData? _getCodeHeaderData;
        private DacGetSyncBlockData? _getSyncBlock;
        private DacGetThreadPoolData? _getThreadPoolData;
        private DacGetWorkRequestData? _getWorkRequestData;
        private DacGetDomainLocalModuleDataFromAppDomain? _getDomainLocalModuleDataFromAppDomain;
        private DacGetLocalModuleData? _getDomainLocalModuleDataFromModule;
        private DacGetCodeHeaps? _getCodeHeaps;
        private DacGetCOMPointers? _getCCWInterfaces;
        private DacGetCOMPointers? _getRCWInterfaces;
        private DacGetAddrWithArgs? _getILForModule;
        private DacGetThreadLocalModuleData? _getThreadLocalModuleData;
        private DacGetAddrWithArgs? _getMethodTableSlot;
        private DacGetCharArrayWithArg? _getMethodDescName;
        private DacGetThreadFromThinLock? _getThreadFromThinlockId;
        private DacGetUInt? _getTlsIndex;
        private DacGetThreadStoreData? _getThreadStoreData;
        private GetMethodDescDataDelegate? _getMethodDescData;
        private GetModuleDelegate? _getModule;
        private GetMethodDescFromTokenDelegate? _getMethodDescFromToken;

        public RejitData[] GetRejitData(ulong md, ulong ip = 0)
        {
            InitDelegate(ref _getMethodDescData, VTable.GetMethodDescData);
            int hr = _getMethodDescData(Self, md, ip, out MethodDescData data, 0, null, out int needed);

            if (SUCCEEDED(hr) && needed > 1)
            {
                RejitData[] result = new RejitData[needed];
                hr = _getMethodDescData(Self, md, ip, out data, result.Length, result, out needed);
                if (SUCCEEDED(hr))
                    return result;
            }

            return Array.Empty<RejitData>();
        }

        public bool GetMethodDescData(ulong md, ulong ip, out MethodDescData data)
        {
            InitDelegate(ref _getMethodDescData, VTable.GetMethodDescData);
            int hr = _getMethodDescData(Self, md, ip, out data, 0, null, out int needed);
            return SUCCEEDED(hr);
        }

        public bool GetThreadStoreData(out ThreadStoreData data)
        {
            InitDelegate(ref _getThreadStoreData, VTable.GetThreadStoreData);
            return _getThreadStoreData(Self, out data) == S_OK;
        }

        public uint GetTlsIndex()
        {
            InitDelegate(ref _getTlsIndex, VTable.GetTLSIndex);
            if (_getTlsIndex(Self, out uint index) == S_OK)
                return index;

            return uint.MaxValue;
        }

        public ClrDataAddress GetThreadFromThinlockId(uint id)
        {
            InitDelegate(ref _getThreadFromThinlockId, VTable.GetThreadFromThinlockID);
            if (_getThreadFromThinlockId(Self, id, out ClrDataAddress thread) == S_OK)
                return thread;

            return default;
        }

        public string? GetMethodDescName(ulong md)
        {
            if (md == 0)
                return null;

            InitDelegate(ref _getMethodDescName, VTable.GetMethodDescName);

            if (_getMethodDescName(Self, md, 0, null, out int needed) < S_OK)
                return null;

            byte[] buffer = ArrayPool<byte>.Shared.Rent(needed * sizeof(char));
            try
            {
                int actuallyNeeded;
                fixed (byte* bufferPtr = buffer)
                    if (_getMethodDescName(Self, md, needed, bufferPtr, out actuallyNeeded) < S_OK)
                        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)
                        if (_getMethodDescName(Self, md, actuallyNeeded, bufferPtr, out actuallyNeeded) < S_OK)
                            return null;
                }

                return Encoding.Unicode.GetString(buffer, 0, (actuallyNeeded - 1) * sizeof(char));
            }
            finally
            {
                ArrayPool<byte>.Shared.Return(buffer);
            }
        }

        public ulong GetMethodTableSlot(ulong mt, int slot)
        {
            if (mt == 0)
                return 0;

            InitDelegate(ref _getMethodTableSlot, VTable.GetMethodTableSlot);

            if (_getMethodTableSlot(Self, mt, (uint)slot, out ClrDataAddress ip) == S_OK)
                return ip;

            return 0;
        }

        public bool GetThreadLocalModuleData(ulong thread, uint index, out ThreadLocalModuleData data)
        {
            InitDelegate(ref _getThreadLocalModuleData, VTable.GetThreadLocalModuleData);

            return _getThreadLocalModuleData(Self, thread, index, out data) == S_OK;
        }

        public ulong GetILForModule(ulong moduleAddr, uint rva)
        {
            InitDelegate(ref _getILForModule, VTable.GetILForModule);

            int hr = _getILForModule(Self, moduleAddr, rva, out ClrDataAddress result);
            return hr == S_OK ? (ulong)result : 0ul;
        }

        public COMInterfacePointerData[]? GetCCWInterfaces(ulong ccw, int count)
        {
            InitDelegate(ref _getCCWInterfaces, VTable.GetCCWInterfaces);

            COMInterfacePointerData[] data = new COMInterfacePointerData[count];
            if (_getCCWInterfaces(Self, ccw, count, data, out int pNeeded) >= 0)
                return data;

            return null;
        }

        public COMInterfacePointerData[]? GetRCWInterfaces(ulong ccw, int count)
        {
            InitDelegate(ref _getRCWInterfaces, VTable.GetRCWInterfaces);

            COMInterfacePointerData[] data = new COMInterfacePointerData[count];
            if (_getRCWInterfaces(Self, ccw, count, data, out int pNeeded) >= 0)
                return data;

            return null;
        }

        public bool GetDomainLocalModuleDataFromModule(ulong module, out DomainLocalModuleData data)
        {
            InitDelegate(ref _getDomainLocalModuleDataFromModule, VTable.GetDomainLocalModuleDataFromModule);
            int res = _getDomainLocalModuleDataFromModule(Self, module, out data);
            return SUCCEEDED(res);
        }

        public bool GetDomainLocalModuleDataFromAppDomain(ulong appDomain, int id, out DomainLocalModuleData data)
        {
            InitDelegate(ref _getDomainLocalModuleDataFromAppDomain, VTable.GetDomainLocalModuleDataFromAppDomain);
            int res = _getDomainLocalModuleDataFromAppDomain(Self, appDomain, id, out data);
            return SUCCEEDED(res);
        }

        public bool GetWorkRequestData(ulong request, out WorkRequestData data)
        {
            InitDelegate(ref _getWorkRequestData, VTable.GetWorkRequestData);
            int hr = _getWorkRequestData(Self, request, out data);
            return SUCCEEDED(hr);
        }

        public bool GetThreadPoolData(out ThreadPoolData data)
        {
            InitDelegate(ref _getThreadPoolData, VTable.GetThreadpoolData);
            int hr = _getThreadPoolData(Self, out data);
            return SUCCEEDED(hr);
        }

        public bool GetSyncBlockData(int index, out SyncBlockData data)
        {
            InitDelegate(ref _getSyncBlock, VTable.GetSyncBlockData);
            int hr = _getSyncBlock(Self, index, out data);
            return SUCCEEDED(hr);
        }

        public string? GetAppBase(ulong domain)
        {
            InitDelegate(ref _getAppBase, VTable.GetApplicationBase);
            return GetString(_getAppBase, domain);
        }

        public string? GetConfigFile(ulong domain)
        {
            InitDelegate(ref _getConfigFile, VTable.GetAppDomainConfigFile);
            return GetString(_getConfigFile, domain);
        }

        public bool GetCodeHeaderData(ulong ip, out CodeHeaderData codeHeaderData)
        {
            if (ip == 0)
            {
                codeHeaderData = default;
                return false;
            }

            InitDelegate(ref _getCodeHeaderData, VTable.GetCodeHeaderData);

            int hr = _getCodeHeaderData(Self, ip, out codeHeaderData);
            return hr == S_OK;
        }

        public ClrDataAddress GetMethodDescPtrFromFrame(ulong frame)
        {
            InitDelegate(ref _getMethodDescPtrFromFrame, VTable.GetMethodDescPtrFromFrame);
            if (_getMethodDescPtrFromFrame(Self, frame, out ClrDataAddress data) == S_OK)
                return data;

            return default;
        }

        public ClrDataAddress GetMethodDescPtrFromIP(ulong frame)
        {
            InitDelegate(ref _getMethodDescPtrFromIP, VTable.GetMethodDescPtrFromIP);
            if (_getMethodDescPtrFromIP(Self, frame, out ClrDataAddress data) == S_OK)
                return data;

            return default;
        }

        public string GetFrameName(ulong vtable)
        {
            InitDelegate(ref _getFrameName, VTable.GetFrameName);
            return GetString(_getFrameName, vtable, false) ?? "Unknown Frame";
        }

        public bool GetFieldInfo(ulong mt, out V4FieldInfo data)
        {
            InitDelegate(ref _getFieldInfo, VTable.GetMethodTableFieldData);
            int hr = _getFieldInfo(Self, mt, out data);
            return SUCCEEDED(hr);
        }

        public bool GetFieldData(ulong fieldDesc, out FieldData data)
        {
            InitDelegate(ref _getFieldData, VTable.GetFieldDescData);
            int hr = _getFieldData(Self, fieldDesc, out data);
            return SUCCEEDED(hr);
        }

        public bool GetObjectData(ulong obj, out V45ObjectData data)
        {
            InitDelegate(ref _getObjectData, VTable.GetObjectData);
            int hr = _getObjectData(Self, obj, out data);
            return SUCCEEDED(hr);
        }

        public bool GetCCWData(ulong ccw, out CcwData data)
        {
            InitDelegate(ref _getCCWData, VTable.GetCCWData);
            int hr = _getCCWData(Self, ccw, out data);
            return SUCCEEDED(hr);
        }

        public bool GetRCWData(ulong rcw, out RcwData data)
        {
            InitDelegate(ref _getRCWData, VTable.GetRCWData);
            int hr = _getRCWData(Self, rcw, out data);
            return SUCCEEDED(hr);
        }

        public ClrDataModule? GetClrDataModule(ulong module)
        {
            if (module == 0)
                return null;

            InitDelegate(ref _getModule, VTable.GetModule);
            if (_getModule(Self, module, out IntPtr iunk) != S_OK)
                return null;

            return new ClrDataModule(_library, iunk);
        }

        public MetadataImport? GetMetadataImport(ulong module)
        {
            if (module == 0)
                return null;

            InitDelegate(ref _getModule, VTable.GetModule);
            if (_getModule(Self, module, out IntPtr iunk) != S_OK)
                return null;

            try
            {
                return new MetadataImport(_library, iunk);
            }
            catch (InvalidCastException)
            {
                // QueryInterface on MetaDataImport seems to fail when we don't have full
                // metadata available.
                return null;
            }
        }

        public bool GetCommonMethodTables(out CommonMethodTables commonMTs)
        {
            InitDelegate(ref _getCommonMethodTables, VTable.GetUsefulGlobals);
            return _getCommonMethodTables(Self, out commonMTs) == S_OK;
        }

        public ClrDataAddress[] GetAssemblyList(ulong appDomain)
        {
            return GetAssemblyList(appDomain, 0);
        }

        public ClrDataAddress[] GetAssemblyList(ulong appDomain, int count)
        {
            return GetModuleOrAssembly(appDomain, count, ref _getAssemblyList, VTable.GetAssemblyList);
        }

        public bool GetAssemblyData(ulong domain, ulong assembly, out AssemblyData data)
        {
            InitDelegate(ref _getAssemblyData, VTable.GetAssemblyData);

            // 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.

            int hr = _getAssemblyData(Self, domain, assembly, out data);
            return SUCCEEDED(hr) || data.Address == assembly;
        }

        public bool GetAppDomainData(ulong addr, out AppDomainData data)
        {
            InitDelegate(ref _getAppDomainData, VTable.GetAppDomainData);

            // 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.

            int hr = _getAppDomainData(Self, addr, out data);
            return SUCCEEDED(hr) || data.Address == addr && data.StubHeap != 0;
        }

        public string? GetAppDomainName(ulong appDomain)
        {
            InitDelegate(ref _getAppDomainName, VTable.GetAppDomainName);
            return GetString(_getAppDomainName, appDomain);
        }

        public string? GetAssemblyName(ulong assembly)
        {
            InitDelegate(ref _getAssemblyName, VTable.GetAssemblyName);
            return GetString(_getAssemblyName, assembly);
        }

        public bool GetAppDomainStoreData(out AppDomainStoreData data)
        {
            InitDelegate(ref _getAppDomainStoreData, VTable.GetAppDomainStoreData);
            int hr = _getAppDomainStoreData(Self, out data);
            return SUCCEEDED(hr);
        }

        public bool GetMethodTableData(ulong addr, out MethodTableData data)
        {
            InitDelegate(ref _getMethodTableData, VTable.GetMethodTableData);
            int hr = _getMethodTableData(Self, addr, out data);
            return SUCCEEDED(hr);
        }

        public string? GetMethodTableName(ulong mt)
        {
            InitDelegate(ref _getMethodTableName, VTable.GetMethodTableName);
            return GetString(_getMethodTableName, mt);
        }

        public string? GetJitHelperFunctionName(ulong addr)
        {
            InitDelegate(ref _getJitHelperFunctionName, VTable.GetJitHelperFunctionName);<commit_msg>Don't request MethodTableData for TypeHandles (#583)<commit_after>﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Diagnostics.Runtime.Utilities;

namespace Microsoft.Diagnostics.Runtime.DacInterface
{
    /// <summary>
    /// This is an undocumented, untested, and unsupported interface.  Do not use.
    /// </summary>
    public sealed unsafe class SOSDac : CallableCOMWrapper
    {
        internal static readonly Guid IID_ISOSDac = new Guid("436f00f2-b42a-4b9f-870c-e73db66ae930");

        private readonly DacLibrary _library;

        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;
        }

        private DacGetIntPtr? _getHandleEnum;
        private GetHandleEnumForTypesDelegate? _getHandleEnumForTypes;
        private DacGetIntPtrWithArg? _getStackRefEnum;
        private DacGetThreadData? _getThreadData;
        private DacGetHeapDetailsWithArg? _getGCHeapDetails;
        private DacGetHeapDetails? _getGCHeapStaticData;
        private DacGetAddrArray? _getGCHeapList;
        private DacGetAddrArray? _getAppDomainList;
        private DacGetAddrArrayWithArg? _getAssemblyList;
        private DacGetAddrArrayWithArg? _getModuleList;
        private DacGetAssemblyData? _getAssemblyData;
        private DacGetADStoreData? _getAppDomainStoreData;
        private DacGetMTData? _getMethodTableData;
        private DacGetAddrWithArg? _getMTForEEClass;
        private DacGetGCInfoData? _getGCHeapData;
        private DacGetCommonMethodTables? _getCommonMethodTables;
        private DacGetCharArrayWithArg? _getMethodTableName;
        private DacGetByteArrayWithArg? _getJitHelperFunctionName;
        private DacGetCharArrayWithArg? _getPEFileName;
        private DacGetCharArrayWithArg? _getAppDomainName;
        private DacGetCharArrayWithArg? _getAssemblyName;
        private DacGetCharArrayWithArg? _getAppBase;
        private DacGetCharArrayWithArg? _getConfigFile;
        private DacGetModuleData? _getModuleData;
        private DacGetSegmentData? _getSegmentData;
        private DacGetAppDomainData? _getAppDomainData;
        private DacGetJitManagers? _getJitManagers;
        private DacTraverseLoaderHeap? _traverseLoaderHeap;
        private DacTraverseStubHeap? _traverseStubHeap;
        private DacTraverseModuleMap? _traverseModuleMap;
        private DacGetFieldInfo? _getFieldInfo;
        private DacGetFieldData? _getFieldData;
        private DacGetObjectData? _getObjectData;
        private DacGetCCWData? _getCCWData;
        private DacGetRCWData? _getRCWData;
        private DacGetCharArrayWithArg? _getFrameName;
        private DacGetAddrWithArg? _getMethodDescPtrFromFrame;
        private DacGetAddrWithArg? _getMethodDescPtrFromIP;
        private DacGetCodeHeaderData? _getCodeHeaderData;
        private DacGetSyncBlockData? _getSyncBlock;
        private DacGetThreadPoolData? _getThreadPoolData;
        private DacGetWorkRequestData? _getWorkRequestData;
        private DacGetDomainLocalModuleDataFromAppDomain? _getDomainLocalModuleDataFromAppDomain;
        private DacGetLocalModuleData? _getDomainLocalModuleDataFromModule;
        private DacGetCodeHeaps? _getCodeHeaps;
        private DacGetCOMPointers? _getCCWInterfaces;
        private DacGetCOMPointers? _getRCWInterfaces;
        private DacGetAddrWithArgs? _getILForModule;
        private DacGetThreadLocalModuleData? _getThreadLocalModuleData;
        private DacGetAddrWithArgs? _getMethodTableSlot;
        private DacGetCharArrayWithArg? _getMethodDescName;
        private DacGetThreadFromThinLock? _getThreadFromThinlockId;
        private DacGetUInt? _getTlsIndex;
        private DacGetThreadStoreData? _getThreadStoreData;
        private GetMethodDescDataDelegate? _getMethodDescData;
        private GetModuleDelegate? _getModule;
        private GetMethodDescFromTokenDelegate? _getMethodDescFromToken;

        public RejitData[] GetRejitData(ulong md, ulong ip = 0)
        {
            InitDelegate(ref _getMethodDescData, VTable.GetMethodDescData);
            int hr = _getMethodDescData(Self, md, ip, out MethodDescData data, 0, null, out int needed);

            if (SUCCEEDED(hr) && needed > 1)
            {
                RejitData[] result = new RejitData[needed];
                hr = _getMethodDescData(Self, md, ip, out data, result.Length, result, out needed);
                if (SUCCEEDED(hr))
                    return result;
            }

            return Array.Empty<RejitData>();
        }

        public bool GetMethodDescData(ulong md, ulong ip, out MethodDescData data)
        {
            InitDelegate(ref _getMethodDescData, VTable.GetMethodDescData);
            int hr = _getMethodDescData(Self, md, ip, out data, 0, null, out int needed);
            return SUCCEEDED(hr);
        }

        public bool GetThreadStoreData(out ThreadStoreData data)
        {
            InitDelegate(ref _getThreadStoreData, VTable.GetThreadStoreData);
            return _getThreadStoreData(Self, out data) == S_OK;
        }

        public uint GetTlsIndex()
        {
            InitDelegate(ref _getTlsIndex, VTable.GetTLSIndex);
            if (_getTlsIndex(Self, out uint index) == S_OK)
                return index;

            return uint.MaxValue;
        }

        public ClrDataAddress GetThreadFromThinlockId(uint id)
        {
            InitDelegate(ref _getThreadFromThinlockId, VTable.GetThreadFromThinlockID);
            if (_getThreadFromThinlockId(Self, id, out ClrDataAddress thread) == S_OK)
                return thread;

            return default;
        }

        public string? GetMethodDescName(ulong md)
        {
            if (md == 0)
                return null;

            InitDelegate(ref _getMethodDescName, VTable.GetMethodDescName);

            if (_getMethodDescName(Self, md, 0, null, out int needed) < S_OK)
                return null;

            byte[] buffer = ArrayPool<byte>.Shared.Rent(needed * sizeof(char));
            try
            {
                int actuallyNeeded;
                fixed (byte* bufferPtr = buffer)
                    if (_getMethodDescName(Self, md, needed, bufferPtr, out actuallyNeeded) < S_OK)
                        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)
                        if (_getMethodDescName(Self, md, actuallyNeeded, bufferPtr, out actuallyNeeded) < S_OK)
                            return null;
                }

                return Encoding.Unicode.GetString(buffer, 0, (actuallyNeeded - 1) * sizeof(char));
            }
            finally
            {
                ArrayPool<byte>.Shared.Return(buffer);
            }
        }

        public ulong GetMethodTableSlot(ulong mt, int slot)
        {
            if (mt == 0)
                return 0;

            InitDelegate(ref _getMethodTableSlot, VTable.GetMethodTableSlot);

            if (_getMethodTableSlot(Self, mt, (uint)slot, out ClrDataAddress ip) == S_OK)
                return ip;

            return 0;
        }

        public bool GetThreadLocalModuleData(ulong thread, uint index, out ThreadLocalModuleData data)
        {
            InitDelegate(ref _getThreadLocalModuleData, VTable.GetThreadLocalModuleData);

            return _getThreadLocalModuleData(Self, thread, index, out data) == S_OK;
        }

        public ulong GetILForModule(ulong moduleAddr, uint rva)
        {
            InitDelegate(ref _getILForModule, VTable.GetILForModule);

            int hr = _getILForModule(Self, moduleAddr, rva, out ClrDataAddress result);
            return hr == S_OK ? (ulong)result : 0ul;
        }

        public COMInterfacePointerData[]? GetCCWInterfaces(ulong ccw, int count)
        {
            InitDelegate(ref _getCCWInterfaces, VTable.GetCCWInterfaces);

            COMInterfacePointerData[] data = new COMInterfacePointerData[count];
            if (_getCCWInterfaces(Self, ccw, count, data, out int pNeeded) >= 0)
                return data;

            return null;
        }

        public COMInterfacePointerData[]? GetRCWInterfaces(ulong ccw, int count)
        {
            InitDelegate(ref _getRCWInterfaces, VTable.GetRCWInterfaces);

            COMInterfacePointerData[] data = new COMInterfacePointerData[count];
            if (_getRCWInterfaces(Self, ccw, count, data, out int pNeeded) >= 0)
                return data;

            return null;
        }

        public bool GetDomainLocalModuleDataFromModule(ulong module, out DomainLocalModuleData data)
        {
            InitDelegate(ref _getDomainLocalModuleDataFromModule, VTable.GetDomainLocalModuleDataFromModule);
            int res = _getDomainLocalModuleDataFromModule(Self, module, out data);
            return SUCCEEDED(res);
        }

        public bool GetDomainLocalModuleDataFromAppDomain(ulong appDomain, int id, out DomainLocalModuleData data)
        {
            InitDelegate(ref _getDomainLocalModuleDataFromAppDomain, VTable.GetDomainLocalModuleDataFromAppDomain);
            int res = _getDomainLocalModuleDataFromAppDomain(Self, appDomain, id, out data);
            return SUCCEEDED(res);
        }

        public bool GetWorkRequestData(ulong request, out WorkRequestData data)
        {
            InitDelegate(ref _getWorkRequestData, VTable.GetWorkRequestData);
            int hr = _getWorkRequestData(Self, request, out data);
            return SUCCEEDED(hr);
        }

        public bool GetThreadPoolData(out ThreadPoolData data)
        {
            InitDelegate(ref _getThreadPoolData, VTable.GetThreadpoolData);
            int hr = _getThreadPoolData(Self, out data);
            return SUCCEEDED(hr);
        }

        public bool GetSyncBlockData(int index, out SyncBlockData data)
        {
            InitDelegate(ref _getSyncBlock, VTable.GetSyncBlockData);
            int hr = _getSyncBlock(Self, index, out data);
            return SUCCEEDED(hr);
        }

        public string? GetAppBase(ulong domain)
        {
            InitDelegate(ref _getAppBase, VTable.GetApplicationBase);
            return GetString(_getAppBase, domain);
        }

        public string? GetConfigFile(ulong domain)
        {
            InitDelegate(ref _getConfigFile, VTable.GetAppDomainConfigFile);
            return GetString(_getConfigFile, domain);
        }

        public bool GetCodeHeaderData(ulong ip, out CodeHeaderData codeHeaderData)
        {
            if (ip == 0)
            {
                codeHeaderData = default;
                return false;
            }

            InitDelegate(ref _getCodeHeaderData, VTable.GetCodeHeaderData);

            int hr = _getCodeHeaderData(Self, ip, out codeHeaderData);
            return hr == S_OK;
        }

        public ClrDataAddress GetMethodDescPtrFromFrame(ulong frame)
        {
            InitDelegate(ref _getMethodDescPtrFromFrame, VTable.GetMethodDescPtrFromFrame);
            if (_getMethodDescPtrFromFrame(Self, frame, out ClrDataAddress data) == S_OK)
                return data;

            return default;
        }

        public ClrDataAddress GetMethodDescPtrFromIP(ulong frame)
        {
            InitDelegate(ref _getMethodDescPtrFromIP, VTable.GetMethodDescPtrFromIP);
            if (_getMethodDescPtrFromIP(Self, frame, out ClrDataAddress data) == S_OK)
                return data;

            return default;
        }

        public string GetFrameName(ulong vtable)
        {
            InitDelegate(ref _getFrameName, VTable.GetFrameName);
            return GetString(_getFrameName, vtable, false) ?? "Unknown Frame";
        }

        public bool GetFieldInfo(ulong mt, out V4FieldInfo data)
        {
            InitDelegate(ref _getFieldInfo, VTable.GetMethodTableFieldData);
            int hr = _getFieldInfo(Self, mt, out data);
            return SUCCEEDED(hr);
        }

        public bool GetFieldData(ulong fieldDesc, out FieldData data)
        {
            InitDelegate(ref _getFieldData, VTable.GetFieldDescData);
            int hr = _getFieldData(Self, fieldDesc, out data);
            return SUCCEEDED(hr);
        }

        public bool GetObjectData(ulong obj, out V45ObjectData data)
        {
            InitDelegate(ref _getObjectData, VTable.GetObjectData);
            int hr = _getObjectData(Self, obj, out data);
            return SUCCEEDED(hr);
        }

        public bool GetCCWData(ulong ccw, out CcwData data)
        {
            InitDelegate(ref _getCCWData, VTable.GetCCWData);
            int hr = _getCCWData(Self, ccw, out data);
            return SUCCEEDED(hr);
        }

        public bool GetRCWData(ulong rcw, out RcwData data)
        {
            InitDelegate(ref _getRCWData, VTable.GetRCWData);
            int hr = _getRCWData(Self, rcw, out data);
            return SUCCEEDED(hr);
        }

        public ClrDataModule? GetClrDataModule(ulong module)
        {
            if (module == 0)
                return null;

            InitDelegate(ref _getModule, VTable.GetModule);
            if (_getModule(Self, module, out IntPtr iunk) != S_OK)
                return null;

            return new ClrDataModule(_library, iunk);
        }

        public MetadataImport? GetMetadataImport(ulong module)
        {
            if (module == 0)
                return null;

            InitDelegate(ref _getModule, VTable.GetModule);
            if (_getModule(Self, module, out IntPtr iunk) != S_OK)
                return null;

            try
            {
                return new MetadataImport(_library, iunk);
            }
            catch (InvalidCastException)
            {
                // QueryInterface on MetaDataImport seems to fail when we don't have full
                // metadata available.
                return null;
            }
        }

        public bool GetCommonMethodTables(out CommonMethodTables commonMTs)
        {
            InitDelegate(ref _getCommonMethodTables, VTable.GetUsefulGlobals);
            return _getCommonMethodTables(Self, out commonMTs) == S_OK;
        }

        public ClrDataAddress[] GetAssemblyList(ulong appDomain)
        {
            return GetAssemblyList(appDomain, 0);
        }

        public ClrDataAddress[] GetAssemblyList(ulong appDomain, int count)
        {
            return GetModuleOrAssembly(appDomain, count, ref _getAssemblyList, VTable.GetAssemblyList);
        }

        public bool GetAssemblyData(ulong domain, ulong assembly, out AssemblyData data)
        {
            InitDelegate(ref _getAssemblyData, VTable.GetAssemblyData);

            // 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.

            int hr = _getAssemblyData(Self, domain, assembly, out data);
            return SUCCEEDED(hr) || data.Address == assembly;
        }

        public bool GetAppDomainData(ulong addr, out AppDomainData data)
        {
            InitDelegate(ref _getAppDomainData, VTable.GetAppDomainData);

            // 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.

            int hr = _getAppDomainData(Self, addr, out data);
            return SUCCEEDED(hr) || data.Address == addr && data.StubHeap != 0;
        }

        public string? GetAppDomainName(ulong appDomain)
        {
            InitDelegate(ref _getAppDomainName, VTable.GetAppDomainName);
            return GetString(_getAppDomainName, appDomain);
        }

        public string? GetAssemblyName(ulong assembly)
        {
            InitDelegate(ref _getAssemblyName, VTable.GetAssemblyName);
            return GetString(_getAssemblyName, assembly);
        }

        public bool GetAppDomainStoreData(out AppDomainStoreData data)
        {
            InitDelegate(ref _getAppDomainStoreData, VTable.GetAppDomainStoreData);
            int hr = _getAppDomainStoreData(Self, out data);
            return SUCCEEDED(hr);
        }

        public bool 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 false;
            }

            InitDelegate(ref _getMethodTableData, VTable.GetMethodTableData);
            int hr = _getMethodTableData(Self, addr, out data);
            return SUCCEEDED(hr);
        }

        public string? GetMethodTableName(ulong mt)
        {
            InitDelegate(ref _getMethodTableName, VTable.GetMethodTableName);
            return GetString(_getMethodTableName, mt);
        }

        public string? GetJitHelperFunctionName(ulong addr)
        {
            InitDelegate(ref _getJitHelperFunctionName, VTable.GetJitHelperFunctionName);
{'fraction_non_alphanumeric': 0.06631748143221372, 'fraction_numerical': 0.002494180246092451, 'mean_word_length': 2.2846349899872567, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3434060', 'n_tokens_mistral': 10018, 'n_tokens_neox': 9715, 'n_words': 2392}