The Mighty Mouse is not as good as it taste 6

Posted by jbevain Mon, 15 Aug 2005 16:54:09 GMT



I was so heavily disappointed by my Mighty Mouse that i’ve swallowed it.

Assembly Round Tripping and much more

Posted by jbevain Sat, 13 Aug 2005 14:11:23 GMT


Thanks to another few hacks today on Cecil, I can now do funny things. Assembly Round Tripping is one of them. It just mean that I can now load an Assembly with Cecil, and write it back. Without loss of data. Anyway Cecil for the moment does not deal with a lot of data :) Here is a sample code so that you can figure out by yourself:

<span class="kwrd">using</span> Mono.Cecil;

<span class="kwrd">class</span> RoundTrip {

    <span class="kwrd">static</span> <span class="kwrd">void</span> Main ()
    {
        <span class="kwrd">string</span> file = <span class="str">"hello.exe"</span>
        <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; 10; i++)
            AssemblyFactory.SaveAssembly (AssemblyFactory.GetAssembly (
                file, LoadingType.Aggressive), file, AssemblyKind.Console);
    }
}

Doing this ten times it plain useless. But now you are sure that the assembly is well round tripped.

Interesting huh ? But yeah, a bit useless as it is. If Cecil is able to read and assembly and write it back, it should also be possible to modify it. To go further, I have to assume that you’ve read the precedent post, that reveals the Hello World example. Now let’s read this wonderful piece of code that will modify the Hello World :

<span class="kwrd">using</span> Mono.Cecil;
<span class="kwrd">using</span> Mono.Cecil.Cil;

<span class="kwrd">class</span> Pre_AOP_Era {

    <span class="kwrd">static</span> <span class="kwrd">void</span> Main ()
    {
        <span class="kwrd">string</span> file = <span class="str">"hello.exe"</span>
        IAssemblyDefinition asm = AssemblyFactory.GetAssembly (
            file, LoadingType.Aggressive);

        ITypeDefinition hello = asm.MainModule.Types [<span class="str">"Test.Hello"</span>];
        IMethodDefinition main = hello.Methods [0]; <span class="rem">// get the Main method</span>
        ICilWorker worker = main.Body.GetWorker ();

        InsertBeforeRetInstruction (
            worker, worker.Create (OpCodes.Ldstr, <span class="str">"And from Jb too!"</span>));
        InsertBeforeRetInstruction (
            worker, worker.Create (OpCodes.Call, <span class="kwrd">typeof</span> (Console).GetMethod (
                    <span class="str">"WriteLine"</span>, <span class="kwrd">new</span> Type [] {<span class="kwrd">typeof</span> (<span class="kwrd">string</span>)})));

        AssemblyFactory.SaveAssembly (asm, file, AssemblyKind.Console);
    }

    <span class="kwrd">static</span> <span class="kwrd">void</span> InsertBeforeRetInstruction (ICilWorker worker, IInstruction ins)
    {
        IMethodBody body = worker.GetBody ();
        IInstruction ret = body.Instructions [body.Instructions.Count - 1];
        worker.InsertBefore (ret, ins);
    }
}

Basically, I retrieve here the type and a method defined in the precedent example, and using I add two instructions before the last instruction of this method. I just call Console.WriteLine with a new string “And from Jb too!” The ICilWorker interface defines methods to create and manipulate CIL streams. As it is not very complete, I’ve written here a little method to help in this task.

Unsurprisingly, by invoking the new executable, you’ll be greeted twice:

newton:~/Sources/temp jbevain$ mono hello.exe 
Hello from Cecil!
And from Jb too!

This feature of Cecil is a terribly exciting one. It leds to many applications, including the re-write of the core of AspectDNG, the Aspect Weaver Thomas Gil and I are working on.

Don’t be desapointed, but once again, this is still not in SVN, but it shows the lasts progress of Cecil. I hope you enjoy it as much as I do :)

Oh, and because he loves pictures, here is one of Sebastien Ros, one of my mentor, and me:

The Thousand Nights and a Night of Hacking 1

Posted by jbevain Sat, 13 Aug 2005 04:31:41 GMT


Hey world, it’s 6am here in Paris, and I’m still in the front of my computer. But this morning, I feel just like happy, excited, and proud. Yeah, and tired too.

I worked all night, and this morning, Cecil have written its first Hello World!. The code is not yet is SVN, it’s still full of debug code, but heh, its works here :)

Here is the little application that emits this new and shiny hello world:

<span class="kwrd">using</span> Mono.Cecil;
<span class="kwrd">using</span> Mono.Cecil.Cil;

