Skip to content
This repository has been archived by the owner on Jan 24, 2022. It is now read-only.

v0.4.0: with LLD support #64

Merged
merged 9 commits into from
Apr 9, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [v0.4.0] - 2018-04-09

### Added

- LLD support. The linker script provided by this crate has been tweaked to support both LLD and GNU
LD. To use LLD as a linker change `.cargo/config` to look like this:

``` diff
[target.thumbv7m-none-eabi]
rustflags = [
"-C", "link-arg=-Tlink.x",
- "-C", "linker=arm-none-eabi-ld",
- "-Z", "linker-flavor=ld",
+ "-C", "linker=lld",
+ "-Z", "linker-flavor=ld.lld",
]
```

### Removed

- [breaking-change] Stack overflow protection has been removed. Unfortunately, supporting this
feature produces totally wrong `arm-none-eabi-size` reports when LLD is used to link the
program. If you need the stack overflow protection feature you can continue to use version
v0.3.13+.

- [breaking-change] The "abort-on-panic" Cargo feature, which provided a `panic_fmt` implementation,
has been removed. If you were using this feature you can instead use a [panic implementation
crate][panic-impl].

[panic-impl]: https://crates.io/keywords/panic-impl

## [v0.3.15] - 2018-04-08

### Fixed
12 changes: 2 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -7,16 +7,8 @@ keywords = ["arm", "cortex-m", "runtime", "startup"]
license = "MIT OR Apache-2.0"
name = "cortex-m-rt"
repository = "https://github.com/japaric/cortex-m-rt"
version = "0.3.15"
version = "0.4.0"

[dependencies]
cortex-m = "0.3.0"
r0 = "0.2.1"

[features]
# provides a panic_fmt implementation that calls the abort instruction (`udf 0xfe`)
abort-on-panic = []

[build-dependencies]
rustc_version = "0.2.1"
chrono = "0.4.0"
r0 = "0.2.1"
19 changes: 0 additions & 19 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
extern crate chrono;
extern crate rustc_version;

use std::env;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use chrono::NaiveDate;

fn main() {
let meta = rustc_version::version_meta().unwrap();
let commit_date = meta.commit_date.unwrap().parse::<NaiveDate>().unwrap();
if meta.channel == rustc_version::Channel::Dev
|| commit_date > NaiveDate::from_ymd(2017, 12, 26)
{
println!("cargo:rustc-cfg=has_termination_lang")
}

// newest nightlies don't need 'extern crate compiler_builtins'
if commit_date < NaiveDate::from_ymd(2018, 04, 07)
{
println!("cargo:rustc-cfg=needs_cb")
}

let target = env::var("TARGET").unwrap();

has_fpu(&target);
48 changes: 6 additions & 42 deletions link.x
Original file line number Diff line number Diff line change
@@ -48,27 +48,16 @@ SECTIONS
. = ALIGN(4);
} > FLASH

/* limits of the .stack region */
_estack = _stack_start;
/* HACK the `true` case indicates that two RAM regions are being used and
/* that the stack was placed in the second region. In that case we don't know
/* the size of the second RAM region, or its start address, so we just assume
/* its zero sized */
_sstack = _stack_start < ORIGIN(RAM)? _stack_start : ORIGIN(RAM);

/* fictitious region that represents the memory available for the stack */
.stack _sstack (INFO) : ALIGN(4)
{
. += (_estack - _sstack);
}

PROVIDE(_sbss = ORIGIN(RAM));
.bss _sbss : ALIGN(4)
{
*(.bss .bss.*);
. = ALIGN(4);
_ebss = .;
} > RAM
} > RAM AT > FLASH
/* NOTE(AT > FLASH) without this LLD v6 produces a binary that crashes OpenOCD whereas LLD v7
emits a ".rodata and .bss sections overlap" error ... This hacky workaround doesn't increase
the binary size AFAICT */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One drawback is this will make firmwares with really full flashes uncompilable. Do I understand it right that lld v7 doesn't require the workaround?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand it right that lld v7 doesn't require the workaround?

No, this also needed for the v7 I tested. Without the workaround linking with LLD fails with the error message in the comment; GNU LD can link the same program without errors and produces a binary that doesn't crash OpenOCD.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to look at the underlying lld bug? I don't yet use lld for my embedded development so I'm afraid you're in the better position here. I can review though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will at least submit a bug report. I have zero experience hacking LLVM :-).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw, with arm-none-eabi-ld at least, this doesn't cause problems even when bss is larger than the entire flash space, everything works as it should (surprisingly?). I haven't tried with lld.


.data : ALIGN(4)
{
@@ -79,16 +68,8 @@ SECTIONS
_edata = .;
} > RAM AT > FLASH

PROVIDE(_heap_size = 0);

/* The heap starts right after the .bss + .data section ends */
_sheap = _edata;
_eheap = _sheap + _heap_size;

/* fictitious region that represents the memory available for the heap */
.heap _sheap (INFO) : ALIGN(4)
{
. += _heap_size;
}

/* fake output .got section */
/* Dynamic relocations are unsupported. This section is only used to detect
@@ -101,26 +82,9 @@ SECTIONS
_egot = .;
} > RAM AT > FLASH

/* The heap starts right after the .bss + .data section ends */
_sheap = _edata;

/* Due to an unfortunate combination of legacy concerns,
toolchain drawbacks, and insufficient attention to detail,
rustc has no choice but to mark .debug_gdb_scripts as allocatable.
We really do not want to upload it to our target, so we
remove the allocatable bit. Unfortunately, it appears
that the only way to do this in a linker script is
the extremely obscure "INFO" output section type specifier. */
/* a rustc hack will force the program to read the first byte of this section,
so we'll set the (fake) start address of this section to something we're
sure can be read at runtime: the start of the .text section */
.debug_gdb_scripts _stext (INFO) : {
KEEP(*(.debug_gdb_scripts))
}

/DISCARD/ :
{
*(.ARM.exidx.*)
*(.ARM.exidx.*);
}
}

18 changes: 0 additions & 18 deletions src/lang_items.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
/// Default panic handler
#[cfg(feature = "abort-on-panic")]
#[lang = "panic_fmt"]
unsafe extern "C" fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u32, _: u32) -> ! {
::core::intrinsics::abort()
}

// Lang item required to make the normal `main` work in applications
//
// This is how the `start` lang item works:
@@ -24,7 +17,6 @@ unsafe extern "C" fn panic_fmt(_: ::core::fmt::Arguments, _: &'static str, _: u3
// The final piece is that the entry point of our program, the reset handler,
// has to call `rustc_main`. That's covered by the `reset_handler` function in
// root of this crate.
#[cfg(has_termination_lang)]
#[lang = "start"]
extern "C" fn start<T>(main: fn() -> T, _argc: isize, _argv: *const *const u8) -> isize
where
@@ -35,21 +27,11 @@ where
0
}

#[cfg(not(has_termination_lang))]
#[lang = "start"]
extern "C" fn start(main: fn(), _argc: isize, _argv: *const *const u8) -> isize {
main();

0
}

#[lang = "termination"]
#[cfg(has_termination_lang)]
pub trait Termination {
fn report(self) -> i32;
}

#[cfg(has_termination_lang)]
impl Termination for () {
fn report(self) -> i32 {
0
Loading