Skip to content

Commit a6643c4

Browse files
Add ImportAsOperand to fix DynamicMethodBodyReader
1 parent 0b2dc95 commit a6643c4

File tree

2 files changed

+52
-30
lines changed

2 files changed

+52
-30
lines changed

src/DotNet/Emit/DynamicMethodBodyReader.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -458,22 +458,22 @@ IMethod ImportMethod(uint rid) {
458458
if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != 0) {
459459
// Sometimes it's a generic type but obj != `GenericMethodInfo`, so pass in 'default' and the
460460
// runtime will try to figure out the declaring type. https://github.com/0xd4d/dnlib/issues/298
461-
return importer.Import(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj, default));
461+
return importer.ImportAsOperand(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj, default));
462462
}
463463
else
464-
return importer.Import(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj));
464+
return importer.ImportAsOperand(SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)obj));
465465
}
466466

467467
if (obj.GetType().ToString() == "System.Reflection.Emit.GenericMethodInfo") {
468468
var context = (RuntimeTypeHandle)gmiContextFieldInfo.Read(obj);
469469
var method = SR.MethodBase.GetMethodFromHandle((RuntimeMethodHandle)gmiMethodHandleFieldInfo.Read(obj), context);
470-
return importer.Import(method);
470+
return importer.ImportAsOperand(method);
471471
}
472472

473473
if (obj.GetType().ToString() == "System.Reflection.Emit.VarArgMethod") {
474474
var method = GetVarArgMethod(obj);
475475
if (!(method is DynamicMethod))
476-
return importer.Import(method);
476+
return importer.ImportAsOperand(method);
477477
obj = method;
478478
}
479479

@@ -506,16 +506,16 @@ IField ImportField(uint rid) {
506506
if ((options & DynamicMethodBodyReaderOptions.UnknownDeclaringType) != 0) {
507507
// Sometimes it's a generic type but obj != `GenericFieldInfo`, so pass in 'default' and the
508508
// runtime will try to figure out the declaring type. https://github.com/0xd4d/dnlib/issues/298
509-
return importer.Import(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj, default));
509+
return importer.ImportAsOperand(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj, default));
510510
}
511511
else
512-
return importer.Import(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj));
512+
return importer.ImportAsOperand(SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)obj));
513513
}
514514

515515
if (obj.GetType().ToString() == "System.Reflection.Emit.GenericFieldInfo") {
516516
var context = (RuntimeTypeHandle)gfiContextFieldInfo.Read(obj);
517517
var field = SR.FieldInfo.GetFieldFromHandle((RuntimeFieldHandle)gfiFieldHandleFieldInfo.Read(obj), context);
518-
return importer.Import(field);
518+
return importer.ImportAsOperand(field);
519519
}
520520

