src/Microsoft.Diagnostics.Runtime.Utilities/DbgEng/Wrappers/IDebugSymbolsWrapper.cs (203 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.Buffers;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Text;
namespace Microsoft.Diagnostics.Runtime.Utilities.DbgEng
{
[DynamicInterfaceCastableImplementation]
internal unsafe interface IDebugSymbolsWrapper : IDebugSymbols
{
string? IDebugSymbols.SymbolPath
{
get
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
int hr = vtable->GetSymbolPathWide(self, null, 0, out int size);
if (hr < 0)
return null;
else if (size is 0 or 1)
return string.Empty;
char[] buffer = ArrayPool<char>.Shared.Rent(size);
try
{
fixed (char* ptr = buffer)
hr = vtable->GetSymbolPathWide(self, ptr, size, out size);
if (hr < 0)
return null;
return new(buffer, 0, size - 1);
}
finally
{
ArrayPool<char>.Shared.Return(buffer);
}
}
set
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
if (string.IsNullOrWhiteSpace(value))
{
fixed (char* ptr = string.Empty)
vtable->SetSymbolPathWide(self, ptr);
}
else
{
fixed (char* ptr = value)
vtable->SetSymbolPathWide(self, ptr);
}
}
}
int IDebugSymbols.GetNumberModules(out int modules, out int unloadedModules)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
return vtable->GetNumberModules(self, out modules, out unloadedModules);
}
int IDebugSymbols.GetImageBase(int index, out ulong baseAddress)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
return vtable->GetModuleByIndex(self, index, out baseAddress);
}
int IDebugSymbols.GetModuleParameters(ReadOnlySpan<ulong> baseAddresses, Span<DEBUG_MODULE_PARAMETERS> parameters)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
int count = Math.Min(baseAddresses.Length, parameters.Length);
fixed (ulong* basesPtr = baseAddresses)
fixed (DEBUG_MODULE_PARAMETERS* parametersPtr = parameters)
return vtable->GetModuleParameters(self, count, basesPtr, 0, parametersPtr);
}
int IDebugSymbols.Reload(string module)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
fixed (char* ptr = module)
return vtable->ReloadWide(self, ptr);
}
int IDebugSymbols.GetModuleParameters(ulong baseAddresses, out DEBUG_MODULE_PARAMETERS parameters)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
fixed (DEBUG_MODULE_PARAMETERS* parametersPtr = ¶meters)
return vtable->GetModuleParameters(self, 1, &baseAddresses, 0, parametersPtr);
}
int IDebugSymbols.GetModuleVersionInformation(int index, ulong address, string item, Span<byte> buffer)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
byte[] itemBuffer = Encoding.ASCII.GetBytes(item);
fixed (byte* bufferPtr = buffer)
fixed (byte* itemBufferPtr = itemBuffer)
return vtable->GetModuleVersionInformation(self, index, address, itemBufferPtr, bufferPtr, buffer.Length, out int size);
}
int IDebugSymbols.GetModuleName(DEBUG_MODNAME which, ulong baseAddress, out string name)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
int hr = vtable->GetModuleNameStringWide(self, which, DEBUG_ANY_ID, baseAddress, null, 0, out int size);
if (hr < 0)
{
name = string.Empty;
return hr;
}
char[] buffer = ArrayPool<char>.Shared.Rent(size);
fixed (char* strPtr = buffer)
hr = vtable->GetModuleNameStringWide(self, which, DEBUG_ANY_ID, baseAddress, strPtr, size, out _);
if (hr < 0)
name = string.Empty;
else
name = new string(new Span<char>(buffer)[0..(size - 1)]);
ArrayPool<char>.Shared.Return(buffer);
return hr;
}
int IDebugSymbols.GetTypeId(ulong moduleBase, string name, out ulong typeId)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
fixed (char* namePtr = name)
return vtable->GetTypeIdWide(self, moduleBase, namePtr, out typeId);
}
int IDebugSymbols.GetFieldOffset(ulong moduleBase, ulong typeId, string name, out ulong offset)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
fixed (char* namePtr = name)
return vtable->GetFieldOffsetWide(self, moduleBase, typeId, namePtr, out offset);
}
int IDebugSymbols.GetModuleByOffset(ulong baseAddr, int nextIndex, out int index, out ulong claimedBaseAddr)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
return vtable->GetModuleByOffset(self, baseAddr, nextIndex, out index, out claimedBaseAddr);
}
bool IDebugSymbols.GetOffsetByName(string name, out ulong offset)
{
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
fixed (char* namePtr = name)
{
int hr = vtable->GetOffsetByNameWide(self, namePtr, out offset);
if (hr == 0)
return true;
}
offset = 0;
return false;
}
bool IDebugSymbols.GetNameByOffset(ulong address, [NotNullWhen(true)] out string? name, out ulong displacement)
{
displacement = 0;
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
int hr = vtable->GetNameByOffsetWide(self, address, null, 0, out int size, out _);
if (hr < 0)
{
name = null;
return false;
}
if (size is 0 or 1)
{
name = string.Empty;
return true;
}
char[] buffer = ArrayPool<char>.Shared.Rent(size);
try
{
fixed (char* ptr = buffer)
hr = vtable->GetNameByOffsetWide(self, address, ptr, size, out size, out displacement);
if (hr == 0)
name = new(buffer, 0, size - 1);
else
name = null;
return hr == 0;
}
finally
{
ArrayPool<char>.Shared.Return(buffer);
}
}
bool IDebugSymbols.GetNameByInlineContext(ulong offset, uint inlineContext, [NotNullWhen(true)] out string? name, out ulong displacement)
{
displacement = 0;
GetVTable(this, out nint self, out IDebugSymbolsVtable* vtable);
int hr = vtable->GetNameByInlineContextWide(self, offset, inlineContext, null, 0, out int size, out _);
if (hr < 0)
{
name = null;
return false;
}
if (size is 0 or 1)
{
name = string.Empty;
return true;
}
char[] buffer = ArrayPool<char>.Shared.Rent(size);
try
{
fixed (char* ptr = buffer)
hr = vtable->GetNameByInlineContextWide(self, offset, inlineContext, ptr, size, out size, out displacement);
if (hr == 0)
name = new(buffer, 0, size - 1);
else
name = null;
return hr == 0;
}
finally
{
ArrayPool<char>.Shared.Return(buffer);
}
}
private static void GetVTable(object ths, out nint self, out IDebugSymbolsVtable* vtable)
{
self = ((IDbgInterfaceProvider)ths).DebugSymbols;
vtable = *(IDebugSymbolsVtable**)self;
}
}
}