| File: Linker\DependencyRecorderHelper.cs | Web Access |
| Project: src\runtime\src\tools\illink\src\linker\Mono.Linker.csproj (illink) |
// Copyright (c) .NET Foundation and contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Diagnostics; using Mono.Cecil; namespace Mono.Linker { /// <summary> /// Class which implements IDependencyRecorder and writes the dependencies into an DGML file. /// </summary> public class DependencyRecorderHelper { static bool IsAssemblyBound(TypeDefinition td) { do { if (td.IsNestedPrivate || td.IsNestedAssembly || td.IsNestedFamilyAndAssembly) return true; td = td.DeclaringType; } while (td != null); return false; } public static string TokenString(LinkContext context, object? o) { if (o == null) return "N:null"; if (o is TypeReference t) { bool addAssembly = true; var td = context.TryResolve(t); if (td != null) { addAssembly = td.IsNotPublic || IsAssemblyBound(td); t = td; } var addition = addAssembly ? $":{t.Module}" : ""; return $"{((IMetadataTokenProvider)o).MetadataToken.TokenType}:{o}{addition}"; } if (o is IMetadataTokenProvider provider) return provider.MetadataToken.TokenType + ":" + o; return "Other:" + o; } static bool ShouldRecordAssembly(LinkContext context, AssemblyDefinition assembly) { Debug.Assert(context.EnableReducedTracing || context.TraceAssembly != null); if (context.TraceAssembly != null && !context.TraceAssembly.Contains(assembly.Name.Name)) return false; // We were asked to only trace a specific set of assemblies and this is not one of them // We were either asked to trace in general, or to trace this assembly in particular. // Note: with reduced tracing, we may still not trace an assembly if it's not linked. if (context.EnableReducedTracing) { switch (context.Annotations.GetAction(assembly)) { case AssemblyAction.Link: case AssemblyAction.AddBypassNGen: case AssemblyAction.AddBypassNGenUsed: return true; default: return false; } } return true; } public static bool ShouldRecord(LinkContext context, object? source, object target) { if (source == null || target == null) return false; // We use a few hacks to work around MarkStep outputting thousands of edges even // with the above ShouldRecord checks. Ideally we would format these into a meaningful format // however I don't think that is worth the effort at the moment. // Prevent useless logging of attributes like `e="Other:Mono.Cecil.CustomAttribute"`. if (source is CustomAttribute || target is CustomAttribute) return false; // Prevent useless logging of interface implementations like `e="InterfaceImpl:Mono.Cecil.InterfaceImplementation"`. if (source is InterfaceImplementation || target is InterfaceImplementation) return false; if (!ShouldRecord(context, source) && !ShouldRecord(context, target)) { return false; } return true; } public static bool ShouldRecord(LinkContext context, object? o) { // If tracing a specific set of assemblies (TraceAssembly != null), // this takes precedence over the EnableReducedTracing setting. if (!context.EnableReducedTracing && context.TraceAssembly == null) return true; if (o is TypeDefinition t) return ShouldRecordAssembly(context, t.Module.Assembly); if (o is IMemberDefinition m) return ShouldRecordAssembly(context, m.DeclaringType.Module.Assembly); if (o is TypeReference typeRef) { var resolved = context.TryResolve(typeRef); // Err on the side of caution if we can't resolve if (resolved == null) return true; return ShouldRecordAssembly(context, resolved.Module.Assembly); } if (o is MemberReference mRef) { var resolved = mRef.Resolve(); // Err on the side of caution if we can't resolve if (resolved == null) return true; return ShouldRecordAssembly(context, resolved.DeclaringType.Module.Assembly); } if (o is ModuleDefinition module) return ShouldRecordAssembly(context, module.Assembly); if (o is AssemblyDefinition assembly) return ShouldRecordAssembly(context, assembly); if (o is ParameterDefinition parameter) { if (parameter.Method is MethodDefinition parameterMethodDefinition) return ShouldRecordAssembly(context, parameterMethodDefinition.DeclaringType.Module.Assembly); } return true; } } }