From ee6a2ff1fe165bb1625fa6614c6af47186f2317a Mon Sep 17 00:00:00 2001 From: Radek Doulik Date: Thu, 3 Sep 2020 19:08:54 +0200 Subject: [PATCH] [jnimarshalmethod-gen] Fix type resolution crash The TypeMover was crashing, when we cannot resolve the type during register method optimization. Like this: Value cannot be null. Parameter name: key System.ArgumentNullException: Value cannot be null. Parameter name: key at System.Collections.Generic.Dictionary`2[TKey,TValue].FindEntry (TKey key) [0x00175] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/debug/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:470 at System.Collections.Generic.Dictionary`2[TKey,TValue].ContainsKey (TKey key) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/debug/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/Dictionary.cs:286 at Xamarin.Android.Tools.JniMarshalMethodGenerator.TypeMover.Resolve (Mono.Cecil.TypeReference type) [0x00001] in /Users/rodo/git/xa-clean/external/Java.Interop/tools/jnimarshalmethod-gen/TypeMover.cs:143 at Xamarin.Android.Tools.JniMarshalMethodGenerator.TypeMover.GetActionConstructor (Mono.Cecil.TypeReference type, Mono.Cecil.ModuleDefinition module) [0x00012] in /Users/rodo/git/xa-clean/external/Java.Interop/tools/jnimarshalmethod-gen/TypeMover.cs:335 at Xamarin.Android.Tools.JniMarshalMethodGenerator.TypeMover.AnalyzeAndImprove (Mono.Collections.Generic.Collection`1[T] instructions, Mono.Collections.Generic.Collection`1[T] newInstructions, System.Int32 idx, System.String typeName, System.Int32& skipCount, Mono.Cecil.ModuleDefinition module) [0x003b6] in /Users/rodo/git/xa-clean/external/Java.Interop/tools/jnimarshalmethod-gen/TypeMover.cs:417 The tool was crashing on IL like this: IL_0122: ldstr "Delegate18$1" IL_0127: ldc.i4.1 IL_0128: call [mscorlib]System.Type [mscorlib]System.Type::GetType(string, bool) The fix makes us more error prone. It doesn't fix the source of the problem, which will be fixed elsewhere. --- tools/jnimarshalmethod-gen/TypeMover.cs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tools/jnimarshalmethod-gen/TypeMover.cs b/tools/jnimarshalmethod-gen/TypeMover.cs index 0b64777b2..ba530ec9c 100644 --- a/tools/jnimarshalmethod-gen/TypeMover.cs +++ b/tools/jnimarshalmethod-gen/TypeMover.cs @@ -15,6 +15,7 @@ public class TypeMover AssemblyDefinition Destination { get; } string DestinationPath { get; } Dictionary Types { get; } + DirectoryAssemblyResolver Resolver { get; } MethodReference consoleWriteLine; TypeDefinitionCache cache; @@ -25,10 +26,11 @@ public TypeMover (AssemblyDefinition source, AssemblyDefinition destination, str Destination = destination; DestinationPath = destinationPath; Types = types; + Resolver = resolver; this.cache = cache; if (App.Debug) { - consoleWriteLine = GetSingleParameterMethod (resolver, Destination.MainModule, "mscorlib", "System.Console", "WriteLine", "System.String"); + consoleWriteLine = GetSingleParameterMethod (Destination.MainModule, "mscorlib", "System.Console", "WriteLine", "System.String"); if (consoleWriteLine == null) { App.Warning ("Unable to find System.Console::WriteLine method. Disabling debug injection"); App.Debug = false; @@ -399,6 +401,15 @@ bool AnalyzeAndImprove (Mono.Collections.Generic.Collection instruc return false; delegateType = module.GetType (delegateTypeName); + if (delegateType == null) { + var t = Type.GetType (delegateTypeName); + if (t == null) + return false; + + delegateType = GetType (t.Assembly.GetName ().ToString (), delegateTypeName); + if (delegateType == null) + return false; + } skipCount = 11; customDelegate = true; @@ -515,16 +526,18 @@ MethodDefinition Duplicate (MethodDefinition src, ModuleDefinition module, TypeD return md; } - MethodReference GetSingleParameterMethod (DirectoryAssemblyResolver resolver, ModuleDefinition module, string assemblyName, string typeName, string methodName, string parameterTypeName) + TypeDefinition GetType (string assemblyName, string typeName) { - var assembly = resolver.Resolve (assemblyName); + var assembly = Resolver.Resolve (assemblyName); if (assembly == null) return null; - var typeTD = assembly.MainModule.GetType (typeName); - if (typeTD == null) - return null; + return assembly.MainModule.GetType (typeName); + } + MethodReference GetSingleParameterMethod (ModuleDefinition module, string assemblyName, string typeName, string methodName, string parameterTypeName) + { + var typeTD = GetType (assemblyName, typeName); foreach (var md in typeTD.Methods) if (md.Name == methodName && md.HasParameters && md.Parameters.Count == 1 && md.Parameters [0].ParameterType.FullName == parameterTypeName) return GetUpdatedMethod (md, module);