microsoft / clrmd

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

Impossible to get an element with ClrArray GetObjectValue() + it crashes when the item is a value type #786

Closed chrisnas closed 4 years ago

chrisnas commented 4 years ago

The ClrArray type should provide methods to get the item at a given index, being a reference type or a value type. As of today, only the former is possible (but broken) with GetObjectValue().

The ClrArray.GetObjectValue() implementation is supposed to return a ClrObject (i.e. the item type must be a reference type) but the test is on the array type itself

public ClrObject GetObjectValue(int index)
{
    // should be Type.ComponentType.IsObjectReference
    //              V V V
    if (!Type.IsObjectReference)
        throw new InvalidOperationException($"{Type} does not contain object references.");

    ulong address = GetValue<UIntPtr>(index).ToUInt64();
    return Type.Heap.GetObject(address);
}

The second issue is related to the way the address of the item is retrieved via GetValue. Since this method is checking the size of T (here UIntPtr) against the size of the item instance, the check throws:

int elementSize = Type.ComponentSize;
if (sizeof(T) != elementSize)
    throw new ArgumentException(...)

I have implemented and tested a solution by adding the following 2 methods to ClrArray

ulong GetItemAddress(int index);
ClrValueType GetStructValue(int index);

and the GetObjectValue() implementation has been updated to use GetItemAddress()

If this looks good, I will create a PR.

CONTEXT: I'm currently adding ClrMD-based commands to dotnet-dump and I would like to dump a ConcurrentQueue and list each item in the queue with the command to type to get more details on a given item

image

@kevingosse: would it be enough for your own scenarios?

leculver commented 4 years ago

I think this was resolved in NextTurn's checkin. Please let me know if that's not the case. (New build should be out in a day or two containing this fix, it's not in NuGet yet.)

chrisnas commented 4 years ago

It works like a charm for reference types @leculver :^) However, I don't see a way to get a ClrValueType from an array element with today's code. I will write a pull request soon for a ClrArray.GetStructValue(int index) method (the code works fine in my tests - int and custom value type)

leculver commented 4 years ago

However, I don't see a way to get a ClrValueType from an array element with today's code.

This was one of the last bits of work that I didn't finish before ClrMD 2.0 went out the door. I just haven't circled back to it yet. If you have time to submit a pull request that'd be great, but otherwise it'll have to wait until I can get around to it. I have a lot of projects going on that are taking up a lot of time. =/

I've reactivated this to track it.