521521
return null;
@@ -524,7 +524,7 @@ IField ImportField(uint rid) {
524524
ITypeDefOrRef ImportType(uint rid) {
525525
var obj = Resolve(rid);
526526
if (obj is RuntimeTypeHandle)
527-
return importer.Import(Type.GetTypeFromHandle((RuntimeTypeHandle)obj));
527+
return importer.ImportAsOperand(Type.GetTypeFromHandle((RuntimeTypeHandle)obj));
528528

529529
return null;
530530
}

src/DotNet/Importer.cs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System;
44
using System.Collections.Generic;
55
using System.Reflection;
6+
using dnlib.DotNet.Emit;
67

78
namespace dnlib.DotNet {
89
/// <summary>
@@ -167,22 +168,22 @@ public Importer(ModuleDef module, ImporterOptions options, GenericParamContext g
167168
}
168169

169170
/// <summary>
170-
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>.
171+
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>.
171172
/// </summary>
172173
/// <param name="type">The type</param>
173174
/// <returns>The imported type or <c>null</c> if <paramref name="type"/> is invalid</returns>
174175
public ITypeDefOrRef Import(Type type) => module.UpdateRowId(ImportAsTypeSig(type).ToTypeDefOrRef());
175176

176177
/// <summary>
177-
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>. See also <see cref="Import(Type)"/>
178+
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>. See also <see cref="Import(Type)"/>
178179
/// </summary>
179180
/// <param name="type">The type</param>
180181
/// <returns></returns>
181182
[Obsolete("Use 'Import(Type)' instead.")]
182183
public ITypeDefOrRef ImportDeclaringType(Type type) => Import(type);
183184

184185
/// <summary>
185-
/// Imports a <see cref="Type"/> as a <see cref="ITypeDefOrRef"/>
186+
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/>
186187
/// </summary>
187188
/// <param name="type">The type</param>
188189
/// <param name="requiredModifiers">A list of all required modifiers or <c>null</c></param>
@@ -399,7 +400,7 @@ IResolutionScope CreateScopeReference(Type type) {
399400
}
400401

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

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

448448
/// <summary>
449-
/// Imports a <see cref="MethodBase"/> as a <see cref="IMethod"/>. This will be either
450-
/// a <see cref="MemberRef"/> or a <see cref="MethodSpec"/>.
449+
/// Imports a <see cref="MethodBase"/> as an <see cref="IMethod"/>.
451450
/// </summary>
452451
/// <param name="methodBase">The method</param>
453452
/// <param name="forceFixSignature">Always verify method signature to make sure the
@@ -459,9 +458,7 @@ public IMethod Import(MethodBase methodBase, bool forceFixSignature) {
459458
return ImportInternal(methodBase, forceFixSignature);
460459
}
461460

462-
IMethod ImportInternal(MethodBase methodBase) => ImportInternal(methodBase, false);
463-
464-
IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) {
461+
IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature, bool asOperand = false) {
465462
if (methodBase is null)
466463
return null;
467464

@@ -484,13 +481,13 @@ IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) {
484481
if (methodBase.DeclaringType.GetElementType2() == ElementType.GenericInst)
485482
method = module.UpdateRowId(new MemberRefUser(module, methodBase.Name, CreateMethodSig(origMethod), Import(methodBase.DeclaringType)));
486483
else
487-
method = ImportInternal(origMethod) as IMethodDefOrRef;
484+
method = ImportInternal(origMethod, forceFixSignature, asOperand) as IMethodDefOrRef;
488485

489486
method = TryResolveMethod(method);
490-
if (methodBase.ContainsGenericParameters)
487+
if (!asOperand && methodBase.ContainsGenericParameters)
491488
return method; // Declaring type is instantiated but method itself is not
492489

493-
var gim = CreateGenericInstMethodSig(methodBase);
490+
var gim = CreateGenericInstMethodSig(methodBase, asOperand);
494491
var methodSpec = module.UpdateRowId(new MethodSpecUser(method, gim));
495492
if (FixSignature && !forceFixSignature) {
496493
//TODO:
@@ -504,7 +501,7 @@ IMethod ImportInternal(MethodBase methodBase, bool forceFixSignature) {
504501
parent = GetModuleParent(methodBase.Module);
505502
}
506503
else
507-
parent = Import(methodBase.DeclaringType);
504+
parent = asOperand ? ImportAsOperand(methodBase.DeclaringType) : Import(methodBase.DeclaringType);
508505
if (parent is null)
509506
return null;
510507

@@ -583,11 +580,11 @@ CallingConvention GetCallingConvention(MethodBase mb) {
583580
return cc;
584581
}
585582

586-
GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb) {
583+
GenericInstMethodSig CreateGenericInstMethodSig(MethodBase mb, bool asOperand) {
587584
var genMethodArgs = mb.GetGenericArguments();
588585
var gim = new GenericInstMethodSig(CallingConvention.GenericInst, (uint)genMethodArgs.Length);
589586
foreach (var gma in genMethodArgs)
590-
gim.GenericArguments.Add(ImportAsTypeSig(gma));
587+
gim.GenericArguments.Add(asOperand ? ImportAsTypeSig(gma, null, gma.IsGenericType) : ImportAsTypeSig(gma));
591588
return gim;
592589
}
593590

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

606603
/// <summary>
607-
/// Imports a <see cref="FieldInfo"/> as a <see cref="MemberRef"/>
604+
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/>
608605
/// </summary>
609606
/// <param name="fieldInfo">The field</param>
610607
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
611608
/// or if we failed to import the field</returns>
612609
public IField Import(FieldInfo fieldInfo) => Import(fieldInfo, false);
613610

614611
/// <summary>
615-
/// Imports a <see cref="FieldInfo"/> as a <see cref="MemberRef"/>
612+
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/>
616613
/// </summary>
617614
/// <param name="fieldInfo">The field</param>
618615
/// <param name="forceFixSignature">Always verify field signature to make sure the
619616
/// returned reference matches the metadata in the source assembly</param>
620617
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
621618
/// or if we failed to import the field</returns>
622-
public IField Import(FieldInfo fieldInfo, bool forceFixSignature) {
619+
public IField Import(FieldInfo fieldInfo, bool forceFixSignature) => ImportInternal(fieldInfo, forceFixSignature, false);
620+
621+
IField ImportInternal(FieldInfo fieldInfo, bool forceFixSignature, bool asOperand = false) {
623622
FixSignature = false;
624623
if (fieldInfo is null)
625624
return null;
@@ -642,7 +641,7 @@ public IField Import(FieldInfo fieldInfo, bool forceFixSignature) {
642641
parent = GetModuleParent(fieldInfo.Module);
643642
}
644643
else
645-
parent = Import(fieldInfo.DeclaringType);
644+
parent = asOperand ? ImportAsOperand(fieldInfo.DeclaringType) : Import(fieldInfo.DeclaringType);
646645
if (parent is null)
647646
return null;
648647

@@ -656,7 +655,7 @@ public IField Import(FieldInfo fieldInfo, bool forceFixSignature) {
656655
origField = fieldInfo;
657656
}
658657

659-
var fieldSig = new FieldSig(ImportAsTypeSig(origField.FieldType,
658+
var fieldSig = new FieldSig(ImportAsTypeSig(origField.FieldType,
660659
origField.GetRequiredCustomModifiers(), origField.GetOptionalCustomModifiers(), origField.DeclaringType));
661660
var fieldRef = module.UpdateRowId(new MemberRefUser(module, fieldInfo.Name, fieldSig, parent));
662661

@@ -1190,5 +1189,28 @@ IMemberRefParent Import(IMemberRefParent parent) {
11901189

11911190
return null;
11921191
}
1192+
1193+
/// <summary>
1194+
/// Imports a <see cref="Type"/> as an <see cref="ITypeDefOrRef"/> used for <see cref="Instruction.Operand"/>.
1195+
/// </summary>
1196+
/// <param name="type">The type</param>
1197+
/// <returns>The imported type or <c>null</c> if <paramref name="type"/> is invalid</returns>
1198+
public ITypeDefOrRef ImportAsOperand(Type type) => module.UpdateRowId(ImportAsTypeSig(type, null, type.IsGenericType).ToTypeDefOrRef());
1199+
1200+
/// <summary>
1201+
/// Imports a <see cref="MethodBase"/> as an <see cref="IMethod"/> used for <see cref="Instruction.Operand"/>.
1202+
/// </summary>
1203+
/// <param name="methodBase">The method</param>
1204+
/// <returns>The imported method or <c>null</c> if <paramref name="methodBase"/> is invalid
1205+
/// or if we failed to import the method</returns>
1206+
public IMethod ImportAsOperand(MethodBase methodBase) => ImportInternal(methodBase, false, true);
1207+
1208+
/// <summary>
1209+
/// Imports a <see cref="FieldInfo"/> as an <see cref="IField"/> used for <see cref="Instruction.Operand"/>.
1210+
/// </summary>
1211+
/// <param name="fieldInfo">The field</param>
1212+
/// <returns>The imported field or <c>null</c> if <paramref name="fieldInfo"/> is invalid
1213+
/// or if we failed to import the field</returns>
1214+
public IField ImportAsOperand(FieldInfo fieldInfo) => ImportInternal(fieldInfo, false, true);
11931215
}
11941216
}

0 commit comments

Comments
 (0)