Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking Rust with C: undefined reference to '__aeabi' functions

Tags:

c

gcc

rust

libc

eabi

I'm working on a project using Rust on an embedded device, where I'm trying to write functions in Rust that can be called from C. I compile the project without the standard library, more or less following this tutorial: Embedded Rust Right Now!

My Rust code compiles just fine to .o files, but I'm having troubles when trying to link the C and Rust object files together using arm-none-eabi-ld. I get several errors similar to these:

rustfunc.o: In function `func':
rustfunc.0.rs:(.text.hash+0x18): undefined reference to `__aeabi_memclr8'
...
/rust/src/libcore/slice.rs:1446: undefined reference to `__aeabi_memcpy'
/rust/src/libcore/fmt/num.rs:196: undefined reference to `__aeabi_memclr4'

What puzzles me the most is that even though I'm just linking object files together, the errors reference both my Rust code, and code from libcore.

Does anybody have an idea what these errors mean and why the linker cannot resolve these issues? Thanks!

like image 281
Jambaman Avatar asked Jul 18 '15 18:07

Jambaman


1 Answers

The problem is that LLVM, which your rustc (and possibly your cc) is built on, references compiler builtins or sometimes intrinsics, which are small helper routines that the compiler assumes will have been optimised for the target platform.

Usually they come with the compiler, so you'll see a lot of commentary out on the 'Net saying "why don't you link with libgcc.a". This seems unhelpful for bare-metal projects, and in fact won't work, because LLVM calls slightly different builtins than gcc.

You can provide implementations for these routines, and a true bare metal OS should probably spend about five minutes contemplating it. You can write them in assembly or Rust:

// Use this at your peril
#[no_mangle]
pub unsafe extern fn __aeabi_memclr4(s: *mut u8, n: usize) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *s.offset(i as isize) = 0u8;
        i += 1;
    }
    return s;
} 

After you've finished dreaming, you set about compiling llvm's compiler-rt (equivalent to libgcc.a) for your target and you link that.

Until rustc and multirust increase their support for installing extra targets for cross-compilation, you have to download the Rust source and try to build the cross-compiler and libs (including compiler-rt) yourself.

Currently arm-none-eabi is not a supported target, and building is rough for a list of reasons, including that arm-none-eabi-gcc won't link an executable, which Rust's jemalloc insists on. My workaround is to harvest the source files from compiler-rt and build and link them individually.

like image 74
Alister Lee Avatar answered Oct 03 '22 19:10

Alister Lee