microsoft / clrmd

Microsoft.Diagnostics.Runtime is a set of APIs for introspecting processes and dumps.
MIT License
1.05k stars 255 forks source link

CLRMD unable to get values of static fields in default app domain #857

Closed ryanmolden closed 4 years ago

ryanmolden commented 4 years ago

We talked about this awhile back (through email), it looks like SOS has the same issue. For instance:

0:000> !DumpClass /d 05add184 Class Name: System.String mdToken: 02000073 File: C:\WINDOWS\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Parent Class: 059a835c Module: 059a1000 Method Table: 05a2f0d4 Vtable Slots: 1b Total Method Slots: 1d Class Attributes: 102101
Transparency: Transparent NumInstanceFields: 2 NumStaticFields: 1 MT Field Offset Type VT Attr Value Name 05a309e8 4000283 4 System.Int32 1 instance m_stringLength 05a2f88c 4000284 8 System.Char 1 instance m_firstChar 05a2f0d4 4000288 70 System.String 0 shared static Empty

Domain:Value 00bd64c8:NotInit <<

String.Empty is initialized here, I know that with certainty. CLRMD also claims the static Empty field on the string class is non-initialized, or rather it gives back a seemingly random/bogus address that doesn't map to any memory in the heap dump.

I know if SOS is broken here there is a chance CLRMD can't do much, but if you could this would be super helpful, or if you could suggest another way of knowing if the parent of an object is a static field on a type, that would also be helpful.

No dump given here (I can get you one if you need it), mainly because this is a widespread problem on every dump I have looked at.

leculver commented 4 years ago

I confirmed this works today on both the test infrastructure and a provided crash dump of Visual Studio, everything worked as expected. Following up offline.

    [Fact]
    public void StringEmptyTest()
    {
        using DataTarget dt = TestTargets.Types.LoadFullDump();
        using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

        ClrType strType = runtime.Heap.StringType;
        var statics = strType.StaticFields;
        ulong valueSlot = Assert.Single(statics).GetAddress(runtime.AppDomains[0]);
        Assert.NotEqual(0ul, valueSlot);

        ulong address = dt.DataReader.ReadPointer(valueSlot);

        Assert.NotEqual(0ul, address);
        ClrObject obj = runtime.Heap.GetObject(address);
        Assert.True(obj.Type.IsString);

        string strValue = obj.AsString();
        Assert.Equal("", strValue);

        ClrSegment seg = runtime.Heap.GetSegmentByAddress(valueSlot);
        Assert.NotNull(seg);

        ulong prev = seg.GetPreviousObjectAddress(valueSlot);
        Assert.NotEqual(0ul, prev);

        ClrObject staticsArray = runtime.Heap.GetObject(prev);
    }
leculver commented 4 years ago

@ryanmolden Closing this issue. Please let me know if you find a problem.