Skip to content

Commit e55be4d

Browse files
Max CharlambCopilot
andcommitted
[cDAC] Add RuntimeSignatureDecoder for ELEMENT_TYPE_INTERNAL support
Custom signature decoder handling runtime-internal type codes (ELEMENT_TYPE_INTERNAL 0x21, ELEMENT_TYPE_CMOD_INTERNAL 0x22) which SRM's SignatureDecoder cannot parse. Replaces SRM in PromoteCallerStack. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 7c419ec commit e55be4d

3 files changed

Lines changed: 475 additions & 20 deletions

File tree

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/FrameHandling/FrameIterator.cs

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -580,9 +580,10 @@ private void PromoteCallerStack(
580580
return;
581581

582582
ReadOnlySpan<byte> signature;
583+
MetadataReader? metadataReader;
583584
try
584585
{
585-
signature = GetMethodSignatureBytes(methodDescPtr);
586+
signature = GetMethodSignatureBytes(methodDescPtr, out metadataReader);
586587
}
587588
catch (System.Exception)
588589
{
@@ -595,20 +596,14 @@ private void PromoteCallerStack(
595596
MethodSignature<GcTypeKind> methodSig;
596597
try
597598
{
598-
unsafe
599-
{
600-
fixed (byte* pSig = signature)
601-
{
602-
BlobReader blobReader = new(pSig, signature.Length);
603-
SignatureDecoder<GcTypeKind, object?> decoder = new(
604-
GcSignatureTypeProvider.Instance, metadataReader: null!, genericContext: null);
605-
methodSig = decoder.DecodeMethodSignature(ref blobReader);
606-
}
607-
}
599+
RuntimeSignatureDecoder<GcTypeKind, object?, SpanSignatureReader> decoder = new(
600+
GcSignatureTypeProvider.Instance, target, genericContext: null,
601+
new SpanSignatureReader(signature, target.IsLittleEndian), metadataReader);
602+
methodSig = decoder.DecodeMethodSignature();
608603
}
609604
catch (System.Exception)
610605
{
611-
// If signature decoding fails (e.g., ELEMENT_TYPE_INTERNAL), skip this frame.
606+
// If signature decoding fails for any reason, skip this frame.
612607
// The GCRefMap path handles these cases when available.
613608
return;
614609
}
@@ -707,8 +702,9 @@ private void PromoteCallerStackHelper(
707702
}
708703
}
709704

710-
private ReadOnlySpan<byte> GetMethodSignatureBytes(TargetPointer methodDescPtr)
705+
private ReadOnlySpan<byte> GetMethodSignatureBytes(TargetPointer methodDescPtr, out MetadataReader? metadataReader)
711706
{
707+
metadataReader = null;
712708
IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem;
713709
MethodDescHandle mdh = rts.GetMethodDescHandle(methodDescPtr);
714710

@@ -727,13 +723,13 @@ private ReadOnlySpan<byte> GetMethodSignatureBytes(TargetPointer methodDescPtr)
727723
ModuleHandle moduleHandle = loader.GetModuleHandleFromModulePtr(modulePtr);
728724

729725
IEcmaMetadata ecmaMetadata = target.Contracts.EcmaMetadata;
730-
MetadataReader? mdReader = ecmaMetadata.GetMetadata(moduleHandle);
731-
if (mdReader is null)
726+
metadataReader = ecmaMetadata.GetMetadata(moduleHandle);
727+
if (metadataReader is null)
732728
return default;
733729

734730
MethodDefinitionHandle methodDefHandle = MetadataTokens.MethodDefinitionHandle((int)(methodToken & 0x00FFFFFF));
735-
MethodDefinition methodDef = mdReader.GetMethodDefinition(methodDefHandle);
736-
BlobReader blobReader = mdReader.GetBlobReader(methodDef.Signature);
731+
MethodDefinition methodDef = metadataReader.GetMethodDefinition(methodDefHandle);
732+
BlobReader blobReader = metadataReader.GetBlobReader(methodDef.Signature);
737733
return blobReader.ReadBytes(blobReader.Length);
738734
}
739735

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcSignatureTypeProvider.cs

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ internal enum GcTypeKind
2323

2424
/// <summary>
2525
/// Classifies signature types for GC scanning purposes.
26-
/// Implements <see cref="ISignatureTypeProvider{TType, TGenericContext}"/> for use
27-
/// with SRM's <see cref="SignatureDecoder{TType, TGenericContext}"/>.
26+
/// Implements <see cref="IRuntimeSignatureTypeProvider{TType, TGenericContext}"/> which
27+
/// is a superset of SRM's <see cref="ISignatureTypeProvider{TType, TGenericContext}"/>,
28+
/// adding support for <c>ELEMENT_TYPE_INTERNAL</c>.
2829
/// </summary>
2930
internal sealed class GcSignatureTypeProvider
30-
: ISignatureTypeProvider<GcTypeKind, object?>
31+
: IRuntimeSignatureTypeProvider<GcTypeKind, object?>
3132
{
3233
public static readonly GcSignatureTypeProvider Instance = new();
3334

@@ -60,5 +61,41 @@ public GcTypeKind GetGenericInstantiation(GcTypeKind genericType, ImmutableArray
6061
public GcTypeKind GetGenericTypeParameter(object? genericContext, int index) => GcTypeKind.Ref;
6162
public GcTypeKind GetFunctionPointerType(MethodSignature<GcTypeKind> signature) => GcTypeKind.None;
6263
public GcTypeKind GetModifiedType(GcTypeKind modifier, GcTypeKind unmodifiedType, bool isRequired) => unmodifiedType;
64+
public GcTypeKind GetInternalModifiedType(Target target, TargetPointer typeHandlePointer, GcTypeKind unmodifiedType, bool isRequired) => unmodifiedType;
6365
public GcTypeKind GetPinnedType(GcTypeKind elementType) => elementType;
66+
67+
public GcTypeKind GetInternalType(Target target, TargetPointer typeHandlePointer)
68+
{
69+
if (typeHandlePointer == TargetPointer.Null)
70+
return GcTypeKind.None;
71+
72+
try
73+
{
74+
IRuntimeTypeSystem rts = target.Contracts.RuntimeTypeSystem;
75+
TypeHandle th = rts.GetTypeHandle(typeHandlePointer);
76+
CorElementType corType = rts.GetSignatureCorElementType(th);
77+
78+
return corType switch
79+
{
80+
CorElementType.Void or CorElementType.Boolean or CorElementType.Char
81+
or CorElementType.I1 or CorElementType.U1
82+
or CorElementType.I2 or CorElementType.U2
83+
or CorElementType.I4 or CorElementType.U4
84+
or CorElementType.I8 or CorElementType.U8
85+
or CorElementType.R4 or CorElementType.R8
86+
or CorElementType.I or CorElementType.U
87+
or CorElementType.FnPtr or CorElementType.Ptr
88+
=> GcTypeKind.None,
89+
90+
CorElementType.Byref => GcTypeKind.Interior,
91+
CorElementType.ValueType => GcTypeKind.Other,
92+
93+
_ => GcTypeKind.Ref,
94+
};
95+
}
96+
catch
97+
{
98+
return GcTypeKind.Ref;
99+
}
100+
}
64101
}

0 commit comments

Comments
 (0)