Hello ! I am trying to write programs to be used with the Linux kernel in the user land.
I did not want to rely on stdlib nor libc , and looking here and there I found about the x86_64-unknown-none target.
It is used for writing freestanding x86 binaries, I think that is the target I am looking for.
I first tried to write a minimal running program (userbin):
#![no_std]
#![no_main]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[export_name = "_start"]
fn main() {
loop {}
}
And running it worked just fine. Now I believe I might want to do some setup before calling main, I do not know yet what this setup will be exactly, but it might involve setting up a global allocator, or unwinding mechanisms. I intend to write many such programs, so I wanted to isolate the setup in a library.
I created a libstartup library package, next to the binary userbin package and wrote the following in libstartup/lib.rs:
#![no_std]
use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
#[export_name = "_start"]
pub fn start_up() -> ! {
extern "Rust" {
fn main () -> !;
}
unsafe { main() };
}
and changed userbin/main.rs to:
#![no_std]
#![no_main]
use libstartup;
#[export_name = "main"]
fn main() {
loop {}
}
running cargo build
works fine, but running the compiled program results in a SIGSEGV(Address boundary error).
Looking at the disassembly of _start
:
0000000000001240 <_start>:
1240: 50 pushq %rax
1241: ff 15 e9 10 00 00 callq *0x10e9(%rip) # 0x2330 <userbin.25798e51bdcbbf78-cgu.0+0x2330>
It looks like it calls a symbol defined in userbin, but it's not main, even though the symbol main is defined. The compiler is aware of the link between the declared main
in libstartup/lib.rs and the exported main
in userbin.rs, because if I change to #[export_name = "not_wanted_main"]
in userbin/main.rs the compilers complains about the undefined symbol main
.
So I know the compiler is aware of the link, but it doesn't call the right function (it calls a symbol that is not a function).
Can you please help me get this working ?
To get here I read:
- some posts of Philipp Oppermann's blog,
- some chapters of the Embedonomicon
- the sources of the riscv-rt crate and in particular:
- the code generated by their
#[entry]
attribute macro - their Rust entry point provided in a library.
- the code generated by their