​Hello Michal,


I haven't found a nice way of linking CAmkES generated symbols against the top level of rumprun apps yet.  By top level I mean the POSIX app that gets linked against syscall layer, and the bottom level is the implementation of the syscall layer including the rump kernel, platform layer code, and camkes generated code.  The two layers are individually compiled and linked separately and both have a main function.   When the layers are combined into the same address space, the main function in the top layer is renamed and it is then linked with the bottom layer (this is done using the rumprun_bake tool).  Symbols are effectively name-spaced so that they don't collide across the two layers.


The CAmkES generated connectors are compiled and linked into the bottom layer.  I don't think it is currently possible to take the generated objects, create a new archive of them and then link the archive into the top layer without ending up with two sets of the same symbols.   Maybe there needs to be a way to mark connections as either top level or bottom level and they will only be linked in once (this would also nicely extend to supporting connectors that directly generate rust instead  of C).  


The current way I achieve what you want in the Ethernet app is by marking the symbols  weak in the top layer, the compiler won't complain if they don't exist, and then when the top is combined with the bottom, the symbols are successfully linked.  


I managed to get this working with your rust app here:  https://github.com/kent-mcleod/camkes/tree/rustapp

​It isn't pretty, and I hope there is a better way in Rust of marking C foreign functions as weak.  See this discussion here for more info: https://github.com/rust-lang/rust/issues/29603

Rust only allows pointers to be marked as weak which is why the functions in the rust code are declared as function pointers, and then cast to actual functions (yuck).


Kind regards,

Kent




From: Devel <devel-bounces@sel4.systems> on behalf of Michal Podhradsky <mpodhradsky@galois.com>
Sent: Wednesday, August 16, 2017 5:04 AM
To: devel@sel4.systems
Subject: [seL4] rumprun + rust + camkes
 
Hello Kent,

I extended the rumprun+rust example (available in this PR) with a simple camkes connection between the rumprum camkes component and a serial server component, as shown below (full code here):

 composition {
     component rumprun_platform_layer rrpl;

     component rumprun_rust hello1;
     RUMPRUN_META_CONNECTION(hello1, rrpl)

     component rumprun hello2;
     RUMPRUN_META_CONNECTION(hello2, rrpl)

     component Server server;

     connection seL4SharedData conn(from hello1.camkes_buffer, to server.buffer);
     connection seL4Notification simpleEvent1(from hello1.camkes_ev, to server.ev);
     connection seL4Notification simpleEvent2(from server.ev1, to hello1.camkes_ev1);
 }

I added a simple rust program (running on rumprun_rust):

fn main() {
 println!("Hello rust!");
 unsafe {
  camkes_ev_emit();
 }
 println!("Waiting for event!");
 unsafe {
camkes_ev1_wait();
 }
 println!("Got event!");
 
}

#[no_mangle]
extern {
    fn camkes_ev_emit();
    fn camkes_ev1_wait(); 
}

In order to compile the cargo project, I added a build.rs script to package the generated camkes object file (camkes.o) into an archite that cargo can link against.

The problem is, that the generated camkes.c file contains its own main function:

int USED main(int argc UNUSED, char *argv[]) {
    assert(argc == 2);
    assert(strcmp(argv[0], "camkes") == 0);

    int thread_id = (int)(uintptr_t)(argv[1]);
    return post_main(thread_id);
}

which collides with the fn main() defined in rust. (I get multiple definition of `main' error).

How is this handled in rumprun_ethernet example? There is also a main function for the rumpkernel component, and the main() from camkes, but the compilation process handles this correctly.

Could you point me in the right direction?

Regards
Michal