Skip to content

Commit

Permalink
Ensure DynamicMethodDefinition can read from DynamicILInfo initialize…
Browse files Browse the repository at this point in the history
…d methods.
  • Loading branch information
Washi1337 committed Oct 8, 2022
1 parent 52f2e6f commit b0b13c8
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 7 deletions.
22 changes: 19 additions & 3 deletions src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,30 @@ private MethodSignature ResolveSig(MethodBase methodBase, ModuleDefinition modul
/// <returns>The method body.</returns>
private static CilMethodBody CreateDynamicMethodBody(MethodDefinition method, object dynamicMethodObj)
{
if (!(method.Module is SerializedModuleDefinition module))
if (method.Module is not SerializedModuleDefinition module)
throw new ArgumentException("Method body should reference a serialized module.");

var result = new CilMethodBody(method);
dynamicMethodObj = DynamicMethodHelper.ResolveDynamicResolver(dynamicMethodObj);

//Get Runtime Fields
byte[] code = FieldReader.ReadField<byte[]>(dynamicMethodObj, "m_code")!;
// Attempt to get the code field.
byte[]? code = FieldReader.ReadField<byte[]>(dynamicMethodObj, "m_code");

// If it is still null, it might still be set using DynamicILInfo::SetCode.
// Find the code stored in the DynamicILInfo if available.
if (code is null
&& FieldReader.TryReadField<MethodBase>(dynamicMethodObj, "m_method", out var methodBase)
&& methodBase is not null
&& FieldReader.TryReadField(methodBase, "m_DynamicILInfo", out object? dynamicILInfo)
&& dynamicILInfo is not null)
{
code = FieldReader.ReadField<byte[]>(dynamicILInfo, "m_code");
}

if (code is null)
throw new InvalidOperationException("Dynamic method does not have a CIL code stream.");

// Get remaining fields.
object scope = FieldReader.ReadField<object>(dynamicMethodObj, "m_scope")!;
var tokenList = FieldReader.ReadField<List<object?>>(scope, "m_tokens")!;
byte[] localSig = FieldReader.ReadField<byte[]>(dynamicMethodObj, "m_localSignature")!;
Expand Down
12 changes: 8 additions & 4 deletions src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private static void InterpretEHInfo(CilMethodBody methodBody, ReferenceImporter
for (int i = 0; i < FieldReader.ReadField<int>(ehInfo, "m_currentCatch"); i++)
{
// Get ExceptionHandlerInfo Field Values
var endFinally = FieldReader.ReadField<int>(ehInfo, "m_endFinally");
int endFinally = FieldReader.ReadField<int>(ehInfo, "m_endFinally");
var instructions = methodBody.Instructions;

var endFinallyLabel = endFinally >= 0
Expand Down Expand Up @@ -155,17 +155,21 @@ public static object ResolveDynamicResolver(object dynamicMethodObj)

if (dynamicMethodObj.GetType().FullName == "System.Reflection.Emit.DynamicMethod")
{
var resolver = FieldReader.ReadField<object>(dynamicMethodObj, "m_resolver");
object? resolver = FieldReader.ReadField<object>(dynamicMethodObj, "m_resolver");
if (resolver != null)
dynamicMethodObj = resolver;
}
//Create Resolver if it does not exist.
if (dynamicMethodObj.GetType().FullName == "System.Reflection.Emit.DynamicMethod")
{
var dynamicResolver = typeof(OpCode).Module.GetTypes()
var dynamicResolver = typeof(OpCode).Module
.GetTypes()
.First(t => t.Name == "DynamicResolver");

var ilGenerator = dynamicMethodObj.GetType().GetRuntimeMethods().First(q => q.Name == "GetILGenerator")
object? ilGenerator = dynamicMethodObj
.GetType()
.GetRuntimeMethods()
.First(q => q.Name == "GetILGenerator")
.Invoke(dynamicMethodObj, null);

//Create instance of dynamicResolver
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
Expand Down Expand Up @@ -72,5 +73,21 @@ public void RtDynamicMethod()
module.CorLibTypeFactory.String,
}, dynamicMethod.CilMethodBody.LocalVariables.Select(v => v.VariableType));
}

[Fact]
public void ReadDynamicMethodInitializedByDynamicILInfo()
{
var method = new DynamicMethod("Test", typeof(void), Type.EmptyTypes);
var info = method.GetDynamicILInfo();
info.SetLocalSignature(new byte[] { 0x7, 0x0 });
info.SetCode(new byte[] {0x2a}, 1);

var contextModule = ModuleDefinition.FromFile(typeof(DynamicMethodDefinitionTest).Assembly.Location);
var definition = new DynamicMethodDefinition(contextModule, method);

Assert.NotNull(definition.CilMethodBody);
var instruction = Assert.Single(definition.CilMethodBody.Instructions);
Assert.Equal(CilOpCodes.Ret, instruction.OpCode);
}
}
}

0 comments on commit b0b13c8

Please sign in to comment.