Skip to content

[cDAC] GetConstructedType cannot resolve cross-module pointer TypeDescs #125792

Description

@max-charlamb

Summary

RuntimeTypeSystem_1.GetConstructedType fails to find pointer TypeDescs (e.g., int*) when the TypeDesc lives in a different module than the element type's loader module. This causes ClrDataFrame to return DEFAULT flags for pointer variables instead of IS_POINTER.

Root Cause

GetConstructedType searches only the loader module's AvailableTypeParams hash table:

  1. For int*, GetLoaderModule(int) returns CoreLib
  2. The search iterates CoreLib's AvailableTypeParams via GetAvailableTypeParams(CoreLib)
  3. If the int* TypeDesc was allocated in the debuggee's module (not CoreLib), it won't be found

The native runtime uses ComputeLoaderModule(TypeKey) -> LookupInLoaderModule -> EETypeHashTable::GetValue(TypeKey*) which performs a hash-based lookup in the computed loader module. The native DAC can find the TypeDesc because it traverses the actual runtime type system data structures.

Affected Code

  • cDAC: src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs GetConstructedType method (line ~851)
  • Consumer: src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs CreateValueFromDebugInfo (line ~500)
  • Native reference: src/coreclr/vm/clsload.cpp ClassLoader::LoadConstructedTypeThrowing / LookupInLoaderModule

The TODO is in ClrDataFrame.cs:

// TODO: Implement cross-module TypeDesc search in GetConstructedType
// so that pointer types (ELEMENT_TYPE_PTR) can be resolved even when
// their TypeDesc lives in a different module than the element type.
valueFlags = (uint)ClrDataValueFlag.DEFAULT;

Possible Approaches

  1. Implement ComputeLoaderModule logic in the cDAC to match the native runtime's module computation, ensuring the correct module is searched
  2. Search multiple modules if the loader module search fails (fallback to searching all loaded modules' AvailableTypeParams)
  3. Use hash-based lookup instead of linear scan in GetAvailableTypeParams if the EETypeHashTable structure supports key-based queries from the cDAC

Impact

Pointer variable arguments (int*, char*, etc.) in stack frames will have DEFAULT (0x0) flags instead of IS_POINTER (0x00040000). This affects diagnostic tools that inspect variable types via IXCLRDataValue::GetFlags. Function pointers (delegate*) are not affected because the cDAC maps FNPTR to IntPtr (matching native DAC behavior).

/cc @max-charlamb

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions