-
Notifications
You must be signed in to change notification settings - Fork 125
/
DynamicCilOperandResolver.cs
111 lines (93 loc) · 4.5 KB
/
DynamicCilOperandResolver.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
using System;
using System.Collections.Generic;
using System.Reflection;
using AsmResolver.DotNet.Code.Cil;
using AsmResolver.DotNet.Serialized;
using AsmResolver.DotNet.Signatures;
using AsmResolver.IO;
using AsmResolver.PE.DotNet.Cil;
using AsmResolver.PE.DotNet.Metadata.Tables;
namespace AsmResolver.DotNet.Dynamic
{
/// <summary>
/// Provides an implementation of <see cref="ICilOperandResolver"/> that resolves operands based on
/// runtime information.
/// </summary>
public class DynamicCilOperandResolver : PhysicalCilOperandResolver
{
private readonly ModuleReaderContext _readerContext;
private readonly IList<object?> _tokens;
private readonly ReferenceImporter _importer;
/// <inheritdoc />
public DynamicCilOperandResolver(SerializedModuleDefinition contextModule, CilMethodBody methodBody, IList<object?> tokens)
: base(contextModule, methodBody)
{
_tokens = tokens ?? throw new ArgumentNullException(nameof(tokens));
_readerContext = contextModule.ReaderContext;
_importer = contextModule.DefaultImporter;
}
/// <inheritdoc />
public override object? ResolveMember(MetadataToken token)
{
switch (token.Table)
{
case TableIndex.TypeDef:
object? type = _tokens[(int)token.Rid];
if (type is RuntimeTypeHandle runtimeTypeHandle)
return _importer.ImportType(Type.GetTypeFromHandle(runtimeTypeHandle));
break;
case TableIndex.Field:
object? field = _tokens[(int)token.Rid];
if (field is null)
return null;
if (field is RuntimeFieldHandle runtimeFieldHandle)
return _importer.ImportField(FieldInfo.GetFieldFromHandle(runtimeFieldHandle));
if (field.GetType().FullName == "System.Reflection.Emit.GenericFieldInfo")
{
bool result = FieldReader.TryReadField<RuntimeFieldHandle>(field, "m_field", out var mField);
var ctx = FieldReader.ReadField<RuntimeTypeHandle>(field, "m_context");
return _importer.ImportField(FieldInfo.GetFieldFromHandle(result
? mField
: FieldReader.ReadField<RuntimeFieldHandle>(field, "m_fieldHandle"), ctx));
}
break;
case TableIndex.Method:
case TableIndex.MemberRef:
object? obj = _tokens[(int)token.Rid];
if (obj is null)
return null;
if (obj is RuntimeMethodHandle methodHandle)
{
var method = MethodBase.GetMethodFromHandle(methodHandle);
return method is not null
? _importer.ImportMethod(method)
: null;
}
if (obj.GetType().FullName == "System.Reflection.Emit.GenericMethodInfo")
{
var context = FieldReader.ReadField<RuntimeTypeHandle>(obj, "m_context");
bool hasHandle = FieldReader.TryReadField<RuntimeMethodHandle>(obj, "m_method", out var mMethod);
var mHandle = FieldReader.ReadField<RuntimeMethodHandle>(obj, "m_methodHandle");
var method = MethodBase.GetMethodFromHandle(
hasHandle ? mMethod : mHandle,
context);
return method is not null
? _importer.ImportMethod(method)
: null;
}
if (obj.GetType().FullName == "System.Reflection.Emit.VarArgMethod")
return _importer.ImportMethod(FieldReader.ReadField<MethodInfo>(obj, "m_method")!);
break;
case TableIndex.StandAloneSig:
var reader = new BinaryStreamReader((byte[])_tokens[(int)token.Rid]!);
return CallingConventionSignature.FromReader(new BlobReadContext(_readerContext), ref reader);
}
return token;
}
/// <inheritdoc />
public override object? ResolveString(MetadataToken token)
{
return _tokens[(int)token.Rid] as string;
}
}
}