<span class="kwrd">class</span> Test {

    <span class="kwrd">static</span> <span class="kwrd">void</span> Main ()
    {
        IAssemblyDefinition asm = AssemblyFactory.DefineAssembly (
            <span class="str">"hello"</span>, <span class="str">"HelloWorld"</span>, TargetRuntime.NET_1_1);

        ITypeDefinition t = asm.MainModule.DefineType (
            <span class="str">"Hello"</span>, <span class="str">"Test"</span>, TypeAttributes.Class, <span class="kwrd">typeof</span> (<span class="kwrd">object</span>));

        IMethodDefinition meth = t.DefineMethod (
            <span class="str">"Main"</span>, MethodAttributes.Static, <span class="kwrd">typeof</span> (<span class="kwrd">void</span>));

        IMethodBody body = meth.DefineBody ();
        ICilWorker cw = body.GetWorker ();
        cw.Emit (OpCodes.Ldstr, <span class="str">"Hello from Cecil!"</span>);
        cw.Emit (OpCodes.Call, <span class="kwrd">typeof</span> (Console).GetMethod (
                <span class="str">"WriteLine"</span>, <span class="kwrd">new</span> Type [] {<span class="kwrd">typeof</span> (<span class="kwrd">string</span>)}));
        cw.Emit (OpCodes.Ret);

        IMethodDefinition ctor = t.DefineConstructor ();
        body = ctor.DefineBody ();
        cw = body.GetWorker ();
        cw.Emit (OpCodes.Ldarg_0);
        cw.Emit (OpCodes.Call,
            <span class="kwrd">typeof</span> (<span class="kwrd">object</span>).GetConstructor (<span class="kwrd">new</span> Type [0]));
        cw.Emit (OpCodes.Ret);

        asm.EntryPoint = meth;

        AssemblyFactory.SaveAssembly (
            asm, <span class="str">"hello.exe"</span>, AssemblyKind.Console);
    }
}

The application is simple, and will looks familiar to everyone that already used System.Reflection.Emit. Of course there are some differences, but let see that later, just notice that Cecil understands both Cecil types, and classics System.Type. Oh, and once again, don’t try this at home, it won’t work. At least, it’s not dangerous. As expected, if you execute this file using Mono, you’ll be greeted:

newton:~/Sources/temp jbevain$ mono hello.exe 
Hello from Cecil!

Don’t expect Cecil to emit more things for the moment. But it’s already not that bad. Let me show you another interesting feature. Imagine you need to generate some ponctual code, that you plan neither to keep, nor to save on the disk. The use case for the AssemblyBuilderAccess.Run enum value within System.Reflection.Emit. Let see how to do that!

Add this import:

<span class="kwrd">using</span> SR = System.Reflection;

And remove the last line of the code above, and replace it the following lines:

        SR.Assembly a = AssemblyFactory.CreateReflectionAssembly (
            asm, AssemblyKind.Console);

        a.GetType (<span class="str">"Test.Hello"</span>).GetMethod (
            <span class="str">"Main"</span>, SR.BindingFlags.NonPublic |
            SR.BindingFlags.Static
        ).Invoke (<span class="kwrd">null</span>, <span class="kwrd">new</span> <span class="kwrd">object</span> [0]);

The assembly will be emitted in memory, and loaded as it in an AppDomain (the current one by default). Then you’ll be able to work on it like any other assembly. Cool huh ?

So, tasks for tomorrow: clean the code, improve it, extend it, then it will go into SVN. As I’m happy, for no reason, here is a picture of where Cecil is tinkered. Please notice in the bottom right a good old xbox, that used to be famous. May it rest in peace.

Hum, if the CLR and MS ildasm loads my fresh new hello world, it can’t be run by lauching it just like another executable. It’s not a valid Win32 executable it says. f**k you billy, I’ll see that tomorrow, I’m going to sleep.

Revision 48210 3

Posted by jbevain Tue, 09 Aug 2005 23:25:13 GMT


On the radio tonight

Brrffrrr frrrfrr frrfr

Assemblies emitted by Cecil are now understood by the .net CLR.

I REPEAT:

Assemblies emitted by Cecil are now understood by the .net CLR.

Brrfrrr frrrffrr frrrf

So that in a near future you can take a short look back in the past and smile

The very first assembly emitted by Cecil, that is readable by Cecil, Mono, Reflector and the .net CLR, can be found here.


La la la lala, lalala.

Older posts: 1 ... 25 26 27 28 29 ... 34