I try to replace the body of a method with the body of a DynamicMethod. So far I used the following resources to get the pointer to a "normal" method and to a DynamicMethod. With the functionality from the first link I have the functionality to replace the body of "normal" method with the body of another "normal" method. But if I try to use the functionality with the DynamicMethod it doesn't work. In the following is an example test:
using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
public class Test
{
public void Test_Dynamic()
{
// --- Gemerate new dynamic method ---
DynamicMethod dynamicMethod = new DynamicMethod(
"My_DynamicMethod",
typeof(int),
new Type[] { typeof(int) },
typeof(Test).Module)
;
ILGenerator il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
// --- Check expected results ---
var normalOriginalValue = TestFunc(78); // is 73
var normalInjectValue = InjectFunc(78); // is 28
var dynamicValue = dynamicMethod.Invoke(null, new object[] { 78 }); // is 78
// --- Get pointer of DynamicMethod ---
var getDynamicHandle = Delegate.CreateDelegate(
typeof(Func<DynamicMethod, RuntimeMethodHandle>),
typeof(DynamicMethod).GetMethod("GetMethodDescriptor",(BindingFlags)(-1))
) as Func<DynamicMethod, RuntimeMethodHandle>;
var handle = getDynamicHandle(dynamicMethod);
var dynamicMethodPtr = handle.Value;
// --- Get pointer of "normal" method ---
var testFunc = typeof(Test).GetMethod("TestFunc", (BindingFlags)(-1));
RuntimeHelpers.PrepareMethod(testFunc.MethodHandle);
var normalTargetMethodPtr = testFunc.MethodHandle.Value;
var injectFunc = typeof(Test).GetMethod("InjectFunc", (BindingFlags)(-1));
RuntimeHelpers.PrepareMethod(injectFunc.MethodHandle);
var normalInjectMethodPtr = injectFunc.MethodHandle.Value;
// --- Swap "normal" method bodies ---
SwapBodies(normalTargetMethodPtr, normalInjectMethodPtr);
var injectedNormalValue = TestFunc(78); // is 28
// --- Swap method bodies with a DynamicMethod ---
// Should be 78 but throws an System.AccessViolationException
SwapBodies(normalTargetMethodPtr, dynamicMethodPtr);
var injectedDynamicMethodValue = TestFunc(78);
}
public static int TestFunc(int value)
{
return value - 5;
}
public static int InjectFunc(int value)
{
return value - 50;
}
private unsafe static void SwapBodies(IntPtr toReplace, IntPtr toInject)
{
// For simplicity here I only show the procedure for a debug run
// and not a production run.
if (IntPtr.Size == 4)
{
int* inj = (int*)toInject.ToPointer() + 2;
int* tar = (int*)toReplace.ToPointer() + 2;
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
}
else
{
long* inj = (long*)toInject.ToPointer() + 1;
long* tar = (long*)toReplace.ToPointer() + 1;
byte* injInst = (byte*)*inj;
byte* tarInst = (byte*)*tar;
int* injSrc = (int*)(injInst + 1);
int* tarSrc = (int*)(tarInst + 1);
*tarSrc = (((int)injInst + 5) + *injSrc) - ((int)tarInst + 5);
}
}
}
Can someone help me to get it working to replace a method body with the body of a DynamicMethod?
Aucun commentaire:
Enregistrer un commentaire