Cortex-m-rt v0.4.0: now you can link ARM Cortex-M programs using LLD


A new version of the cortex-m-rt crate is out!

A lot of bare metal applications use this crate to handle the memory layout and boot process
requirements of ARM Cortex-M devices. In other words, this crate makes sure your program boots the
device correctly!

The main highlight of this release is that now you can link Rust programs using the LLD (LLVM’s
linker) shipped with the Rust toolchain. Using Rust’s LLD means that you don’t have to install
arm-none-eabi-binutils, which contains GNU LD, to build Rust programs (though you may still want
to install that for tools like size and objdump – at least for now)

To use LLD instead of GNU LD, or GCC, tweak your project Cargo configuration file to look like this:

This diff assumes you started with version v0.2.6 of the [cortex-m-quickstart] template

 runner = 'arm-none-eabi-gdb'
 rustflags = [
   "-C", "link-arg=-Tlink.x",
-  "-C", "linker=arm-none-eabi-ld",
-  "-Z", "linker-flavor=ld",
+  "-C", "linker=lld",
+  "-Z", "linker-flavor=ld.lld",

Make sure you are using v0.4.0 of cortex-m-rt and that’s it! Now just call cargo build and your
program will be linked using LLD. If you want to confirm you can pass -Z print-link-args to

$ cargo rustc --release -- -Z print-link-args
"lld" "-flavor" "gnu" "-L" (..)

If you run into any trouble using LLD with cortex-m-rt v0.4.x please open an issue here!

To add LLD support we had to tweak the linker script that cortex-m-rt provides. Sadly, this meant
dropping the support for zero cost stack overflow protection that was added in v0.3.13. The
stack overflow protection stuff made LLD produce binaries that reported totally wrong information
when you ran size on them; this made it impossible to use the double linking trick, which adds the
stack overflow protection, with LLD.

We felt that making LLD work correctly out of the box, thus making the development process require
one less external tool, was worth the trade-off. We may add back stack overflow protection in the future
behind a Cargo feature that only works with GNU LD; though, it would be best if LLD’s linker scripts
supported the feature out of the box.

Another important change in this release is that the “abort-on-panic” Cargo feature is gone. This
feature added an implementation of panic_fmt that simply called intrinsics::abort to the crate.

If you were using this feature now you’ll have to define the panicking behavior yourself. We got you
covered though: you can simply link to a panic implementation crate like panic-semihosting or
panic-itm to define the panicking behavior, instead of having to write a panic_fmt
implementation yourself. You’ll have to write something like this:


extern crate cortex_m_rt;
extern crate panic_semihosting; // NEW! provides the panicking behavior

fn main() {

We suggest that only the “top” binary crate, i.e. your application, links to a panic implementation
crate. If a library crate links to a panic implementation crate then applications that use that
library won’t be able to pick a different panicking behavior!

This new release is part of the effort towards reducing the complexity of setting up a development
environment for embedded development