Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public static class CorDbgHResults
public const int CORDBG_E_READVIRTUAL_FAILURE = unchecked((int)0x80131c49);
public const int ERROR_BUFFER_OVERFLOW = unchecked((int)0x8007006F); // HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW)
public const int CORDBG_E_CLASS_NOT_LOADED = unchecked((int)0x80131303);
public const int CORDBG_E_FUNCTION_NOT_IL = unchecked((int)0x8013130a);
public const int CORDBG_E_TARGET_INCONSISTENT = unchecked((int)0x80131c36);
public const int CORDBG_S_NOT_ALL_BITS_SET = unchecked((int)0x00131c13);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public enum TokenType : uint
mdtTypeDef = 0x02 << 24,
mdtFieldDef = 0x04 << 24,
mdtMethodDef = 0x06 << 24,
mdtSignature = 0x11 << 24,
}

public const uint TokenTypeMask = 0xff000000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
Expand Down Expand Up @@ -1400,7 +1403,73 @@ public int ResolveExactGenericArgsToken(uint dwExactGenericArgsTokenIndex, ulong
}

public int GetILCodeAndSig(ulong vmAssembly, uint functionToken, DacDbiTargetBuffer* pTargetBuffer, uint* pLocalSigToken)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetILCodeAndSig(vmAssembly, functionToken, pTargetBuffer, pLocalSigToken) : HResults.E_NOTIMPL;
{
*pTargetBuffer = default;
*pLocalSigToken = (uint)EcmaMetadataUtils.TokenType.mdtSignature;
Comment thread
rcj1 marked this conversation as resolved.
int hr = HResults.S_OK;
try
{
ILoader loader = _target.Contracts.Loader;
Contracts.ModuleHandle moduleHandle = loader.GetModuleHandleFromAssemblyPtr(new TargetPointer(vmAssembly));

MetadataReader mdReader = _target.Contracts.EcmaMetadata.GetMetadata(moduleHandle)
?? throw new InvalidOperationException("Module has no metadata.");
MethodDefinitionHandle mdMethodHandle = MetadataTokens.MethodDefinitionHandle((int)EcmaMetadataUtils.GetRowId(functionToken));
MethodDefinition methodDef = mdReader.GetMethodDefinition(mdMethodHandle);

// Reject anything whose metadata CodeType isn't IL.
if ((methodDef.ImplAttributes & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL)
throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_FUNCTION_NOT_IL)!;

ModuleLookupTables lookupTables = loader.GetLookupTables(moduleHandle);
TargetPointer methodDescPtr = loader.GetModuleLookupMapElement(lookupTables.MethodDefToDesc, functionToken, out _);
if (methodDescPtr != TargetPointer.Null)
{
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem;
MethodDescHandle mdHandle = rts.GetMethodDescHandle(methodDescPtr);
if (!rts.IsIL(mdHandle))
throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_FUNCTION_NOT_IL)!;
}

else if (methodDef.RelativeVirtualAddress == 0)
throw Marshal.GetExceptionForHR(CorDbgHResults.CORDBG_E_FUNCTION_NOT_IL)!;

TargetPointer headerPtr = loader.GetILHeader(moduleHandle, functionToken);
if (headerPtr != TargetPointer.Null)
{
int headerSize = HeaderReaderHelpers.GetHeaderSize(_target, headerPtr);
int codeSize = HeaderReaderHelpers.GetCodeSize(_target, headerPtr);

if (HeaderReaderHelpers.TryGetLocalVarSigToken(_target, headerPtr, out int localToken) && localToken != 0)
{
*pLocalSigToken = (uint)localToken;
}

pTargetBuffer->pAddress = headerPtr.Value + (ulong)headerSize;
pTargetBuffer->cbSize = (uint)codeSize;
}
}
catch (System.Exception ex)
{
hr = ex.HResult;
}
#if DEBUG
if (_legacy is not null)
{
DacDbiTargetBuffer bufferLocal = default;
uint sigLocal;
int hrLocal = _legacy.GetILCodeAndSig(vmAssembly, functionToken, &bufferLocal, &sigLocal);
Debug.ValidateHResult(hr, hrLocal);
if (hr == HResults.S_OK)
{
Debug.Assert(pTargetBuffer->pAddress == bufferLocal.pAddress, $"cDAC ILAddr: 0x{pTargetBuffer->pAddress:X}, DAC ILAddr: 0x{bufferLocal.pAddress:X}");
Debug.Assert(pTargetBuffer->cbSize == bufferLocal.cbSize, $"cDAC ILSize: {pTargetBuffer->cbSize}, DAC ILSize: {bufferLocal.cbSize}");
Debug.Assert(*pLocalSigToken == sigLocal, $"cDAC LocalSig: 0x{*pLocalSigToken:X}, DAC LocalSig: 0x{sigLocal:X}");
}
}
#endif
return hr;
}

public int GetNativeCodeInfo(ulong vmAssembly, uint functionToken, nint pJitManagerList)
=> LegacyFallbackHelper.CanFallback() && _legacy is not null ? _legacy.GetNativeCodeInfo(vmAssembly, functionToken, pJitManagerList) : HResults.E_NOTIMPL;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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.InteropServices;

namespace Microsoft.Diagnostics.DataContractReader.Legacy;
Expand All @@ -14,6 +15,34 @@ internal enum CorILMethodFlags
}
internal static class HeaderReaderHelpers
{
public static int GetHeaderSize(Target target, TargetPointer ilHeader)
{
// see ECMA-335 II.25.4
ushort sizeAndFlags = target.Read<ushort>(ilHeader);
CorILMethodFlags flags = (CorILMethodFlags)(sizeAndFlags & (int)CorILMethodFlags.CorILMethod_FormatMask);

return flags switch
{
CorILMethodFlags.CorILMethod_TinyFormat => 1,
CorILMethodFlags.CorILMethod_FatFormat => 12,
_ => throw new BadImageFormatException("Invalid IL method header."),
Comment on lines +20 to +28
};
}

public static int GetCodeSize(Target target, TargetPointer ilHeader)
{
// see ECMA-335 II.25.4
ushort sizeAndFlags = target.Read<ushort>(ilHeader);
CorILMethodFlags flags = (CorILMethodFlags)(sizeAndFlags & (int)CorILMethodFlags.CorILMethod_FormatMask);

return flags switch
{
CorILMethodFlags.CorILMethod_TinyFormat => sizeAndFlags >> 2,
CorILMethodFlags.CorILMethod_FatFormat => (int)target.Read<uint>(ilHeader + 4),
_ => throw new BadImageFormatException("Invalid IL method header."),
};
}

public static bool TryGetLocalVarSigToken(Target target, TargetPointer ilHeader, out int localVarSigToken)
{
// see ECMA-335 II.25.4
Expand Down
Loading