diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs index 4349d9006..3cb1512b3 100644 --- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs +++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodDefinition.cs @@ -69,14 +69,30 @@ private MethodSignature ResolveSig(MethodBase methodBase, ModuleDefinition modul /// The method body. 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(dynamicMethodObj, "m_code")!; + // Attempt to get the code field. + byte[]? code = FieldReader.ReadField(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(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(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(dynamicMethodObj, "m_scope")!; var tokenList = FieldReader.ReadField>(scope, "m_tokens")!; byte[] localSig = FieldReader.ReadField(dynamicMethodObj, "m_localSignature")!; diff --git a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs index 118fd49ac..eb6ce85f2 100644 --- a/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs +++ b/src/AsmResolver.DotNet.Dynamic/DynamicMethodHelper.cs @@ -108,7 +108,7 @@ private static void InterpretEHInfo(CilMethodBody methodBody, ReferenceImporter for (int i = 0; i < FieldReader.ReadField(ehInfo, "m_currentCatch"); i++) { // Get ExceptionHandlerInfo Field Values - var endFinally = FieldReader.ReadField(ehInfo, "m_endFinally"); + int endFinally = FieldReader.ReadField(ehInfo, "m_endFinally"); var instructions = methodBody.Instructions; var endFinallyLabel = endFinally >= 0 @@ -155,17 +155,21 @@ public static object ResolveDynamicResolver(object dynamicMethodObj) if (dynamicMethodObj.GetType().FullName == "System.Reflection.Emit.DynamicMethod") { - var resolver = FieldReader.ReadField(dynamicMethodObj, "m_resolver"); + object? resolver = FieldReader.ReadField(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 diff --git a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs index 7d3f91e09..ee2dea17e 100644 --- a/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs +++ b/test/AsmResolver.DotNet.Dynamic.Tests/DynamicMethodDefinitionTest.cs @@ -1,3 +1,4 @@ +using System; using System.Linq; using System.Reflection; using System.Reflection.Emit; @@ -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); + } } }