In my previous entry on IL modification we looked at the details for inserting a method call with a known (hardcoded) method token. We also used metadata to list the available methods, as a way to avoid this hardcoding.
When listing the methods on a given class, the method signatures were available, but we didn't use them. In this short entry, we'll extend our metadata inspection a little bit by using an existing method's signature to search for another method with a matching signature.
Update: I posted the zipped project.
A couple of days back, we tweaked the running IL a little bit. Today, let's modify it some more!
We'll insert a method call at the beginning of the body of the Main method. The method we'll call is as easy as can be: it is part of the of the same class, is static and has a void() signature.
The IL used during the modification is still hardcoded. But we'll try to start moving away from that by exploring the metadata, to try and find the method token at runtime. The first step of this is to list all the methods on the current class and print out their names, which we'll see how to do.
You'll need a running copy of the DNProfiler tool to try the code provided and I recommend that you read my previous blog on the subject if you haven't used the Profiler APIs before.
If you remember the Omniscient Debugger, it was a Java debugger that instrumented the bytecode at runtime to trace calls and monitor variables. It did so by using a custom ClassLoader.
Unfortunately the .NET classes that seemed somewhat equivalent to the Java ClassLoader are sealed, so they can't be extended. So, for a while I thought runtime instrumentation of the code wasn't possible in .NET...
A couple weeks later, I stumbled onto the NProf (open-source .NET profiler) project and wondered how they did their magic. It turns out they use the CLR Profiling APIs which are COM based and allow you to hook up into various events and get information on the runtime. It is while digging some more into these that I first found a mention of the intriguing ICorProfilerInfo::SetILFunctionBody method.