About an inherent limitation, and a possible solution 2

Posted by Jb Evain Mon, 11 Jun 2007 08:53:00 GMT

The linker is a static tool. It uses Mono.Cecil to analyze the assemblies, modify them, and save them back in a linked form.

That means that the linker can only know about the assemblies and the types that are statically referenced. You already see where I’m going to. Mono, just like .net, provides very interesting, and also widely used, ways to dynamically load assemblies and types. The common use case is a plug-in framework for instance, where assemblies are loaded when asked to.

As an example, let’s have a look to a piece of code I’ve faced when working on linking MoMa:

static Socket() {
    Assembly ass;

    try {
        ass = Assembly.Load (Consts.AssemblyMono_Posix);
    } catch (FileNotFoundException) {
        return;
    }

    unixendpointtype=ass.GetType("Mono.Posix.UnixEndPoint");

    Type[] arg_types=new Type[1];
    arg_types[0]=typeof(string);
    ConstructorInfo cons=unixendpointtype.GetConstructor(arg_types);

    object[] args=new object[1];
    args[0]="nothing";

    unixendpoint=cons.Invoke(args);
}
From System.Net.Sockets.Socket in System.dll

This code is fairly simple to understand. The the Socket class constructor will be called, the assembly Mono.Posix will be loaded, and an instance of the type Mono.Posix.UnixEndPoint will be created, and its constructor will be invoked.

That’s the marvel of the reflection API. But as you can see, everything here is dynamic. The assembly System.dll contains no reference to the Mono.Posix.UnixEndPoint type, and no reference to the assembly Mono.Posix.

The linker can take two different kind of input. The first one is of course an assembly. It’s obvious what it does, the linker will link everything necessary for this particular assembly. The second one, is an xml file, that describes what types to save, and you can even choose in those types which fields or methods you want to link.

So, when linking your assemblies, you have to know if you’re doing some dynamic loading. If yes, you have to tell the linker using a xml descriptor which dynamic types you want to save, otherwise, they may very well be not present in the output assemblies.

That’s a little bit painful, and that forces you to maintain a list of such types/assemblies. To ease your pain, I wrote something that I find really useful, even if it’s not completely done yet.

Guys, that was the biggest introduction ever to talk about a little piece of code. This little guy is a profiler for Mono, that is simply triggered every time the JIT will leave a method.

It’s goal is to produce an xml file that the linker understand, from a running application. For instance, before linking MoMa, I used:
# mono --profile=link:moma.xml ./MoMa.exe

Then I’ve simply used MoMa like I would if I was simply analysing an application to submit a report, and at the end, I had an interesting moma.xml file. When opening it, I’ve seen:
<linker>
    <!-- ... -->
    <assembly fullname="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756">
        <type fullname="Mono.Posix.UnixEndPoint">
            <method signature="System.Void .ctor(System.String)" />
        </type>
        <!-- ... -->
    </assembly>
    <!-- ... -->
</linker>
As we can see, during the execution, we’ve been using the constructor of the type Mono.Posix.UnixEndPoint in the assembly Mono.Posix. That’s an information the linker would not have been able to know. By using the profiler, one can prepare the linker to do its job with more data that it would have been able to gather by itself.

And that’s pretty good to be able to do it without requiring me to write xml descriptors for every possible type that is dynamically loaded.

See, I can even write a few lines of C, isn’t that amazing?

Trackbacks

Use the following link to trackback from your own site:
http://evain.net/blog/articles/trackback/416

  1. Linker and mkbundle From Duff show
    Linker is a beautiful tool build by JB based on Cecil lib. It inspect assembly to get what external call is used and reduce all assembly to have the smaller one. The best friend application of linker is mkbundle which can ship all assembly/exe in ...
Comments

Leave a response

  1. Avatar
    Vladimir Giszpenc Mon, 11 Jun 2007 13:45:33 GMT

    Hi JB,

    Your work on Mono is great. It inspired an idea that I wanted to propose to you. The next logical step after the linker is a cross application linker—emerge type capability as on the Gentoo distribution. The idea is that if we want to build a few apps to go on a phone for example, we would want to use the linker to get everything we need for each app we choose to put on the phone. #Merge or whatever you call it, could help us get a small footprint and a giant leap for Mono on the rapidly growing OpenMoko, GMAE and other open source smart phone initiatives.

    Thanks,

    Vlad

  2. Avatar
    Jb Evain Tue, 12 Jun 2007 19:59:34 GMT

    Hey Vlad,

    Your proposal looks nice, but it’s a little out of my scope for now :)

    But feel free to start the effort ;)

Comments