Skip to content

Commit

Permalink
Add ImportAsOperand to fix DynamicMethodBodyReader
Browse files Browse the repository at this point in the history
  • Loading branch information
CreateAndInject committed Apr 5, 2024
1 parent 0b2dc95 commit 04632a7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 29 deletions.
16 changes: 8 additions & 8 deletions src/DotNet/Emit/DynamicMethodBodyReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down
64 changes: 43 additions & 21 deletions src/DotNet/Importer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using dnlib.DotNet.Emit;

namespace dnlib.DotNet {
/// <summary>
Expand Down Expand Up @@ -167,22 +168,22 @@ public Importer(ModuleDef module, ImporterOptions options, GenericParamContext g
}

/// <summary>
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>.
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>.
/// </summary>
/// <param name="type">The type</param>
/// <returns>The imported type or <c>null</c> if <paramref name="type"/> is invalid</returns>
public ITypeDefOrRef Import(Type type) => module.UpdateRowId(ImportAsTypeSig(type).ToTypeDefOrRef());

/// <summary>
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>. See also <see cref="Import(Type)"/>
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>. See also <see cref="Import(Type)"/>
/// </summary>
/// <param name="type">The type</param>
/// <returns></returns>
[Obsolete("Use 'Import(Type)' instead.")]
public ITypeDefOrRef ImportDeclaringType(Type type) => Import(type);

/// <summary>
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>
/// </summary>
/// <param name="type">The type</param>
/// <param name="requiredModifiers">A list of all required modifiers or <c>null</c></param>
Expand Down Expand Up @@ -399,7 +400,7 @@ IResolutionScope CreateScopeReference(Type type) {
}

/// <summary>
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>
/// </summary>
/// <param name="type">The type</param>
/// <param name="requiredModifiers">A list of all required modifiers or <c>null</c></param>
Expand Down Expand Up @@ -437,17 +438,15 @@ TypeSig ImportAsTypeSig(Type type, IList<Type> requiredModifiers, IList<Type> op
static bool IsEmpty<T>(IList<T> list) => list is null || list.Count == 0;

/// <summary>
/// Imports a <see cref="MethodBase"/> as a <see cref="IMethod"/>. This will be either
/// a <see cref="MemberRef"/> or a <see cref="MethodSpec"/>.
/// Imports a <see cref="MethodBase"/> as an <see cref="IMethod"/>.
/// </summary>
/// <param name="methodBase">The method</param>
/// <returns>The imported method or <c>null</c> if <paramref name="methodBase"/> is invalid
/// or if we failed to import the method</returns>
public IMethod Import(MethodBase methodBase) => Import(methodBase, false);

/// <summary>
/// Imports a <see cref="MethodBase"/> as a <see cref="IMethod"/>. This will be either
/// a <see cref="MemberRef"/> or a <see cref="MethodSpec"/>.
/// Imports a <see cref="MethodBase"/> as an <see cref="IMethod"/>.
/// </summary>
/// <param name="methodBase">The method</param>
/// <param name="forceFixSignature">Always verify method signature to make sure the
Expand All @@ -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;

Expand All @@ -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:
Expand All @@ -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;

Expand Down Expand Up @@ -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;
}

Expand All @@ -604,22 +601,24 @@ bool IsThisAssembly(Module module2) {
}

/// <summary>
/// Imports a <see cref="FieldInfo"/> as a <see cref="MemberRef"/>
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/>
/// </summary>
/// <param name="fieldInfo">The field</param>
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
/// or if we failed to import the field</returns>
public IField Import(FieldInfo fieldInfo) => Import(fieldInfo, false);

/// <summary>
/// Imports a <see cref="FieldInfo"/> as a <see cref="MemberRef"/>
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/>
/// </summary>
/// <param name="fieldInfo">The field</param>
/// <param name="forceFixSignature">Always verify field signature to make sure the
/// returned reference matches the metadata in the source assembly</param>
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
/// or if we failed to import the field</returns>
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;
Expand All @@ -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;

Expand Down Expand Up @@ -1190,5 +1189,28 @@ IMemberRefParent Import(IMemberRefParent parent) {

return null;
}

/// <summary>
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/> used for <see cref="Instruction.Operand"/>.
/// </summary>
/// <param name="type">The type</param>
/// <returns>The imported type or <c>null</c> if <paramref name="type"/> is invalid</returns>
public ITypeDefOrRef ImportAsOperand(Type type) => module.UpdateRowId(ImportAsTypeSig(type, null, type.IsGenericType).ToTypeDefOrRef());

/// <summary>
/// Imports a <see cref="MethodBase"/> as an <see cref="IMethod"/> used for <see cref="Instruction.Operand"/>.
/// </summary>
/// <param name="methodBase">The method</param>
/// <returns>The imported method or <c>null</c> if <paramref name="methodBase"/> is invalid
/// or if we failed to import the method</returns>
public IMethod ImportAsOperand(MethodBase methodBase) => ImportInternal(methodBase, false, true);

/// <summary>
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/> used for <see cref="Instruction.Operand"/>.
/// </summary>
/// <param name="fieldInfo">The field</param>
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
/// or if we failed to import the field</returns>
public IField ImportAsOperand(FieldInfo fieldInfo) => ImportInternal(fieldInfo, false, true);
}
}

0 comments on commit 04632a7

Please sign in to comment.