private static ReflectionComposablePart ProcessReflectionComposablePartDefinition(ClrHeap heap, ulong part) { var rcp = new ReflectionComposablePart(); ulong creationInfoObj = ClrMdHelper.GetLastObjectInHierarchy(heap, part, HIERARCHY_ReflectionComposablePartDefinition_To_AttributedPartCreationInfo, 0); ClrType creationInfoObjType = heap.GetObjectType(creationInfoObj); rcp.TypeName = creationInfoObjType.GetRuntimeType(creationInfoObj)?.Name ?? creationInfoObjType.Name; var importObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, part, HIERARCHY_CreationInfo_To_ImportArray, 0, TYPE_ImportDefinitionArray); foreach (var importDef in importObjs) { var importDefType = heap.GetObjectType(importDef); var prodInfoDef = importDefType.GetFieldByName(ProductImportDefinition); ulong imDef; if (prodInfoDef != null) { imDef = (ulong)prodInfoDef.GetValue(importDef); } else { imDef = importDef; } string contract = ClrMdHelper.GetObjectAs <string>(heap, imDef, FIELD_ContractName); string typeId = ClrMdHelper.GetObjectAs <string>(heap, imDef, FIELD_RequiredTypeIdentity); rcp.Imports.Add(new ImportDefinition() { ContractName = contract, RequiredTypeIdentity = typeId }); } // Get ExportDefinition[] ulong exportArrayObj = ClrMdHelper.GetObjectAs <ulong>(heap, part, FIELD_Exports); if (exportArrayObj != 0) { List <ulong> exportObjs = ClrMdHelper.GetArrayItems(heap.GetObjectType(exportArrayObj), exportArrayObj); foreach (var exportDef in exportObjs) { ulong attrExpDef = ClrMdHelper.GetObjectAs <ulong>(heap, exportDef, FIELD_ExportDefinition); string contract = ClrMdHelper.GetObjectAs <string>(heap, attrExpDef, FIELD_ContractName); ulong typeObj = ClrMdHelper.GetObjectAs <ulong>(heap, attrExpDef, FIELD_TypeIdentityType); string typename = null; if (typeObj == 0) { Console.WriteLine($"WARNING: Special export was found with no type identity (contract: {contract})"); typename = rcp.TypeName; } else { ClrType typeObjType = heap.GetObjectType(typeObj); typename = typeObjType.GetRuntimeType(typeObj)?.Name ?? typeObjType.Name; } rcp.Exports.Add(new ExportDefinition() { ContractName = contract, TypeIdentity = typename }); } } return(rcp); }
private static void DumpTypes(ClrHeap heap, ulong obj, string type) { Console.WriteLine($"Dumping CompositionContainer @{obj:X}"); // Check if custom ExportProviders are present ulong providersFieldValue = ClrMdHelper.GetObjectAs <ulong>(heap, obj, FIELD_Providers); if (providersFieldValue != 0) { ulong providerArrayObj = ClrMdHelper.GetObjectAs <ulong>(heap, providersFieldValue, FIELD_List); List <ulong> providerObjs = ClrMdHelper.GetArrayItems(heap.GetObjectType(providerArrayObj), providerArrayObj); if (providerObjs.Count > 0) { Console.WriteLine("WARNING: custom ExportProvider(s) were found:"); } foreach (ulong provider in providerObjs) { ClrType itemType = heap.GetObjectType(provider); Console.WriteLine($"\t{itemType.Name}"); } } var RESULT = new Dictionary <string, ReflectionComposablePart>(); // Check if there exists a PartExportProvider ulong partExportProvider = ClrMdHelper.GetObjectAs <ulong>(heap, obj, FIELD_PartExportProvider); if (partExportProvider != 0) { // Get ComposablePart[] from ComposablePartExportProvider List <ulong> composableParts = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, partExportProvider, HIERARCHY_PartExportProvider_To_ComposableParts, 0, TYPE_ComposablePart); foreach (var composablePart in composableParts) { string composablePartTypeName = heap.GetObjectType(composablePart).Name; if (composablePartTypeName == TYPE_ReflectionComposablePart) { var rcpDef = ClrMdHelper.GetObjectAs <ulong>(heap, composablePart, FIELD_Definition); var rcp = ProcessReflectionComposablePartDefinition(heap, rcpDef); rcp.IsCreated = true; MergeResults(RESULT, rcp); } else if (composablePartTypeName == TYPE_SingleExportComposablePart) { ulong export = ClrMdHelper.GetObjectAs <ulong>(heap, composablePart, FIELD_Export); ulong exportedValue = ClrMdHelper.GetObjectAs <ulong>(heap, export, FIELD_ExportedValue); string exportedValueTypeName = exportedValue != 0 ? heap.GetObjectType(exportedValue).Name : null; bool isCached = exportedValue != 0 && exportedValueTypeName != typeof(object).FullName; if (!isCached) { ulong realExportedValue = ClrMdHelper.GetLastObjectInHierarchy(heap, export, HIERARCHY_Func_To_ExportedValue, 0); if (realExportedValue != 0) { exportedValueTypeName = heap.GetObjectType(realExportedValue).Name; } } var exportDefinition = ClrMdHelper.GetObjectAs <ulong>(heap, export, FIELD_Definition); string contract = ClrMdHelper.GetObjectAs <string>(heap, exportDefinition, FIELD_ContractName); var metadata = ClrMdHelper.GetLastObjectInHierarchyAsKVPs(heap, exportDefinition, HIERARCHY_ExportDefinition_To_Metadata, 0, TYPE_KVP_String_Object); string typeId = ""; foreach (var entry in metadata) { if (ClrMdHelper.GetStringContents(heap, entry.key) == CONST_ExportTypeIdentity) { typeId = ClrMdHelper.GetStringContents(heap, entry.value); break; } } var rcp = new ReflectionComposablePart(); rcp.TypeName = exportedValueTypeName ?? typeId; rcp.IsCreated = true; rcp.Exports.Add(new ExportDefinition() { ContractName = contract, TypeIdentity = typeId }); MergeResults(RESULT, rcp); } else { Console.WriteLine($"WARNING: Unsupported ComposablePart was found: {composablePartTypeName}"); } } } // Check if there exists a CatalogExportProvider ulong catalogExProvider = ClrMdHelper.GetObjectAs <ulong>(heap, obj, FIELD_CatalogExportProvider); if (catalogExProvider != 0) { ulong catalogFieldValue = ClrMdHelper.GetObjectAs <ulong>(heap, catalogExProvider, FIELD_Catalog); HashSet <ulong> parts = new HashSet <ulong>(); InvokeCatalogHandler(heap, catalogFieldValue, parts); foreach (var part in parts) { var rcp = ProcessReflectionComposablePartDefinition(heap, part); MergeResults(RESULT, rcp); } Console.WriteLine($"{RESULT.Count} parts were found: "); foreach (var part in RESULT.Keys) { Console.WriteLine($"\t{part}"); } Console.WriteLine(); // Get activated auto-created parts var activePartObjs = ClrMdHelper.GetLastObjectInHierarchyAsKVPs(heap, catalogExProvider, HIERARCHY_CatalogExportProvider_To_Activated, 0, TYPE_ComposablePartDefinitionArray2); var activatedPartNames = new HashSet <string>(); foreach (var activePart in activePartObjs) { ulong partCreationInfo = ClrMdHelper.GetObjectAs <ulong>(heap, activePart.key, FIELD_CreationInfo); string partType = InvokePartCreationInfoHandler(heap, partCreationInfo); activatedPartNames.Add(partType); } foreach (var rcp in RESULT) { if (activatedPartNames.Contains(rcp.Key)) { rcp.Value.IsCreated = true; } } DgmlHelper.CreateDgml($"{obj:X}.dgml", RESULT.Select(x => x.Value)); } else { Console.WriteLine("INFO: No CatalogExportProvider was found."); } }