private static void ProcessApplicationCatalog(ClrHeap heap, ulong appCat, HashSet <ulong> parts) { // It's always an AggregateCatalog ulong innerCatalog = ClrMdHelper.GetObjectAs <ulong>(heap, appCat, FIELD_InnerCatalog); InvokeCatalogHandler(heap, innerCatalog, parts); }
private static string ProcessAttributedPartCreationInfo(ClrHeap heap, ulong partCreationInfo) { ulong creationInfoObj = ClrMdHelper.GetObjectAs <ulong>(heap, partCreationInfo, FIELD_Type); ClrType creationInfoObjType = heap.GetObjectType(creationInfoObj); return(creationInfoObjType.GetRuntimeType(creationInfoObj)?.Name ?? creationInfoObjType.Name); }
private static void ProcessFilteredCatalog(ClrHeap heap, ulong filteredCat, HashSet <ulong> parts) { // It can be any derivation of ComposablePartCatalog ulong innerCatalog = ClrMdHelper.GetObjectAs <ulong>(heap, filteredCat, FIELD_InnerCatalog); InvokeCatalogHandler(heap, innerCatalog, parts); }
private static void ProcessAssemblyCatalog(ClrHeap heap, ulong asmCat, HashSet <ulong> parts) { // It's always a TypeCatalog ulong innerCatalog = ClrMdHelper.GetObjectAs <ulong>(heap, asmCat, FIELD_InnerCatalog); InvokeCatalogHandler(heap, innerCatalog, parts); }
private static void ProcessPrismDefaultsCatalog(ClrHeap heap, ulong prismCat, HashSet <ulong> parts) { // Get all auto-created partdescriptions (ComposablePartDefinition[]) List <ulong> partObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, prismCat, HIERARCHY_PrismDefaultsCatalog_To_ComposablePartDefinitions, 0, TYPE_ComposablePartDefinitionArray); foreach (var partObj in partObjs) { parts.Add(partObj); } }
private static void ProcessAggregateCatalog(ClrHeap heap, ulong aggrCat, HashSet <ulong> parts) { List <ulong> catalogs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, aggrCat, HIERARCHY_AggregateCatalog_To_ComposablePartCatalogs, 0, TYPE_ComposablePartCatalogArray); foreach (var catalog in catalogs) { // It can be any derivation of ComposablePartCatalog InvokeCatalogHandler(heap, catalog, parts); } }
private static void ProcessDirectoryCatalog(ClrHeap heap, ulong dirCat, HashSet <ulong> parts) { var asmCatalogs = ClrMdHelper.GetLastObjectInHierarchyAsKVPs(heap, dirCat, HIERARCHY_DirectoryCatalog_To_AssemblyCatalogs, 0, TYPE_KVP_String_AssemblyCatalog); foreach (var catalog in asmCatalogs) { Console.WriteLine(catalog.key); // It's always an AssemblyCatalog InvokeCatalogHandler(heap, catalog.value, parts); } }
private static void DumpTypes(ClrHeap heap, ulong obj, string type) { var resultItem = new ServiceDescriptionEntry((int)heap.Runtime.DataTarget.ProcessId); // Get ServiceEndpoint[] List <ulong> endpointObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, obj, HIERARCHY_ServiceDescription_To_ServiceEndpoints, 0, TYPE_ServiceEndpointArray); foreach (var endpointObj in endpointObjs) { var epEntry = new ServiceEndpointEntry(); // Get Contract ulong contractObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_ContractType, 0); if (contractObj == 0) { continue; } string contractTypeName = heap.GetObjectType(contractObj).GetRuntimeType(contractObj).Name; epEntry.Contract = contractTypeName; // Get IContractBehavior[] List <ulong> contractBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_ContractBehaviors, 0, TYPE_ContractBehaviorArray); foreach (var contractBehaviorObj in contractBehaviorObjs) { ClrType itemType = heap.GetObjectType(contractBehaviorObj); epEntry.ContractBehaviors.Add(itemType.Name); } // Get OperationDescription[] List <ulong> operationDescObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_OperationDescriptions, 0, TYPE_OperationDescriptionArray); foreach (var operationDescObj in operationDescObjs) { ulong opNameObj = ClrMdHelper.GetLastObjectInHierarchy(heap, operationDescObj, HIERARCHY_OperationDescription_To_Name, 0); string opName = ClrMdHelper.GetObjectAs <string>(heap, opNameObj, FIELD_XmlName); var odEntry = new OperationDescriptionEntry(); odEntry.OperationName = opName; // Get IOperationBehavior[] List <ulong> operationBehavObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, operationDescObj, HIERARCHY_OperationDescription_To_OperationBehaviors, 0, TYPE_OperationBehaviorArray); foreach (var operationBehavObj in operationBehavObjs) { ClrType itemType = heap.GetObjectType(operationBehavObj); odEntry.OperationBehaviors.Add(itemType.Name); } epEntry.ContractOperations.Add(odEntry); } // Get CallbackContract ulong cbcontractObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_CallbackContractType, 0); if (cbcontractObj != 0) { string cbcontractTypeName = heap.GetObjectType(cbcontractObj).GetRuntimeType(cbcontractObj).Name; epEntry.CallbackContract = cbcontractTypeName; } // Get EndpointAddress URI ulong uriObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_Uri, 0); string uri = ClrMdHelper.GetObjectAs <string>(heap, uriObj, FIELD_UriName); epEntry.Uri = uri; // Read binding security information. ulong bindingObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, new [] { "binding" }, 0); ClrType bindingType = heap.GetObjectType(bindingObj); if (bindingType == null) { epEntry.BindingSecurity = new UnknownBindingSecurity(); } else if (bindingType.Name.EndsWith("NetTcpBinding")) { ulong securityObj = ClrMdHelper.GetLastObjectInHierarchy(heap, bindingObj, new[] { "security" }, 0); NetTcpBindingSecurity netTcpBindingSecurity = new NetTcpBindingSecurity(); netTcpBindingSecurity.SecurityMode = ClrMdHelper.GetObjectAs <SecurityMode>(heap, securityObj, FIELD_NetTcpBindingSecurityMode); ulong tcpTransportSecurityObj = ClrMdHelper.GetLastObjectInHierarchy(heap, securityObj, HIERARCHY_NetTcpBindingSecurity_To_TcpTransportSecurity, 0); netTcpBindingSecurity.ClientCredentialType = (TcpClientCredentialType)ClrMdHelper.GetObjectAs <int>(heap, tcpTransportSecurityObj, FIELD_NetTcpBindingClientCredentialType); epEntry.BindingSecurity = netTcpBindingSecurity; } else if (bindingType.Name.EndsWith("NetNamedPipeBinding")) { ulong securityObj = ClrMdHelper.GetLastObjectInHierarchy(heap, bindingObj, new[] { "security" }, 0); NetNamedPipeBindingSecurity netNamedPipeSecurity = new NetNamedPipeBindingSecurity(); netNamedPipeSecurity.SecurityMode = ClrMdHelper.GetObjectAs <NetNamedPipeSecurityMode>(heap, securityObj, FIELD_NetTcpBindingSecurityMode); epEntry.BindingSecurity = netNamedPipeSecurity; } else { epEntry.BindingSecurity = new UnknownBindingSecurity(bindingType.Name); } // Get IEndpointBehavior[] List <ulong> endpBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_EndpointBehaviors, 0, TYPE_EndpointBehaviorArray); foreach (var endpBehaviorObj in endpBehaviorObjs) { ClrType itemType = heap.GetObjectType(endpBehaviorObj); epEntry.EndpointBehaviors.Add(itemType.Name); } resultItem.ServiceEndpoints.Add(epEntry); } // Get IServiceBehavior[] List <ulong> svcBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, obj, HIERARCHY_ServiceDescription_To_ServiceBehaviors, 0, TYPE_ServiceBehaviorArray); foreach (var svcBehaviorObj in svcBehaviorObjs) { ClrType svcBehaviorType = heap.GetObjectType(svcBehaviorObj); resultItem.ServiceBehaviors.Add(svcBehaviorType.Name); } RESULTS.Add(resultItem); }
static void Main(string[] args) { var retCode = ArgParser.Parse(args, new string[0], new string[] { "-pids" }); if (retCode != ErrorCode.Success) { PrintSyntaxAndExit(retCode); } List <ProcessInfo> procInfos; if (ArgParser.SwitchesWithValues.ContainsKey("-pids")) { var pids = ParseAndValidatePids(); procInfos = pids.Select(x => ProcessHelper.GetProcessDetailsByPid(x)).ToList(); } else { procInfos = ProcessHelper.GetProcessDetails(args[0]); } Console.WriteLine($"Number of matching processes: {procInfos.Count}"); Console.WriteLine(); if (procInfos.Any()) { Console.WriteLine($"Data collection started."); Console.WriteLine(); } for (int i = 0; i < procInfos.Count; i++) { int pid = procInfos[i].PID; Console.WriteLine($"Process {i + 1}/{procInfos.Count}"); if (string.IsNullOrWhiteSpace(procInfos[i].Name)) { Console.WriteLine($"WARNING: Process with pid '{pid}' does not exist."); Console.WriteLine(); continue; } Console.WriteLine($"Process: {procInfos[i].Name} ({pid})"); Console.WriteLine($"CmdLine: {procInfos[i].CmdLine}"); var wrapper = ClrMdHelper.AttachToLiveProcess(pid); wrapper.TypesToDump.Add(TYPE_ServiceDescription); wrapper.ClrHeapIsNotWalkableCallback = () => { Console.WriteLine("PID: {0} - Cannot walk the heap!", pid); }; wrapper.ClrObjectOfTypeFoundCallback = DumpTypes; wrapper.Process(); Console.WriteLine(); } if (procInfos.Any()) { Console.WriteLine($"Data collection completed."); Console.WriteLine(); } // Display results foreach (var group in RESULTS.GroupBy(x => x.Pid)) { var proc = procInfos.First(x => x.PID == group.Key); Console.WriteLine($"Displaying data for:"); Console.WriteLine($"\tProcess: {proc.Name} ({proc.PID})"); Console.WriteLine($"\tCmdLine: {proc.CmdLine}"); Console.WriteLine(); int cnt = 0; int cntAll = group.Count(); foreach (var result in group) { Console.WriteLine($"ServiceDescription {++cnt}/{cntAll}"); Console.WriteLine($"----------------------"); Console.WriteLine(); Console.WriteLine("ServiceBehaviors: "); foreach (var svcBehavior in result.ServiceBehaviors) { Console.WriteLine($"\t{svcBehavior}"); } Console.WriteLine(); Console.WriteLine("ServiceEndpoints:"); foreach (var svcEndpoint in result.ServiceEndpoints) { Console.WriteLine($"\t{proc.PID} | {svcEndpoint.Contract} | {svcEndpoint.CallbackContract ?? "<n/a>"} | {svcEndpoint.Uri}"); Console.WriteLine($"\t{svcEndpoint.BindingSecurity}"); if (svcEndpoint.EndpointBehaviors.Any()) { Console.WriteLine(); Console.WriteLine("\tEndpointBehaviors:"); foreach (var endpointbehavior in svcEndpoint.EndpointBehaviors) { Console.WriteLine($"\t\t{endpointbehavior}"); } } if (svcEndpoint.ContractBehaviors.Any()) { Console.WriteLine(); Console.WriteLine("\tContractBehaviors:"); foreach (var contractbehavior in svcEndpoint.ContractBehaviors) { Console.WriteLine($"\t\t{contractbehavior}"); } } if (svcEndpoint.ContractOperations.Any()) { Console.WriteLine(); Console.WriteLine("\tOperations:"); foreach (var operation in svcEndpoint.ContractOperations) { Console.WriteLine($"\t\t{operation.OperationName}"); Console.WriteLine("\t\t\tOperationBehaviors:"); foreach (var opBehavior in operation.OperationBehaviors) { Console.WriteLine($"\t\t\t\t{opBehavior}"); } } } } Console.WriteLine(); } } }
private static string ProcessGenericSpecializationPartCreationInfo(ClrHeap heap, ulong partCreationInfo) { ulong creationInfoObj = ClrMdHelper.GetObjectAs <ulong>(heap, partCreationInfo, FIELD_OriginalPartCreationInfo); return(InvokePartCreationInfoHandler(heap, creationInfoObj)); }
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."); } }
static void Main(string[] args) { var retCode = ArgParser.Parse(args, new string[] { "-h", "-?", "/?" }, new string[] { "-a", "-d", "-pid" }); ValidateArguments(retCode); string switchArg = ArgParser.Switches.FirstOrDefault(); if (switchArg != null) { switch (switchArg) { case "-h": case "-?": case "/?": { PrintSyntaxAndExit(retCode); break; } } } var kvp = ArgParser.SwitchesWithValues.FirstOrDefault(); if (!kvp.Equals(default(KeyValuePair <string, string>))) { switch (kvp.Key) { case "-a": { var assemblies = kvp.Value.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (var assembly in assemblies) { ValidateFile(assembly); } var aggrCat = new AggregateCatalog(assemblies.Select(x => new AssemblyCatalog(x))); var RESULT = new List <ReflectionComposablePart>(); using (var container = new CompositionContainer(aggrCat)) { foreach (var part in container.Catalog.Parts) { var rfc = new ReflectionComposablePart(); rfc.TypeName = part.ToString(); foreach (var import in part.ImportDefinitions) { var impDef = new ImportDefinition(); string[] s = ParseImportDefinition(import.ToString()); impDef.ContractName = s[0].Substring(s[0].IndexOf("\t") + 1); impDef.RequiredTypeIdentity = s[1].Substring(s[1].IndexOf("\t") + 1); rfc.Imports.Add(impDef); } foreach (var export in part.ExportDefinitions) { var expDef = new ExportDefinition(); expDef.ContractName = export.ContractName; expDef.TypeIdentity = (string)export.Metadata[CONST_ExportTypeIdentity]; rfc.Exports.Add(expDef); } RESULT.Add(rfc); } } DgmlHelper.CreateDgml($"{Guid.NewGuid().ToString()}.dgml", RESULT); break; } case "-d": { string dumpFile = kvp.Value; ValidateFile(dumpFile); var wrapper = ClrMdHelper.LoadDumpFile(dumpFile); InitAndStartProcessing(wrapper); break; } case "-pid": { if (int.TryParse(kvp.Value, out int pid)) { var wrapper = ClrMdHelper.AttachToLiveProcess(pid); InitAndStartProcessing(wrapper); } else { Console.WriteLine($"ERROR: Invalid process id."); Environment.Exit(1); } break; } } } }
private static void DumpTypes(ClrHeap heap, ulong obj, string type) { var resultItem = new ServiceDescriptionEntry((int)heap.Runtime.DataTarget.ProcessId); // Get ServiceEndpoint[] List <ulong> endpointObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, obj, HIERARCHY_ServiceDescription_To_ServiceEndpoints, 0, TYPE_ServiceEndpointArray); foreach (var endpointObj in endpointObjs) { var epEntry = new ServiceEndpointEntry(); // Get Contract ulong contractObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_ContractType, 0); string contractTypeName = heap.GetObjectType(contractObj).GetRuntimeType(contractObj).Name; epEntry.Contract = contractTypeName; // Get IContractBehavior[] List <ulong> contractBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_ContractBehaviors, 0, TYPE_ContractBehaviorArray); foreach (var contractBehaviorObj in contractBehaviorObjs) { ClrType itemType = heap.GetObjectType(contractBehaviorObj); epEntry.ContractBehaviors.Add(itemType.Name); } // Get OperationDescription[] List <ulong> operationDescObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_OperationDescriptions, 0, TYPE_OperationDescriptionArray); foreach (var operationDescObj in operationDescObjs) { ulong opNameObj = ClrMdHelper.GetLastObjectInHierarchy(heap, operationDescObj, HIERARCHY_OperationDescription_To_Name, 0); string opName = ClrMdHelper.GetObjectAs <string>(heap, opNameObj, FIELD_XmlName); var odEntry = new OperationDescriptionEntry(); odEntry.OperationName = opName; // Get IOperationBehavior[] List <ulong> operationBehavObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, operationDescObj, HIERARCHY_OperationDescription_To_OperationBehaviors, 0, TYPE_OperationBehaviorArray); foreach (var operationBehavObj in operationBehavObjs) { ClrType itemType = heap.GetObjectType(operationBehavObj); odEntry.OperationBehaviors.Add(itemType.Name); } epEntry.ContractOperations.Add(odEntry); } // Get CallbackContract ulong cbcontractObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_CallbackContractType, 0); if (cbcontractObj != 0) { string cbcontractTypeName = heap.GetObjectType(cbcontractObj).GetRuntimeType(cbcontractObj).Name; epEntry.CallbackContract = cbcontractTypeName; } // Get EndpointAddress URI ulong uriObj = ClrMdHelper.GetLastObjectInHierarchy(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_Uri, 0); string uri = ClrMdHelper.GetObjectAs <string>(heap, uriObj, FIELD_UriName); epEntry.Uri = uri; // Get IEndpointBehavior[] List <ulong> endpBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, endpointObj, HIERARCHY_ServiceEndpoint_To_EndpointBehaviors, 0, TYPE_EndpointBehaviorArray); foreach (var endpBehaviorObj in endpBehaviorObjs) { ClrType itemType = heap.GetObjectType(endpBehaviorObj); epEntry.EndpointBehaviors.Add(itemType.Name); } resultItem.ServiceEndpoints.Add(epEntry); } // Get IServiceBehavior[] List <ulong> svcBehaviorObjs = ClrMdHelper.GetLastObjectInHierarchyAsArray(heap, obj, HIERARCHY_ServiceDescription_To_ServiceBehaviors, 0, TYPE_ServiceBehaviorArray); foreach (var svcBehaviorObj in svcBehaviorObjs) { ClrType svcBehaviorType = heap.GetObjectType(svcBehaviorObj); resultItem.ServiceBehaviors.Add(svcBehaviorType.Name); } RESULTS.Add(resultItem); }