Title more or less says it all. Based on this article, I've come up with this:
public static unsafe void Replace(this MethodBase destination, MethodBase source)
{
IntPtr srcHandle = source.MethodHandle.GetFunctionPointer();
IntPtr dstHandle = destination.MethodHandle.GetFunctionPointer();
int* dstPtr = (int*)dstHandle.ToPointer();
*dstPtr = srcHandle.ToInt32();
}
This actually works... occasionally -.-
For example, this works.
public static class Program
{
public static void Main(string[] args)
{
MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);
methodA.Replace(methodB);
A();
B();
}
public static void A()
{
Console.WriteLine("Hai World");
}
public static void B()
{
Console.WriteLine("Bai World");
}
}
However, this doesn't (SEHException). All I did was change the order in which the functions were defined.
public static class Program
{
public static void Main(string[] args)
{
MethodInfo methodA = typeof(Program).GetMethod("A", BindingFlags.Public | BindingFlags.Static);
MethodInfo methodB = typeof(Program).GetMethod("B", BindingFlags.Public | BindingFlags.Static);
methodA.Replace(methodB);
A();
B();
}
public static void B()
{
Console.WriteLine("Bai World");
}
public static void A()
{
Console.WriteLine("Hai World");
}
}
As for the code in the article... I couldn't get it to work at all.
Any ideas/alternatives?
This is making a lot of bad assumptions which will bite you in the ass.
First things first, the structure returned via reflection is not guaranteed, in any way, to point to any runtime structures at all. As such attempting to modify the pointers it contains or returns is just plain wrong.
Secondly, if you wish to do something like injecting pre/post method call invariants (as an example) then you should probably construct runtime proxy objects and inject those instead. Or use dynamic method construction through the Emit namespace. Attempting to manipulate things through undocumented/unknown behaviors (such as the above code) just wont work.
You also need to realize that the JIT decides when it will run. Sometimes it runs against an entire class, and sometimes it just runs against a single method. Your code makes no attempt at determining if the method has been JITted yet, and blindly assumes that the function pointer returned can be modified.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With