From 04632a71c5f7f80fea380a080c440ba16ea43825 Mon Sep 17 00:00:00 2001 From: CreateAndInject Date: Fri, 5 Apr 2024 08:03:53 +0800 Subject: [PATCH] Add ImportAsOperand to fix DynamicMethodBodyReader --- src/DotNet/Emit/DynamicMethodBodyReader.cs | 16 +++--- src/DotNet/Importer.cs | 64 +++++++++++++++------- 2 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/DotNet/Emit/DynamicMethodBodyReader.cs b/src/DotNet/Emit/DynamicMethodBodyReader.cs index a90ff326c..f3122deea 100644 --- a/src/DotNet/Emit/DynamicMethodBodyReader.cs +++ b/src/DotNet/Emit/DynamicMethodBodyReader.cs @@ -458,22 +458,22 @@ IMethod ImportMethod(uint rid) { if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != 0) { // Sometimes it's a generic type but obj != `GenericMethodInfo`, so pass in 'default' and the // runtime will try to figure out the declaring type. https://github.com/0xd4d/dnlib/issues/298 - return importer.Import(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj, default)); + return importer.ImportAsOperand(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj, default)); } else - return importer.Import(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj)); + return importer.ImportAsOperand(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj)); } if (obj.GetType().ToString() == "System.Reflection.Emit.GenericMethodInfo") { var context = (RuntimeTypeHandle)gmiContextFieldInfo.Read(obj); var method = SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)gmiMethodHandleFieldInfo.Read(obj), context); - return importer.Import(method); + return importer.ImportAsOperand(method); } if (obj.GetType().ToString() == "System.Reflection.Emit.VarArgMethod") { var method = GetVarArgMethod(obj); if (!(method is DynamicMethod)) - return importer.Import(method); + return importer.ImportAsOperand(method); obj = method; } @@ -506,16 +506,16 @@ IField ImportField(uint rid) { if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != 0) { // Sometimes it's a generic type but obj != `GenericFieldInfo`, so pass in 'default' and the // runtime will try to figure out the declaring type. https://github.com/0xd4d/dnlib/issues/298 - return importer.Import(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj, default)); + return importer.ImportAsOperand(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj, default)); } else - return importer.Import(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj)); + return importer.ImportAsOperand(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj)); } if (obj.GetType().ToString() == "System.Reflection.Emit.GenericFieldInfo") { var context = (RuntimeTypeHandle)gfiContextFieldInfo.Read(obj); var field = SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)gfiFieldHandleFieldInfo.Read(obj), context); - return importer.Import(field); + return importer.ImportAsOperand(field); } return null; @@ -524,7 +524,7 @@ IField ImportField(uint rid) { ITypeDefOrRef ImportType(uint rid) { var obj = Resolve(rid); if (obj is RuntimeTypeHandle) - return importer.Import(Type.GetTypeFromHandle((RuntimeTypeHandle)obj)); + return importer.ImportAsOperand(Type.GetTypeFromHandle((RuntimeTypeHandle)obj)); return null; } diff --git a/src/DotNet/Importer.cs b/src/DotNet/Importer.cs index de37e66b6..f4cff7d82 100644 --- a/src/DotNet/Importer.cs +++ b/src/DotNet/Importer.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Reflection; +using dnlib.DotNet.Emit; namespace dnlib.DotNet { /// @@ -167,14 +168,14 @@ public Importer(ModuleDef module, ImporterOptions options, GenericParamContext g } /// - /// Imports a as a . + /// Imports a as an . /// /// The type /// The imported type or null if is invalid public ITypeDefOrRef Import(Type type) => module.UpdateRowId(ImportAsTypeSig(type).ToTypeDefOrRef()); /// - /// Imports a as a . See also + /// Imports a as an . See also /// /// The type /// @@ -182,7 +183,7 @@ public Importer(ModuleDef module, ImporterOptions options, GenericParamContext g public ITypeDefOrRef ImportDeclaringType(Type type) => Import(type); /// - /// Imports a as a + /// Imports a as an /// /// The type /// A list of all required modifiers or null @@ -399,7 +400,7 @@ IResolutionScope CreateScopeReference(Type type) { } /// - /// Imports a as a + /// Imports a as an /// /// The type /// A list of all required modifiers or null @@ -437,8 +438,7 @@ TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList op static bool IsEmpty(IList list) => list is null || list.Count == 0; /// - /// Imports a as a . This will be either - /// a or a . + /// Imports a as an . /// /// The method /// The imported method or null if is invalid @@ -446,8 +446,7 @@ TypeSig ImportAsTypeSig(Type type, IList requiredModifiers, IList op public IMethod Import(MethodBase methodBase) => Import(methodBase, false); /// - /// Imports a as a . This will be either - /// a or a . + /// Imports a as an . /// /// The method /// Always verify method signature to make sure the @@ -459,9 +458,7 @@ public IMethod Import(MethodBase methodBase, bool forceFixSignature) { return ImportInternal(methodBase, forceFixSignature); } - IMethod ImportInternal(MethodBase methodBase) => ImportInternal(methodBase, false); - - IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) { + IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature, bool asOperand = false) { if (methodBase is null) return null; @@ -484,13 +481,13 @@ IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) { if (methodBase.DeclaringType.GetElementType2() == ElementType.GenericInst) method = module.UpdateRowId(new MemberRefUser(module, methodBase.Name, CreateMethodSig(origMethod), Import(methodBase.DeclaringType))); else - method = ImportInternal(origMethod) as IMethodDefOrRef; + method = ImportInternal(origMethod, forceFixSignature, asOperand) as IMethodDefOrRef; method = TryResolveMethod(method); - if (methodBase.ContainsGenericParameters) + if (!asOperand && methodBase.ContainsGenericParameters) return method; // Declaring type is instantiated but method itself is not - var gim = CreateGenericInstMethodSig(methodBase); + var gim = CreateGenericInstMethodSig(methodBase, asOperand); var methodSpec = module.UpdateRowId(new MethodSpecUser(method, gim)); if (FixSignature && !forceFixSignature) { //TODO: @@ -504,7 +501,7 @@ IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) { parent = GetModuleParent(methodBase.Module); } else - parent = Import(methodBase.DeclaringType); + parent = asOperand ? ImportAsOperand(methodBase.DeclaringType) : Import(methodBase.DeclaringType); if (parent is null) return null; @@ -583,11 +580,11 @@ CallingConvention GetCallingConvention(MethodBase mb) { return cc; } - GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb) { + GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb, bool asOperand) { var genMethodArgs = mb.GetGenericArguments(); var gim = new GenericInstMethodSig(CallingConvention.GenericInst, (uint)genMethodArgs.Length); foreach (var gma in genMethodArgs) - gim.GenericArguments.Add(ImportAsTypeSig(gma)); + gim.GenericArguments.Add(asOperand ? ImportAsTypeSig(gma, null, gma.IsGenericType) : ImportAsTypeSig(gma)); return gim; } @@ -604,7 +601,7 @@ bool IsThisAssembly(Module module2) { } /// - /// Imports a as a + /// Imports a as an /// /// The field /// The imported field or null if is invalid @@ -612,14 +609,16 @@ bool IsThisAssembly(Module module2) { public IField Import(FieldInfo fieldInfo) => Import(fieldInfo, false); /// - /// Imports a as a + /// Imports a as an /// /// The field /// Always verify field signature to make sure the /// returned reference matches the metadata in the source assembly /// The imported field or null if is invalid /// or if we failed to import the field - public IField Import(FieldInfo fieldInfo, bool forceFixSignature) { + public IField Import(FieldInfo fieldInfo, bool forceFixSignature) => ImportInternal(fieldInfo, forceFixSignature, false); + + IField ImportInternal(FieldInfo fieldInfo, bool forceFixSignature, bool asOperand = false) { FixSignature = false; if (fieldInfo is null) return null; @@ -642,7 +641,7 @@ public IField Import(FieldInfo fieldInfo, bool forceFixSignature) { parent = GetModuleParent(fieldInfo.Module); } else - parent = Import(fieldInfo.DeclaringType); + parent = asOperand ? ImportAsOperand(fieldInfo.DeclaringType) : Import(fieldInfo.DeclaringType); if (parent is null) return null; @@ -1190,5 +1189,28 @@ IMemberRefParent Import(IMemberRefParent parent) { return null; } + + /// + /// Imports a as an used for . + /// + /// The type + /// The imported type or null if is invalid + public ITypeDefOrRef ImportAsOperand(Type type) => module.UpdateRowId(ImportAsTypeSig(type, null, type.IsGenericType).ToTypeDefOrRef()); + + /// + /// Imports a as an used for . + /// + /// The method + /// The imported method or null if is invalid + /// or if we failed to import the method + public IMethod ImportAsOperand(MethodBase methodBase) => ImportInternal(methodBase, false, true); + + /// + /// Imports a as an used for . + /// + /// The field + /// The imported field or null if is invalid + /// or if we failed to import the field + public IField ImportAsOperand(FieldInfo fieldInfo) => ImportInternal(fieldInfo, false, true); } }