Skip to content

Commit 1818a74

Browse files
authored
[cDAC] Fix stale Continuation MT bug (#129109)
_continuationMethodTablePointer and _continuationSingletonEEClassPointer are not filled on startup, but on the first creation of a Continuation without metadata. Therefore, on a live target we may read a null MT if we only read upon contract creation. Update this such that if these are still null, we try again to read them.
1 parent 9350750 commit 1818a74

2 files changed

Lines changed: 59 additions & 13 deletions

File tree

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ internal partial struct RuntimeTypeSystem_1 : IRuntimeTypeSystem
1919
private readonly Target _target;
2020
private readonly TargetPointer _freeObjectMethodTablePointer;
2121
private readonly TargetPointer _objectMethodTablePointer;
22-
private readonly TargetPointer _continuationMethodTablePointer;
23-
private readonly TargetPointer _continuationSingletonEEClassPointer;
22+
private TargetPointer _continuationMethodTablePointer;
23+
private TargetPointer _continuationSingletonEEClassPointer;
2424
private readonly TargetPointer _multicastDelegateMethodTablePointer;
2525
private readonly ulong _methodDescAlignment;
2626
private readonly TypeValidation _typeValidation;
@@ -436,7 +436,29 @@ internal RuntimeTypeSystem_1(Target target)
436436

437437
internal TargetPointer FreeObjectMethodTablePointer => _freeObjectMethodTablePointer;
438438
internal TargetPointer ObjectMethodTablePointer => _objectMethodTablePointer;
439-
internal TargetPointer ContinuationMethodTablePointer => _continuationMethodTablePointer;
439+
internal TargetPointer ContinuationMethodTablePointer
440+
{
441+
get
442+
{
443+
if (_continuationMethodTablePointer != TargetPointer.Null)
444+
return _continuationMethodTablePointer;
445+
_continuationMethodTablePointer = _target.ReadPointer(
446+
_target.ReadGlobalPointer(Constants.Globals.ContinuationMethodTable));
447+
return _continuationMethodTablePointer;
448+
}
449+
}
450+
451+
internal TargetPointer ContinuationSingletonEEClassPointer
452+
{
453+
get
454+
{
455+
if (_continuationSingletonEEClassPointer != TargetPointer.Null)
456+
return _continuationSingletonEEClassPointer;
457+
_continuationSingletonEEClassPointer = _target.ReadPointer(
458+
_target.ReadGlobalPointer(Constants.Globals.ContinuationSingletonEEClass));
459+
return _continuationSingletonEEClassPointer;
460+
}
461+
}
440462

441463
internal ulong MethodDescAlignment => _methodDescAlignment;
442464

@@ -571,10 +593,10 @@ public bool IsObjRef(TypeHandle typeHandle)
571593
public bool ContainsGCPointers(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers;
572594
public bool RequiresAlign8(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.RequiresAlign8;
573595
public bool IsContinuationWithoutMetadata(TypeHandle typeHandle) => typeHandle.IsMethodTable()
574-
&& _continuationMethodTablePointer != TargetPointer.Null
575-
&& _methodTables[typeHandle.Address].ParentMethodTable == _continuationMethodTablePointer
576-
&& _continuationSingletonEEClassPointer != TargetPointer.Null
577-
&& GetClassPointer(typeHandle) == _continuationSingletonEEClassPointer;
596+
&& ContinuationMethodTablePointer != TargetPointer.Null
597+
&& _methodTables[typeHandle.Address].ParentMethodTable == ContinuationMethodTablePointer
598+
&& ContinuationSingletonEEClassPointer != TargetPointer.Null
599+
&& GetClassPointer(typeHandle) == ContinuationSingletonEEClassPointer;
578600

579601
IEnumerable<(uint Offset, uint Size)> IRuntimeTypeSystem.GetGCDescSeries(TypeHandle typeHandle, uint numComponents)
580602
{

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/RuntimeTypeSystemHelpers/TypeValidation.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ namespace Microsoft.Diagnostics.DataContractReader.RuntimeTypeSystemHelpers;
99
internal sealed class TypeValidation
1010
{
1111
private readonly Target _target;
12-
private readonly TargetPointer _continuationMethodTablePointer;
13-
private readonly TargetPointer _continuationSingletonEEClassPointer;
12+
private TargetPointer _continuationMethodTablePointer;
13+
private TargetPointer _continuationSingletonEEClassPointer;
1414

1515
internal TypeValidation(Target target, TargetPointer continuationMethodTablePointer, TargetPointer continuationSingletonEEClassPointer)
1616
{
@@ -19,6 +19,30 @@ internal TypeValidation(Target target, TargetPointer continuationMethodTablePoin
1919
_continuationSingletonEEClassPointer = continuationSingletonEEClassPointer;
2020
}
2121

22+
private TargetPointer ContinuationMethodTablePointer
23+
{
24+
get
25+
{
26+
if (_continuationMethodTablePointer != TargetPointer.Null)
27+
return _continuationMethodTablePointer;
28+
_continuationMethodTablePointer = _target.ReadPointer(
29+
_target.ReadGlobalPointer(Constants.Globals.ContinuationMethodTable));
30+
return _continuationMethodTablePointer;
31+
}
32+
}
33+
34+
private TargetPointer ContinuationSingletonEEClassPointer
35+
{
36+
get
37+
{
38+
if (_continuationSingletonEEClassPointer != TargetPointer.Null)
39+
return _continuationSingletonEEClassPointer;
40+
_continuationSingletonEEClassPointer = _target.ReadPointer(
41+
_target.ReadGlobalPointer(Constants.Globals.ContinuationSingletonEEClass));
42+
return _continuationSingletonEEClassPointer;
43+
}
44+
}
45+
2246
// This doesn't need as many properties as MethodTable because we don't want to be operating on
2347
// a NonValidatedMethodTable for too long
2448
internal struct NonValidatedMethodTable
@@ -235,10 +259,10 @@ private TargetPointer GetClassThrowing(NonValidatedMethodTable methodTable)
235259
// duplicate the check using the raw ParentMethodTable read from target memory.
236260
private bool IsContinuationWithoutMetadata(NonValidatedMethodTable methodTable)
237261
{
238-
return _continuationMethodTablePointer != TargetPointer.Null
239-
&& methodTable.ParentMethodTable == _continuationMethodTablePointer
240-
&& _continuationSingletonEEClassPointer != TargetPointer.Null
241-
&& GetClassThrowing(methodTable) == _continuationSingletonEEClassPointer;
262+
return ContinuationMethodTablePointer != TargetPointer.Null
263+
&& methodTable.ParentMethodTable == ContinuationMethodTablePointer
264+
&& ContinuationSingletonEEClassPointer != TargetPointer.Null
265+
&& GetClassThrowing(methodTable) == ContinuationSingletonEEClassPointer;
242266
}
243267

244268
internal bool TryValidateMethodTablePointer(TargetPointer methodTablePointer)

0 commit comments

Comments
 (0)