2

I would like to run !refs command against each address from following command

!dumpgen 2 -type System.DateTime[]

How this could be done.I know a loop can be created as follows

.foreach (myvar {!dumpgen 2 -type System.DateTime[]}) 

But how can I access object address that could be used in loop with !refs?

whoami
  • 1,689
  • 3
  • 22
  • 45

1 Answers1

3

!dumpgen does not have a -short argument like !dumpheap has and I'd really like to see a simpler answer than this one.

Approach 1: dump a generation manually

  1. Get the addresses of the heap

    0:003> !eeheap -gc
    Number of GC Heaps: 1
    generation 0 starts at 0x026f1018
    generation 1 starts at 0x026f100c
    generation 2 starts at 0x026f1000
    
  2. Use the addresses to limit the output to the generation you want:

    !dumpheap -type X <start> <end>
    
  3. Use the -short parameter on !dumpheap, which outputs the address only. This address of an object can then be processed by other commands.

Also note: using -type may result in other types as well. Better use the method table with -mt since only that guarantees the uniqueness of types. Use !name2ee if you don't get that from elsewhere.

A complete session could look like this:

0:003> !dumpheap -stat
total 345 objects
Statistics:
      MT    Count    TotalSize Class Name
53ab421c        1           12 System.Text.DecoderExceptionFallback
[...]
53ab0d48      135         6640 System.String
53a84518       26         9452 System.Object[]
Total 345 objects

0:003> !eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x026f1018
generation 1 starts at 0x026f100c
generation 2 starts at 0x026f1000
[...]

0:003> !name2ee *!System.String
Module: 53841000 (mscorlib.dll)
Token: 0x02000024
MethodTable: 53ab0d48
[...]

0:003> !dumpheap -short -mt 53ab0d48 0x026f1000 0x026f100c

(Ok, all my strings seem to be in generation 0, damn :-)

0:003> .foreach (addr {!dumpheap -short -mt 53ab0d48 0x026f1018}) {!refs ${addr}}

Disadvantage: you need to do that for all GC heaps separately. There could be several of them.

Approach 2: decide for the generation on each single object

Another ugly solution is to

  1. Dump all object addresses (!dumpheap -short and -type or -mt)
  2. Query the generation of each object via !gcgen
  3. Depending on the generation, execute a command

Here's how to do it (formatted for readability, put it all into one line):

.foreach (addr {!dumpheap -short -mt 53ab0d48}) {
    .foreach /pS 1 (gen {!gcgen ${addr}}) { 
        .if ($scmp("${gen}","2")==0) {
            !refs ${addr}
        }
    }
}

where 53ab0d48 is the method table of the type you're looking for and "2" is the generation you want. /pS 1 skips the word "Gen" in the output of !gcgen.

Disadvantage: might be slow since it works on all objects.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222