@@ -35,7 +35,7 @@ public class ClrDump : IClrDump
35
35
36
36
public List < ClrHandle > Handles => Runtime . EnumerateHandles ( ) . ToList ( ) ;
37
37
public List < ulong > FinalizerQueueObjectAddresses => Runtime . EnumerateFinalizerQueueObjectAddresses ( ) . ToList ( ) ;
38
- public IEnumerable < IGrouping < ClrType , ulong > > FinalizerQueueObjectAddressesByType => Runtime . EnumerateFinalizerQueueObjectAddresses ( ) . GroupBy ( address => GetObjectType ( address ) ) ;
38
+ public IEnumerable < IGrouping < ClrType , ulong > > FinalizerQueueObjectAddressesByType => Runtime . EnumerateFinalizerQueueObjectAddresses ( ) . GroupBy ( address => GetObjectType ( address ) ) ;
39
39
public IList < ClrThread > Threads => Runtime . Threads ;
40
40
public ClrThreadPool ThreadPool => Runtime . GetThreadPool ( ) ;
41
41
public List < ClrType > AllTypes => Heap . EnumerateTypes ( ) . ToList ( ) ;
@@ -57,7 +57,7 @@ public Dictionary<int, ThreadProperty> ThreadProperties
57
57
Dictionary < int , ThreadProperty > threadProperties ;
58
58
private readonly SingleThreadWorker worker ;
59
59
private ClrDumpCache cache ;
60
-
60
+
61
61
public ClrDump ( DataTarget target , string dumpPath , MessageBus msgBus )
62
62
{
63
63
Id = n ++ ;
@@ -94,7 +94,7 @@ private void InitRuntime()
94
94
95
95
public List < ClrType > GetTypes ( )
96
96
{
97
- List < ClrType > t = worker . Eval ( ( ) => t = AllTypes ) ;
97
+ List < ClrType > t = worker . Eval ( ( ) => t = AllTypes ) ;
98
98
return t ;
99
99
}
100
100
@@ -110,7 +110,7 @@ internal void Dispose()
110
110
logger . Debug ( "Cache dispose" ) ;
111
111
cache . Dispose ( ) ;
112
112
logger . Debug ( "Runtime.DataTarget.Dispose" ) ;
113
- Run ( ( ) => Runtime ? . DataTarget ? . Dispose ( ) ) ;
113
+ Run ( ( ) => Runtime ? . DataTarget ? . Dispose ( ) ) ;
114
114
logger . Debug ( "Worker.Dispose" ) ;
115
115
worker . Dispose ( ) ;
116
116
}
@@ -205,7 +205,7 @@ private object GetSimpleValueImpl(ulong address, ClrType type)
205
205
var value = SimpleValueHelper . GetSimpleValue ( address , type , false ) ;
206
206
return value ;
207
207
}
208
-
208
+
209
209
return address ;
210
210
}
211
211
@@ -225,28 +225,30 @@ public object GetFieldValue(ulong address, ClrType type, ClrInstanceField field)
225
225
return obj ;
226
226
}
227
227
228
- internal Dictionary < string , ClrType > GetFieldNames ( ClrType type )
228
+ internal List < FieldInfo > GetFieldInfos ( ClrType type )
229
229
{
230
- Dictionary < string , ClrType > fieldNames = Eval ( ( ) => GetFieldNamesImpl ( type ) ) ;
230
+ List < FieldInfo > fieldNames = Eval ( ( ) => GetFieldNamesImpl ( type ) ) ;
231
231
return fieldNames ;
232
232
}
233
233
234
- private Dictionary < string , ClrType > GetFieldNamesImpl ( ClrType type )
234
+ private List < FieldInfo > GetFieldNamesImpl ( ClrType type )
235
235
{
236
- var fieldNames = type . Fields . ToDictionary ( f => f . Name , f => f . Type ) ;
237
- if ( type . IsInterface )
236
+ var fieldNames = type . Fields . Select ( f => new FieldInfo ( f . Name , f . Type ) ) . ToList ( ) ;
237
+ if ( type . IsInterface || type . IsAbstract )
238
238
{
239
- var properties = type . Methods . Where ( meth => meth . Name . StartsWith ( "get_" ) && meth . IsVirtual ) ;
240
- foreach ( var meth in properties )
239
+ foreach ( var someType in Heap . EnumerateTypes ( ) )
241
240
{
242
- var propName = meth . Name . Substring ( "get_" . Length ) ;
243
- // BUG: this is not the real type of the field !
244
- // TODO: get the return type from the method
245
- fieldNames [ propName ] = meth . Type ;
241
+ if ( type . IsInterface && someType . Interfaces . Any ( interf => interf . Name == type . Name ) )
242
+ {
243
+ fieldNames . AddRange ( GetFieldNamesImpl ( someType ) ) ;
244
+ }
245
+ if ( type . IsAbstract && someType . BaseType == type )
246
+ {
247
+ fieldNames . AddRange ( GetFieldNamesImpl ( someType ) ) ;
248
+ }
246
249
}
247
-
248
250
}
249
- return fieldNames ;
251
+ return fieldNames . Distinct ( ) . ToList ( ) ;
250
252
}
251
253
252
254
public object GetFieldValueImpl ( ulong address , ClrType type , List < ClrInstanceField > fields )
@@ -257,7 +259,7 @@ public object GetFieldValueImpl(ulong address, ClrType type, List<ClrInstanceFie
257
259
{
258
260
var field = fields [ i ] ;
259
261
obj = obj [ field ] ;
260
- if ( obj . IsNull )
262
+ if ( obj . IsNull )
261
263
{
262
264
return null ;
263
265
}
@@ -272,7 +274,13 @@ public object GetFieldValueImpl(ulong address, ClrType type, List<string> fieldN
272
274
for ( int i = 0 ; i < fieldNames . Count ; i ++ )
273
275
{
274
276
var fieldName = fieldNames [ i ] ;
275
- obj = obj [ fieldName ] ;
277
+ ClrInstanceField field = obj . GetField ( fieldName ) ;
278
+ if ( field == null )
279
+ {
280
+ return null ;
281
+ }
282
+
283
+ obj = obj [ field ] ;
276
284
if ( obj . IsNull )
277
285
{
278
286
return null ;
@@ -313,7 +321,7 @@ public bool HasReferers(ulong address)
313
321
314
322
public int CountReferers ( ulong address )
315
323
{
316
- var count = cache . CountReferers ( address ) ;
324
+ var count = cache . CountReferers ( address ) ;
317
325
return count ;
318
326
}
319
327
@@ -384,15 +392,15 @@ public ClrMethod GetMethodByHandle(ulong methodDescriptorPtr)
384
392
}
385
393
386
394
// Find the field in instance at address that references refAddress
387
- public string GetFieldNameReference ( ulong refAddress , ulong address , bool prefixWithType = false )
395
+ public string GetFieldNameReference ( ulong refAddress , ulong address , bool prefixWithType = false )
388
396
{
389
397
return Eval ( ( ) => GetFieldNameReferenceImpl ( refAddress , address , prefixWithType ) ) ;
390
398
}
391
399
392
400
public string GetFieldNameReferenceImpl ( ulong refAddress , ulong address , bool prefixWithType )
393
- {
401
+ {
394
402
ClrType type = GetObjectTypeImpl ( address ) ;
395
- if ( type == null )
403
+ if ( type == null )
396
404
{
397
405
return "Unknown" ;
398
406
}
@@ -504,16 +512,16 @@ public List<ClrRoot> GetClrRoots()
504
512
505
513
public bool HasField ( ClrType clrType )
506
514
{
507
- if ( clrType . IsPrimitive )
515
+ if ( clrType . IsPrimitive )
508
516
{
509
517
return false ;
510
518
}
511
- if ( clrType . Fields . Any ( ) )
519
+ if ( clrType . Fields . Any ( ) )
512
520
{
513
521
return true ;
514
522
}
515
523
516
- if ( clrType . IsInterface && clrType . Methods . Any ( meth => meth . Name . StartsWith ( "get_" ) ) )
524
+ if ( clrType . IsInterface && clrType . Methods . Any ( meth => meth . Name . StartsWith ( "get_" ) ) )
517
525
{
518
526
return true ;
519
527
}
@@ -531,4 +539,27 @@ public class ThreadProperty
531
539
public int Priority { get ; set ; }
532
540
public int ManagedId { get ; set ; }
533
541
}
542
+
543
+ public class FieldInfo : IEquatable < FieldInfo >
544
+ {
545
+ public string Name { get ; }
546
+ public ClrType FieldType { get ; }
547
+ public FieldInfo ( string name , ClrType fieldType )
548
+ {
549
+ Name = name ;
550
+ FieldType = fieldType ;
551
+ }
552
+ public bool Equals ( FieldInfo fieldInfo )
553
+ {
554
+ return fieldInfo . Name == Name && fieldInfo . FieldType . Name == FieldType . Name ;
555
+ }
556
+ public override bool Equals ( object o )
557
+ {
558
+ return ( ( IEquatable < FieldInfo > ) this ) . Equals ( ( FieldInfo ) o ) ;
559
+ }
560
+ public override int GetHashCode ( )
561
+ {
562
+ return Name . GetHashCode ( ) * 37 + FieldType . Name . GetHashCode ( ) ;
563
+ }
564
+ }
534
565
}
0 commit comments