Skip to content

Commit a3815d1

Browse files
authored
[cdac] Lazily read global string/object method table pointers (#109093)
When the [c]DAC is created, the string and object method tables may not be loaded and the global pointers set yet. We don't actually need them at creation of `SOSDacImpl`, so but we were always reading those global pointers and expecting them to be set. Switch reading of the string and object method table pointers to be lazy,
1 parent 10ee2b1 commit a3815d1

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ internal sealed unsafe partial class SOSDacImpl
2727
ISOSDacInterface11, ISOSDacInterface12, ISOSDacInterface13, ISOSDacInterface14, ISOSDacInterface15
2828
{
2929
private readonly Target _target;
30-
private readonly TargetPointer _stringMethodTable;
31-
private readonly TargetPointer _objectMethodTable;
30+
31+
// When this class is created, the runtime may not have loaded the string and object method tables and set the global pointers.
32+
// They should be set when actually requested via a DAC API, so we lazily read the global pointers.
33+
private readonly Lazy<TargetPointer> _stringMethodTable;
34+
private readonly Lazy<TargetPointer> _objectMethodTable;
3235

3336
private readonly ISOSDacInterface? _legacyImpl;
3437
private readonly ISOSDacInterface2? _legacyImpl2;
@@ -52,8 +55,11 @@ internal sealed unsafe partial class SOSDacImpl
5255
public SOSDacImpl(Target target, object? legacyObj)
5356
{
5457
_target = target;
55-
_stringMethodTable = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.StringMethodTable));
56-
_objectMethodTable = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.ObjectMethodTable));
58+
_stringMethodTable = new Lazy<TargetPointer>(
59+
() => _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.StringMethodTable)));
60+
61+
_objectMethodTable = new Lazy<TargetPointer>(
62+
() => _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.ObjectMethodTable)));
5763

5864
// Get all the interfaces for delegating to the legacy DAC
5965
if (legacyObj is not null)
@@ -619,14 +625,14 @@ int ISOSDacInterface.GetObjectData(ulong objAddr, DacpObjectData* data)
619625
ulong numComponentsOffset = (ulong)_target.GetTypeInfo(DataType.Array).Fields[Data.Array.FieldNames.NumComponents].Offset;
620626
data->Size += _target.Read<uint>(objAddr + numComponentsOffset) * data->dwComponentSize;
621627
}
622-
else if (mt == _stringMethodTable)
628+
else if (mt == _stringMethodTable.Value)
623629
{
624630
data->ObjectType = DacpObjectType.OBJ_STRING;
625631

626632
// Update the size to include the string character components
627633
data->Size += (uint)objectContract.GetStringValue(objAddr).Length * data->dwComponentSize;
628634
}
629-
else if (mt == _objectMethodTable)
635+
else if (mt == _objectMethodTable.Value)
630636
{
631637
data->ObjectType = DacpObjectType.OBJ_OBJECT;
632638
}
@@ -967,8 +973,8 @@ int ISOSDacInterface.GetUsefulGlobals(DacpUsefulGlobalsData* data)
967973
{
968974
data->ArrayMethodTable = _target.ReadPointer(
969975
_target.ReadGlobalPointer(Constants.Globals.ObjectArrayMethodTable));
970-
data->StringMethodTable = _stringMethodTable;
971-
data->ObjectMethodTable = _objectMethodTable;
976+
data->StringMethodTable = _stringMethodTable.Value;
977+
data->ObjectMethodTable = _objectMethodTable.Value;
972978
data->ExceptionMethodTable = _target.ReadPointer(
973979
_target.ReadGlobalPointer(Constants.Globals.ExceptionMethodTable));
974980
data->FreeMethodTable = _target.ReadPointer(

0 commit comments

Comments
 (0)