A number of times when debugging managed code I've realised an object is ultimitely rooted in a static member but I've not been sure how to determine where in the application that static is declared. Today I finally got round to figuring out a way to do it.
Take this program as an example:
using System; using System.Collections; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { class Program { static ArrayList _fruit = new ArrayList(); static void Main(string[] args) { _fruit.Add(new Fruit("Apple")); _fruit.Add(new Fruit("Bannana")); _fruit.Add(new Fruit("Cherry")); Console.ReadLine(); } } class Fruit { public Fruit(string Name) { _name = Name; } private string _name = ""; } }
0:003> .loadby sos mscorwks
0:003> .load clr10\sos
0:003> !dumpheap -type Fruit Address MT Size 02651c28 01cc30c4 12 02651c68 01cc30c4 12 02651c74 01cc30c4 12 total 3 objects Statistics: MT Count TotalSize Class Name 01cc30c4 3 36 ConsoleApplication1.Fruit Total 3 objects 0:003> !gcroot 02651c28 Note: Roots found on stacks may be false positives. Run "!help gcroot" for more info. Scan Thread 0 OSTHread c8c ESP:2cf438:Root:02651ba4(System.Collections.ArrayList)-> 02651c48(System.Object[])-> 02651c28(ConsoleApplication1.Fruit) ESP:2cf450:Root:02651ba4(System.Collections.ArrayList)-> 02651c48(System.Object[]) ESP:2cf464:Root:02651ba4(System.Collections.ArrayList)-> 02651c48(System.Object[]) Scan Thread 2 OSTHread d98 DOMAIN(002D9968):HANDLE(Pinned):1ca13fc:Root:03651010(System.Object[])-> 02651ba4(System.Collections.ArrayList)
0:003> !do 03651010 Name: System.Object[] MethodTable: 79124228 EEClass: 7912479c Size: 4096(0x1000) bytes Array: Rank 1, Number of elements 1020, Type CLASS Element Type: System.Object Fields: None
0:003> s-d 03651010 L?0x1000 02651ba4 03651ec4 02651ba4 00000000 00000000 00000000 ..e.............
0:003> s-d 0 L?0xbfffffff 03651ec4 01cc2fc8 03651ec4 00000500 01cc3008 11000001 ..e......0...... 02060094 03651ec4 e13989e8 c35e9077 01cc1880 ..e...9.w.^.....
0:003> !u 01cc2fc8 Unmanaged code 01cc2fc8 c41e les ebx,[esi] 01cc2fca 650300 add eax,gs:[eax] 01cc2fcd 0500000830 add eax,0x30080000 01cc2fd2 cc int 3 01cc2fd3 0101 add [ecx],eax 01cc2fd5 0000 add [eax],al 01cc2fd7 1100 adc [eax],eax 01cc2fd9 0000 add [eax],al 01cc2fdb 90 nop 01cc2fdc 0000 add [eax],al
0:003> !u 02060094 Normal JIT generated code ConsoleApplication1.Program..cctor() Begin 02060070, size 30 02060070 56 push esi 02060071 833dc82dcc0100 cmp dword ptr [01cc2dc8],0x0 02060078 7405 jz 0206007f 0206007a e87f220378 call mscorwks!JIT_DbgIsJustMyCode (7a0922fe) 0206007f b9b0361079 mov ecx,0x791036b0 (MT: System.Collections.ArrayList) 02060084 e8931fc5ff call 01cb201c (JitHelp: CORINFO_HELP_NEWSFAST) 02060089 8bf0 mov esi,eax 0206008b 8bce mov ecx,esi *** WARNING: Unable to verify checksum for mscorlib.ni.dll 0206008d e8ce1d3077 call mscorlib_ni+0x2a1e60 (79361e60) (System.Collections.ArrayList..ctor(), mdToken: 0600153c) 02060092 8d15c41e6503 lea edx,[03651ec4] 02060098 e88939e177 call mscorwks!JIT_Writeable_Thunks_Buf+0xf6 (79e73a26) (mscorwks!JIT_Writeable_Thunks_Buf) 0206009d 90 nop 0206009e 5e pop esi 0206009f c3 ret