6

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!

Jambaman
  • 741
  • 9
  • 22
  • 1
    Looks like a missmatch in the ABIs. I'd check if they are compatible or need wrappers. The symbols sems to be some libgcc special versions of `memclr` (which is a special variant of `memset`) and `memcpy` – too honest for this site Jul 18 '15 at 18:35
  • As a newbie to this, could you point me in the direction to look for checking this? – Jambaman Jul 20 '15 at 05:44
  • 1
    That depends on the OS and CPU and compiler settings. For ARM, current PCS is AAPCS and the ABI specs (free download), but gcc allows for some others, too. That is valid for C and some other languages, but no idea about Rust. – too honest for this site Jul 20 '15 at 12:19
  • I'm working on this issue now. Did you solve it? I think we need to see a bit more of your code - cargo.toml, makefile, etc. My theory is that the arm-none-eabi tools work slightly differently than thumbv7. There are asm versions of these routines (builtins for llvm) out there. – Alister Lee Nov 24 '15 at 12:04
  • No, didn't solve it. The code is here: https://github.com/halseth/embedded_rust The architecture I use is ARM Cortex-M0, which is thumbv6m I believe. – Jambaman Nov 25 '15 at 12:41
  • To add to that. That code repo is just used to build the Rust code, into object files. I end up with sha256.o, but the problem arises when I try to link this into my C-project. Cannot provide the whole Makefile for that link process unfortunately, as it has some proprietary code, but can provide snippets if I know what to look for. – Jambaman Nov 25 '15 at 12:58

1 Answers1

7

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.

Alister Lee
  • 2,236
  • 18
  • 21