public override void Execute() { var configOptions = new WeaverConfigOptions(Config); var config = new WeaverConfig(configOptions, ModuleDefinition); var context = new ModuleWeavingContext(ModuleDefinition, config); foreach (var type in ModuleDefinition.GetTypes()) { foreach (var method in type.Methods) { try { if (!MethodWeaver.NeedsProcessing(context, method)) { continue; } _log.Debug($"Processing: {method.FullName}"); new MethodWeaver(context, method).Process(); } catch (WeavingException ex) { AddError(ex.Message, ex.SequencePoint); InvalidateMethod(method, ex.Message); } } if (type.IsInlineILTypeUsageDeep(context)) { AddError($"Reference to InlineIL found in type {type.FullName}. InlineIL should not be referenced in attributes/constraints, as its assembly reference will be removed.", null); } } RemoveLibReference(context); }
static bool DoCheck(TypeReference typeRef, ModuleWeavingContext ctx) { switch (typeRef) { case GenericInstanceType t: return(t.ElementType.IsInlineILTypeUsage(ctx) || t.GenericParameters.Any(i => i.IsInlineILTypeUsage(ctx)) || t.GenericArguments.Any(i => i.IsInlineILTypeUsage(ctx))); case GenericParameter t: return(t.HasConstraints && t.Constraints.Any(c => c.IsInlineILTypeUsage(ctx)) || t.HasCustomAttributes && t.CustomAttributes.Any(i => i.IsInlineILTypeUsage(ctx))); case IModifierType t: return(t.ElementType.IsInlineILTypeUsage(ctx) || t.ModifierType.IsInlineILTypeUsage(ctx)); case FunctionPointerType t: return(((IMethodSignature)t).IsInlineILTypeUsage(ctx)); default: return(typeRef.Scope?.MetadataScopeType == MetadataScopeType.AssemblyNameReference && typeRef.Scope.Name == "InlineIL"); } }
private void RemoveLibReference(ModuleWeavingContext context) { var libRef = ModuleDefinition.AssemblyReferences.FirstOrDefault(i => i.IsInlineILAssembly()); if (libRef == null) { return; } var importScopes = new HashSet <ImportDebugInformation>(); foreach (var method in ModuleDefinition.GetTypes().SelectMany(t => t.Methods)) { foreach (var scope in method.DebugInformation.GetScopes()) { ProcessScope(scope); } } ModuleDefinition.AssemblyReferences.Remove(libRef); var copyLocalFilesToRemove = new HashSet <string>(StringComparer.OrdinalIgnoreCase) { libRef.Name + ".dll", libRef.Name + ".xml", libRef.Name + ".pdb" // We don't ship this, but future-proof that ;) }; ReferenceCopyLocalPaths.RemoveAll(i => copyLocalFilesToRemove.Contains(Path.GetFileName(i))); _log.Debug("Removed reference to InlineIL"); void ProcessScope(ScopeDebugInformation scope) { ProcessImportScope(scope.Import); if (scope.HasScopes) { foreach (var childScope in scope.Scopes) { ProcessScope(childScope); } } } void ProcessImportScope(ImportDebugInformation importScope) { if (importScope == null || !importScopes.Add(importScope)) { return; } importScope.Targets.RemoveWhere(t => t.AssemblyReference.IsInlineILAssembly() || t.Type.IsInlineILTypeUsage(context)); ProcessImportScope(importScope.Parent); } }
public MethodWeaver(ModuleWeavingContext context, MethodDefinition method, ILogger log) { _context = context; _method = method; _il = new WeaverILProcessor(_method); _sequencePoints = new SequencePointMapper(_method, context.Config); _log = new MethodWeaverLogger(log, _method); _labels = new LabelMapper(_il, _log); _consumer = new ArgumentConsumer(_il); }
public void SingleMethod() { var assemblyPath = FixtureHelper.IsolateAssembly <StandardAssemblyToProcessReference>(); var type = typeof(MethodRefTestCases); var methodName = nameof(MethodRefTestCases.ReturnMethodHandle); using var module = ModuleDefinition.ReadModule(assemblyPath); var weavingContext = new ModuleWeavingContext(module, new WeaverConfig(null, module)); var typeDef = module.GetTypes().Single(i => i.FullName == type.FullName); var methodDef = typeDef.Methods.Single(i => i.Name == methodName); new MethodWeaver(weavingContext, methodDef, NoOpLogger.Instance).Process(); }
public static bool IsInlineILTypeUsage(this TypeReference?type, ModuleWeavingContext context) { if (type == null) { return(false); } if (context.LibUsageTypeCache.TryGetValue(type, out var result)) { return(result); } context.LibUsageTypeCache[type] = false; result = DoCheck(type, context); context.LibUsageTypeCache[type] = result; return(result);
private static bool HasLibReference(ModuleWeavingContext context, MethodDefinition method, out Instruction?refInstruction) { refInstruction = null; if (method.IsInlineILTypeUsage(context)) { return(true); } if (!method.HasBody) { return(false); } if (method.Body.HasVariables && method.Body.Variables.Any(i => i.VariableType.IsInlineILTypeUsage(context))) { return(true); } foreach (var instruction in method.Body.Instructions) { refInstruction = instruction; switch (instruction.Operand) { case MethodReference methodRef when methodRef.IsInlineILTypeUsage(context): case TypeReference typeRef when typeRef.IsInlineILTypeUsage(context): case FieldReference fieldRef when fieldRef.IsInlineILTypeUsage(context): case CallSite callSite when callSite.IsInlineILTypeUsage(context): return(true); } } refInstruction = null; return(false); }
public static bool NeedsProcessing(ModuleWeavingContext context, MethodDefinition method) => HasLibReference(context, method, out _);