protected override void ProcessAssembly(AssemblyDefinition assembly) { if (!Annotations.HasAction(assembly)) { Annotations.SetAction(assembly, AssemblyAction.Skip); } if (Profile.IsSdkAssembly(assembly) || Profile.IsProductAssembly(assembly)) { return; } bool changed = false; foreach (var type in assembly.MainModule.Types) { if (MightNeedFix(type)) { changed |= FixAbstractMethods(type); } } if (changed) { AssemblyAction action = Annotations.HasAction(assembly) ? Annotations.GetAction(assembly) : AssemblyAction.Skip; if (action == AssemblyAction.Skip || action == AssemblyAction.Copy || action == AssemblyAction.Delete) { Annotations.SetAction(assembly, AssemblyAction.Save); } var td = AbstractMethodErrorConstructor.DeclaringType.Resolve(); Annotations.Mark(td); Annotations.SetPreserve(td, TypePreserve.Nothing); Annotations.AddPreservedMethod(td, AbstractMethodErrorConstructor.Resolve()); } }
void ProcessType(TypeDefinition type) { if (!IsActiveFor(type.Module.Assembly)) { return; } // If we are preserving a Mono.Android interface, // preserve all members on the interface. if (!type.IsInterface) { return; } // Mono.Android interfaces will always inherit IJavaObject if (!type.ImplementsIJavaObject()) { return; } foreach (MethodReference method in type.Methods) { Annotations.AddPreservedMethod(type, method.Resolve()); } }
void MapInterfaceMethodsInTypeHierarchy(TypeDefinition type) { if (!type.HasInterfaces) { return; } foreach (TypeReference @interface in type.Interfaces) { var iface = @interface.Resolve(); if (iface == null || !iface.HasMethods) { continue; } foreach (MethodDefinition method in iface.Methods) { if (TryMatchMethod(type, method) != null) { continue; } var @base = GetBaseMethodInTypeHierarchy(type, method); if (@base == null) { continue; } Annotations.AddPreservedMethod(type, @base); } } }
protected override void ProcessAssembly(AssemblyDefinition assembly) { if (!Annotations.HasAction(assembly)) { Annotations.SetAction(assembly, AssemblyAction.Skip); } if (IsProductOrSdkAssembly(assembly)) { return; } CheckAppDomainUsageUnconditional(assembly, (string msg) => Context.Logger.LogMessage(MessageImportance.High, msg)); if (FixAbstractMethodsUnconditional(assembly)) { Context.SafeReadSymbols(assembly); AssemblyAction action = Annotations.HasAction(assembly) ? Annotations.GetAction(assembly) : AssemblyAction.Skip; if (action == AssemblyAction.Skip || action == AssemblyAction.Copy || action == AssemblyAction.Delete) { Annotations.SetAction(assembly, AssemblyAction.Save); } var td = AbstractMethodErrorConstructor.DeclaringType.Resolve(); Annotations.Mark(td); Annotations.SetPreserve(td, TypePreserve.Nothing); Annotations.AddPreservedMethod(td, AbstractMethodErrorConstructor.Resolve()); } }
void AddPreservedMethod(MethodDefinition target, string methodName) { foreach (MethodDefinition method in target.DeclaringType.Methods) { if (method.Name == methodName) { Annotations.AddPreservedMethod(target, method); } } }
void PreserveConditional(IMetadataTokenProvider provider) { var method = provider as MethodDefinition; if (method == null) { return; } Annotations.AddPreservedMethod(method.DeclaringType, method); }
void MarkDefautConstructor (TypeDefinition type) { if ((type == null) || !type.HasMethods) return; foreach (MethodDefinition ctor in type.Methods) { if (!ctor.IsConstructor || ctor.IsStatic || ctor.HasParameters) continue; Annotations.AddPreservedMethod (type, ctor); } }
void PreserveConditional(IMetadataTokenProvider provider) { var method = provider as MethodDefinition; if (method == null) { // workaround to support (uncommon but valid) conditional fields form [Preserve] PreserveUnconditional(provider); return; } Annotations.AddPreservedMethod(method.DeclaringType, method); }
public override void ProcessType (TypeDefinition type) { // If we are preserving a Mono.Android interface, // preserve all members on the interface. if (!type.IsInterface) return; // Mono.Android interfaces will always inherit IJavaObject if (!type.ImplementsIJavaObject ()) return; foreach (MethodReference method in type.Methods) Annotations.AddPreservedMethod (type, method.Resolve ()); }
void MarkAbstractMethodErrorType() { if (markedAbstractMethodErrorType) { return; } markedAbstractMethodErrorType = true; var td = AbstractMethodErrorConstructor.DeclaringType; Annotations.Mark(td); Annotations.SetPreserve(td, TypePreserve.Nothing); Annotations.AddPreservedMethod(td, AbstractMethodErrorConstructor); }
public void ProcessMethod(MethodDefinition method) { if (method.Name == "MarkedMethod") { Annotations.Mark(method); } foreach (var m in method.DeclaringType.Methods) { if (m.Name == $"PreservedForMethod_{method.Name}") { Annotations.AddPreservedMethod(method, m); } } }
protected override void ProcessMethod(TypeDefinition type, MethodDefinition method, XPathNavigator nav, object customData) { if (Annotations.IsMarked(method)) { Context.LogWarning($"Duplicate preserve of '{method.GetDisplayName ()}' in '{_xmlDocumentLocation}'", 2025, _xmlDocumentLocation); } Annotations.Mark(method, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation)); Annotations.MarkIndirectlyCalledMethod(method); Annotations.SetAction(method, MethodAction.Parse); if (!(bool)customData) { Annotations.AddPreservedMethod(type, method); } }
void MarkMethod(TypeDefinition type, MethodDefinition method, bool required) { if (Annotations.IsMarked(method)) { Context.LogMessage(MessageContainer.CreateWarningMessage($"Duplicate preserve of '{method.FullName}' in '{_xmlDocumentLocation}'", 2025)); } Annotations.Mark(method, new DependencyInfo(DependencyKind.XmlDescriptor, _xmlDocumentLocation)); Annotations.MarkIndirectlyCalledMethod(method); Annotations.SetAction(method, MethodAction.Parse); if (!required) { Annotations.AddPreservedMethod(type, method); } }
void PreserveIntPtrConstructor(TypeDefinition type) { foreach (MethodDefinition constructor in type.GetConstructors()) { if (!constructor.HasParameters) { continue; } if (constructor.Parameters.Count != 1 || !constructor.Parameters [0].ParameterType.Is("System", "IntPtr")) { continue; } Annotations.AddPreservedMethod(type, constructor); break; // only one .ctor can match this } }
void PreserveTypeConverter(TypeDefinition type) { if (!type.HasMethods) { return; } foreach (var ctor in type.Methods.Where(m => m.IsConstructor)) { // We only care about ctors with 0 or 1 params. if (ctor.HasParameters && ctor.Parameters.Count > 1) { continue; } Annotations.AddPreservedMethod(type, ctor); } }
void PreserveExportedMethods(TypeDefinition type) { foreach (var method in type.Methods) { if (!IsExportedMethod(method)) { continue; } // not optimal if "Link all" is used as the override might be removed later if (!IsOverridenInUserCode(method)) { continue; } Annotations.AddPreservedMethod(type, method); } }
void PreserveJSInvokable(MethodDefinition method) { Context.LogDebug($"Preserving `[{js_invokable_attribute_type}]': `{method}' in `{method.DeclaringType.Module.FileName}'."); PreserveType(method.DeclaringType); Annotations.AddPreservedMethod(method.DeclaringType, method); if (method.HasParameters) { foreach (var pd in method.Parameters) { var ptype = BasicBlocks.CecilHelper.Resolve(pd.ParameterType); if (ptype != null) { PreserveType(ptype); Annotations.SetPreserve(ptype, TypePreserve.All); } } } }
void PreserveTypeIfRequested(TypeDefinition type) { var typePreserved = IsTypePreserved(type); if (IsTypePreserved(type)) { MarkAndPreserveAll(type); } else { foreach (var m in type.Methods.Where(IsMethodPreserved)) { Annotations.AddPreservedMethod(type, m); } foreach (var t in type.NestedTypes) { PreserveTypeIfRequested(t); } } }
void ProcessType(TypeDefinition type) { if (type.HasNestedTypes) { foreach (var nested in type.NestedTypes) { ProcessType(nested); } } foreach (var method in type.Methods) { if (method.Name == "PreservedForType") { Annotations.AddPreservedMethod(type, method); } ProcessMethod(method); } }
protected override void ProcessAssembly(AssemblyDefinition assembly) { if (!Annotations.HasAction(assembly)) { Annotations.SetAction(assembly, AssemblyAction.Skip); } bool changed = FixAbstractMethods(assembly); if (changed) { Context.SafeReadSymbols(assembly); AssemblyAction action = Annotations.HasAction(assembly) ? Annotations.GetAction(assembly) : AssemblyAction.Skip; if (action == AssemblyAction.Skip || action == AssemblyAction.Copy || action == AssemblyAction.Delete) { Annotations.SetAction(assembly, AssemblyAction.Save); } var td = AbstractMethodErrorConstructor.DeclaringType.Resolve(); Annotations.Mark(td); Annotations.SetPreserve(td, TypePreserve.Nothing); Annotations.AddPreservedMethod(td, AbstractMethodErrorConstructor.Resolve()); } }
void PreserveMethod(TypeDefinition type, MethodDefinition method) { Annotations.AddPreservedMethod(type, method); }
void AddPreservedMethod(MethodDefinition key, MethodDefinition method) { Annotations.AddPreservedMethod(key, method); }
protected override void Process() { AssemblyDefinition?assembly = LoadAssemblyFile(); if (assembly == null) { return; } var di = new DependencyInfo(DependencyKind.RootAssembly, assembly); var origin = new MessageOrigin(assembly); AssemblyAction action = Context.Annotations.GetAction(assembly); switch (action) { case AssemblyAction.Copy: Annotations.Mark(assembly.MainModule, di, origin); // Mark Step will take care of marking whole assembly return; case AssemblyAction.CopyUsed: case AssemblyAction.Link: break; default: Context.LogError(null, DiagnosticId.RootAssemblyCannotUseAction, assembly.Name.ToString(), action.ToString()); return; } switch (rootMode) { case AssemblyRootMode.Default: if (assembly.MainModule.Kind == ModuleKind.Dll) { goto case AssemblyRootMode.AllMembers; } else { goto case AssemblyRootMode.EntryPoint; } case AssemblyRootMode.EntryPoint: var ep = assembly.MainModule.EntryPoint; if (ep == null) { Context.LogError(null, DiagnosticId.RootAssemblyDoesNotHaveEntryPoint, assembly.Name.ToString()); return; } Annotations.Mark(ep.DeclaringType, di, origin); Annotations.AddPreservedMethod(ep.DeclaringType, ep); break; case AssemblyRootMode.VisibleMembers: var preserve_visible = TypePreserveMembers.Visible; if (MarkInternalsVisibleTo(assembly)) { preserve_visible |= TypePreserveMembers.Internal; } MarkAndPreserve(assembly, preserve_visible); break; case AssemblyRootMode.Library: var preserve_library = TypePreserveMembers.Visible | TypePreserveMembers.Library; if (MarkInternalsVisibleTo(assembly)) { preserve_library |= TypePreserveMembers.Internal; } MarkAndPreserve(assembly, preserve_library); // Assembly root mode wins over any enabled optimization which // could conflict with library rooting behaviour Context.Optimizations.Disable( CodeOptimizations.Sealer | CodeOptimizations.UnusedTypeChecks | CodeOptimizations.UnreachableBodies | CodeOptimizations.UnusedInterfaces | CodeOptimizations.RemoveDescriptors | CodeOptimizations.RemoveLinkAttributes | CodeOptimizations.RemoveSubstitutions | CodeOptimizations.RemoveDynamicDependencyAttribute | CodeOptimizations.OptimizeTypeHierarchyAnnotations, assembly.Name.Name); // Enable EventSource special handling Context.DisableEventSourceSpecialHandling = false; // No metadata trimming Context.MetadataTrimming = MetadataTrimming.None; break; case AssemblyRootMode.AllMembers: Context.Annotations.SetAction(assembly, AssemblyAction.Copy); return; } }
protected override void Process() { AssemblyDefinition assembly = LoadAssemblyFile(); if (assembly == null) { return; } var di = new DependencyInfo(DependencyKind.RootAssembly, assembly); AssemblyAction action = Context.Annotations.GetAction(assembly); switch (action) { case AssemblyAction.Copy: Annotations.Mark(assembly.MainModule, di); // Mark Step will take care of marking whole assembly return; case AssemblyAction.CopyUsed: case AssemblyAction.Link: break; default: Context.LogError($"Root assembly '{assembly.Name}' cannot use action '{action}'", 1035); return; } switch (rootMode) { case AssemblyRootMode.Default: if (assembly.MainModule.Kind == ModuleKind.Dll) { goto case AssemblyRootMode.AllMembers; } else { goto case AssemblyRootMode.EntryPoint; } case AssemblyRootMode.EntryPoint: var ep = assembly.MainModule.EntryPoint; if (ep == null) { Context.LogError($"Root assembly '{assembly.Name}' does not have entry point", 1034); return; } Annotations.Mark(ep.DeclaringType, di); Annotations.AddPreservedMethod(ep.DeclaringType, ep); break; case AssemblyRootMode.VisibleMembers: var preserve_visible = TypePreserveMembers.Visible; if (MarkInternalsVisibleTo(assembly)) { preserve_visible |= TypePreserveMembers.Internal; } MarkAndPreserve(assembly, preserve_visible); break; case AssemblyRootMode.Library: var preserve_library = TypePreserveMembers.Visible | TypePreserveMembers.Library; if (MarkInternalsVisibleTo(assembly)) { preserve_library |= TypePreserveMembers.Internal; } MarkAndPreserve(assembly, preserve_library); // Assembly root mode wins over any enabled optimization which // could conflict with library rooting behaviour Context.Optimizations.Disable( CodeOptimizations.Sealer | CodeOptimizations.UnusedTypeChecks | CodeOptimizations.UnreachableBodies | CodeOptimizations.UnusedInterfaces | CodeOptimizations.RemoveDescriptors | CodeOptimizations.RemoveLinkAttributes | CodeOptimizations.RemoveSubstitutions | CodeOptimizations.RemoveDynamicDependencyAttribute, assembly.Name.Name); // No metadata trimming Context.MetadataTrimming = MetadataTrimming.None; break; case AssemblyRootMode.AllMembers: Context.Annotations.SetAction(assembly, AssemblyAction.Copy); return; } }
void PreserveBlockField(FieldDefinition field) { /* For the following class: * * static internal class SDInnerBlock { * // this field is not preserved by other means, but it must not be linked away * static internal readonly DInnerBlock Handler = Invoke; * * [MonoPInvokeCallback (typeof (DInnerBlock))] * static internal void Invoke (IntPtr block, int magic_number) * { * } * } * * We need to make sure the linker doesn't remove the Handler field * and the Invoke method. Unfortunately there's no programmatic way * to preserve a field dependent upon the preservation of the * containing type, so we have to inject a DynamicDependency * attribute. And since we can't add a DynamicDependency attribute on * the type itself, we add it to the Invoke method. We also need to * preserve the Invoke method (which is done programmatically). Our * generator generates the required attributes, but since we have to * work with existing assemblies, we detect the scenario here as well * and inject the attributes manually if they're not already there. * */ // First make sure we got the right field // The containing type for the field we're looking for is abstract, sealed and nested and contains exactly 1 field. var td = field.DeclaringType; if (!td.IsAbstract || !td.IsSealed || !td.IsNested) { return; } if (td.Fields.Count != 1) { return; } // The containing type is also nested inside ObjCRuntime.Trampolines class) var nestingType = td.DeclaringType; if (!nestingType.Is("ObjCRuntime", "Trampolines")) { return; } // The field itself is a readonly field named 'Handler' if (!field.IsInitOnly) { return; } if (field.Name != "Handler") { return; } // One problem is that we can't add the DynamicDependency attribute to the type, nor the field itself, // so we add it to the Invoke method in the same type. if (!td.HasMethods) { return; } var method = td.Methods.SingleOrDefault(v => { if (v.Name != "Invoke") { return(false); } if (v.Parameters.Count == 0) { return(false); } if (!v.HasCustomAttributes) { return(false); } if (!v.CustomAttributes.Any(v => v.AttributeType.Name == "MonoPInvokeCallbackAttribute")) { return(false); } return(true); }); if (method == null) { return; } // We need to preserve the method, if the type is used (unless it's already preserved) if (!method.CustomAttributes.Any(v => v.AttributeType.Name == "PreserveAttribute")) { Annotations.AddPreservedMethod(method.DeclaringType, method); } // Does the method already have a DynamicDependency attribute? If so, no need to add another one if (method.CustomAttributes.Any(v => v.AttributeType.Is("System.Diagnostics.CodeAnalysis", "DynamicDependencyAttribute"))) { return; } // Create and add the DynamicDependency attribute to the method var ctor = GetConstructorReference(field.DeclaringType.Module.Assembly); var attrib = new CustomAttribute(ctor); attrib.ConstructorArguments.Add(new CustomAttributeArgument(ctor.Parameters [0].ParameterType, "Handler")); method.CustomAttributes.Add(attrib); }