aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jorge Aparicio <jorge@japaric.io> 2018-08-07 14:43:28 -0500
committerGravatar Jorge Aparicio <jorge@japaric.io> 2018-08-07 15:22:39 -0500
commitf2c5e2e4058b0a57a1d874878bde67f612b2d9dd (patch)
treeba2164706a20c1fac83a9118753cd81302724402
parent6e5e5ea4597ec6634f5d730b3218f8b71156da40 (diff)
downloadcortex-m-f2c5e2e4058b0a57a1d874878bde67f612b2d9dd.tar.gz
cortex-m-f2c5e2e4058b0a57a1d874878bde67f612b2d9dd.tar.zst
cortex-m-f2c5e2e4058b0a57a1d874878bde67f612b2d9dd.zip
refactor the linker script
to make it more compatible with LLD. This commit contains no functional changes. fixes #70 Overview of changes: - Alignment checks are enabled now that rust-lld (LLD 7.0) supports the modulo operator. - Removed some private symbols (e.g. __foo) in favor of ADDR and SIZEOF. - Turned .got into a NOLOAD section now that rust-lld supports it. - Replaced `ABSOLUTE(.)` with `.` as an old LLD overlap bug seems to be gone and ABSOLUTE seems to cause problems, like #70, on bigger programs. - Made the linker assertion messages more uniform. - Extended test suite to check that linking works with both rust-lld and GNU LD.
-rw-r--r--cortex-m-rt/Cargo.toml1
-rw-r--r--cortex-m-rt/build.rs8
-rw-r--r--cortex-m-rt/ci/script.sh25
-rw-r--r--cortex-m-rt/examples/alignment.rs45
-rw-r--r--cortex-m-rt/link.x.in160
5 files changed, 149 insertions, 90 deletions
diff --git a/cortex-m-rt/Cargo.toml b/cortex-m-rt/Cargo.toml
index 1b7427c..9cd9d19 100644
--- a/cortex-m-rt/Cargo.toml
+++ b/cortex-m-rt/Cargo.toml
@@ -17,6 +17,7 @@ r0 = "0.2.1"
[dev-dependencies]
panic-semihosting = "0.3.0"
+panic-abort = "0.2.0"
[features]
device = []
diff --git a/cortex-m-rt/build.rs b/cortex-m-rt/build.rs
index 8edba9f..fc53d79 100644
--- a/cortex-m-rt/build.rs
+++ b/cortex-m-rt/build.rs
@@ -42,12 +42,12 @@ INCLUDE device.x"#
writeln!(
f,
r#"
-ASSERT(__einterrupts - __eexceptions <= 0x{:x}, "
-There can't be more than {} interrupt handlers. This may be a bug in
-your device crate, or you may have registered more than 240 interrupt
+ASSERT(SIZEOF(.vector_table) <= 0x{:x}, "
+There can't be more than {1} interrupt handlers. This may be a bug in
+your device crate, or you may have registered more than {1} interrupt
handlers.");
"#,
- max_int_handlers * 4,
+ max_int_handlers * 4 + 0x40,
max_int_handlers
).unwrap();
diff --git a/cortex-m-rt/ci/script.sh b/cortex-m-rt/ci/script.sh
index 221386d..2515b8f 100644
--- a/cortex-m-rt/ci/script.sh
+++ b/cortex-m-rt/ci/script.sh
@@ -6,11 +6,13 @@ main() {
cargo check --target $TARGET --features device
local examples=(
+ alignment
minimal
main
state
)
if [ $TRAVIS_RUST_VERSION = nightly ]; then
+ # linking with GNU LD
for ex in "${examples[@]}"; do
cargo rustc --target $TARGET --example $ex -- \
-C link-arg=-nostartfiles \
@@ -28,6 +30,29 @@ main() {
cargo rustc --target $TARGET --example device --features device --release -- \
-C link-arg=-nostartfiles \
-C link-arg=-Wl,-Tlink.x
+
+ # linking with rustc's LLD
+ for ex in "${examples[@]}"; do
+ cargo rustc --target $TARGET --example $ex -- \
+ -C linker=rust-lld \
+ -Z linker-flavor=ld.lld \
+ -C link-arg=-Tlink.x
+
+ cargo rustc --target $TARGET --example $ex --release -- \
+ -C linker=rust-lld \
+ -Z linker-flavor=ld.lld \
+ -C link-arg=-Tlink.x
+ done
+
+ cargo rustc --target $TARGET --example device --features device -- \
+ -C linker=rust-lld \
+ -Z linker-flavor=ld.lld \
+ -C link-arg=-Tlink.x
+
+ cargo rustc --target $TARGET --example device --features device --release -- \
+ -C linker=rust-lld \
+ -Z linker-flavor=ld.lld \
+ -C link-arg=-Tlink.x
fi
}
diff --git a/cortex-m-rt/examples/alignment.rs b/cortex-m-rt/examples/alignment.rs
new file mode 100644
index 0000000..ef1beaa
--- /dev/null
+++ b/cortex-m-rt/examples/alignment.rs
@@ -0,0 +1,45 @@
+//! This is not an example; this is a link-pass test
+
+#![deny(warnings)]
+#![no_main]
+#![no_std]
+
+#[macro_use(entry, exception)]
+extern crate cortex_m_rt as rt;
+extern crate panic_abort;
+
+use core::ptr;
+
+use rt::ExceptionFrame;
+
+entry!(main);
+
+static mut BSS1: u16 = 0;
+static mut BSS2: u8 = 0;
+static mut DATA1: u8 = 1;
+static mut DATA2: u16 = 1;
+static RODATA1: &[u8; 3] = b"012";
+static RODATA2: &[u8; 2] = b"34";
+
+fn main() -> ! {
+ unsafe {
+ let _bss1 = ptr::read_volatile(&BSS1);
+ let _bss2 = ptr::read_volatile(&BSS2);
+ let _data1 = ptr::read_volatile(&DATA1);
+ let _data2 = ptr::read_volatile(&DATA2);
+ let _rodata1 = ptr::read_volatile(&RODATA1);
+ let _rodata2 = ptr::read_volatile(&RODATA2);
+ }
+
+ loop {}
+}
+
+exception!(HardFault, hard_fault);
+
+fn hard_fault(_ef: &ExceptionFrame) -> ! {
+ loop {}
+}
+
+exception!(*, default_handler);
+
+fn default_handler(_irqn: i16) {}
diff --git a/cortex-m-rt/link.x.in b/cortex-m-rt/link.x.in
index 9b99427..5df965a 100644
--- a/cortex-m-rt/link.x.in
+++ b/cortex-m-rt/link.x.in
@@ -48,87 +48,86 @@ PROVIDE(SysTick = DefaultHandler);
/* # Interrupt vectors */
EXTERN(__INTERRUPTS); /* `static` variable similar to `__EXCEPTIONS` */
-/* # User overridable symbols I */
-/* Lets the user place the stack in a different RAM region */
-PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
-
/* # Sections */
SECTIONS
{
+ PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
+
/* ## Sections in FLASH */
/* ### Vector table */
- .vector_table ORIGIN(FLASH) : ALIGN(4)
+ .vector_table ORIGIN(FLASH) :
{
/* Initial Stack Pointer (SP) value */
- __STACK_START = .; /* Just to get a nicer name in the disassembly */
LONG(_stack_start);
/* Reset vector */
- KEEP(*(.vector_table.reset_vector)); /* this is `__RESET_VECTOR` symbol */
- __reset_vector = ABSOLUTE(.);
+ KEEP(*(.vector_table.reset_vector)); /* this is the `__RESET_VECTOR` symbol */
+ __reset_vector = .;
/* Exceptions */
- KEEP(*(.vector_table.exceptions)); /* this is `__EXCEPTIONS` symbol */
- __eexceptions = ABSOLUTE(.);
+ KEEP(*(.vector_table.exceptions)); /* this is the `__EXCEPTIONS` symbol */
+ __eexceptions = .;
/* Device specific interrupts */
- KEEP(*(.vector_table.interrupts)); /* this is `__INTERRUPTS` symbol */
- __einterrupts = ABSOLUTE(.);
+ KEEP(*(.vector_table.interrupts)); /* this is the `__INTERRUPTS` symbol */
} > FLASH
+ PROVIDE(_stext = ADDR(.vector_table) + SIZEOF(.vector_table));
+
/* ### .text */
.text _stext :
{
*(.text .text.*);
- __etext = ABSOLUTE(.);
} > FLASH
/* ### .rodata */
.rodata :
{
- . = ALIGN(4); /* 4-byte align the start (VMA) of this section */
- /* __srodata = ABSOLUTE(.); */
-
*(.rodata .rodata.*);
- . = ALIGN(4); /* 4-byte align the end (VMA) of this section */
- __erodata = ABSOLUTE(.);
+ /* 4-byte align the end (VMA) of this section */
+ /* WHY? To my knowledge there's no way to indicate the alignment of *LMA* so we align *this*
+ section with the goal of using its end address as the LMA of .data */
+ . = ALIGN(4);
} > FLASH
/* ## Sections in RAM */
/* ### .data */
- .data : AT(__erodata) /* LMA */
+ .data : AT(ADDR(.rodata) + SIZEOF(.rodata)) /* LMA */
{
- . = ALIGN(4); /* 4-byte align the start (VMA) of this section */
- __sdata = ABSOLUTE(.);
-
*(.data .data.*);
. = ALIGN(4); /* 4-byte align the end (VMA) of this section */
- __edata = ABSOLUTE(.);
} > RAM
+ /* VMA of .data */
+ __sdata = ADDR(.data);
+ __edata = ADDR(.data) + SIZEOF(.data);
+
+ /* LMA of .data */
+ __sidata = LOADADDR(.data);
+
/* ### .bss */
.bss :
{
- . = ALIGN(4); /* 4-byte align the start (VMA) of this section */
- __sbss = ABSOLUTE(.);
-
*(.bss .bss.*);
. = ALIGN(4); /* 4-byte align the end (VMA) of this section */
- __ebss = ABSOLUTE(.);
} > RAM
- /* ## Fake output .got section */
+ __sbss = ADDR(.bss);
+ __ebss = ADDR(.bss) + SIZEOF(.bss);
+
+ /* Place the heap right after `.bss` */
+ __sheap = ADDR(.bss) + SIZEOF(.bss);
+
+ /* ## .got */
/* Dynamic relocations are unsupported. This section is only used to detect relocatable code in
the input files and raise an error if relocatable code is found */
- .got :
+ .got (NOLOAD) :
{
- __sgot = ABSOLUTE(.);
KEEP(*(.got .got.*));
- __egot = ABSOLUTE(.);
- } > FLASH
+ }
/* ## Discarded sections */
/DISCARD/ :
@@ -138,67 +137,56 @@ SECTIONS
}
}
-/* # User overridable symbols II */
-/* (The user overridable symbols are split in two parts because LLD demands that the RHS of PROVIDE
- to be defined before the PROVIDE invocation) */
-/* Lets the user override this to place .text a bit further than the vector table. Required by
-microcontrollers that store their configuration right after the vector table. */
-PROVIDE(_stext = __einterrupts);
+/* Do not exceed this mark in the error messages below | */
+/* # Alignment checks */
+ASSERT(ORIGIN(FLASH) % 4 == 0, "
+ERROR(cortex-m-rt): the start of the FLASH region must be 4-byte aligned");
-/* # Hardcoded symbols */
-/* Place `.bss` at the start of the RAM region */
-__sidata = LOADADDR(.data);
-/* Place the heap right after `.bss` and `.data` */
-__sheap = __ebss;
+ASSERT(ORIGIN(RAM) % 4 == 0, "
+ERROR(cortex-m-rt): the start of the RAM region must be 4-byte aligned");
-/* # Sanity checks */
+ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, "
+BUG(cortex-m-rt): .data is not 4-byte aligned");
-/* Do not exceed this mark in the error messages below | */
-ASSERT(__reset_vector == ORIGIN(FLASH) + 0x8, "
-cortex-m-rt: The reset vector is missing. This is a bug in cortex-m-rt. Please file a bug
-report at: https://github.com/japaric/cortex-m-rt/issues");
-
-ASSERT(__eexceptions - ORIGIN(FLASH) == 0x40, "
-cortex-m-rt: The exception vectors are missing. This is a bug in cortex-m-rt. Please file
-a bug report at: https://github.com/japaric/cortex-m-rt/issues");
-
-ASSERT(__sheap >= __ebss, "
-cortex-m-rt: The heap overlaps with the .bss section. This is a bug in cortex-m-rt. Please
-file a bug report at: https://github.com/japaric/cortex-m-rt/issues");
-
-ASSERT(__sheap >= __edata, "
-cortex-m-rt: The heap overlaps with the .data section. This is a bug in cortex-m-rt.
-Please file a bug report at: https://github.com/japaric/cortex-m-rt/issues");
-
-ASSERT(__einterrupts - __eexceptions > 0, "
-cortex-m-rt: The interrupt vectors are missing. Possible solutions, from most likely to
-less likely:
-- Link to a device crate
-- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency
- may be enabling it)
-- Supply the interrupt handlers yourself. Check the documentation for details.");
+ASSERT(__sidata % 4 == 0, "
+BUG(cortex-m-rt): the LMA of .data is not 4-byte aligned");
+
+ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, "
+BUG(cortex-m-rt): .bss is not 4-byte aligned");
-ASSERT(__einterrupts <= _stext, "
-cortex-m-rt: The '.text' section can't be placed inside the '.vector_table' section. Set
-'_stext' to an address greater than '__einterrupts' (cf. `nm` output)");
+ASSERT(__sheap % 4 == 0, "
+BUG(cortex-m-rt): start of .heap is not 4-byte aligned");
-ASSERT(_stext < ORIGIN(FLASH) + LENGTH(FLASH), "
-cortex-m-rt The '.text' section must be placed inside the FLASH memory. Set '_stext' to an
-address smaller than 'ORIGIN(FLASH) + LENGTH(FLASH)");
+/* # Position checks */
-/* This has been temporarily omitted because it's not supported by LLD */
-/* ASSERT(__sbss % 4 == 0 && __ebss % 4 == 0, " */
-/* .bss is not 4-byte aligned at its boundaries. This is a cortex-m-rt bug."); */
+/* ## .vector_table */
+ASSERT(__reset_vector == ADDR(.vector_table) + 0x8, "
+BUG(cortex-m-rt): the reset vector is missing");
-/* ASSERT(__sdata % 4 == 0 && __edata % 4 == 0, " */
-/* .data is not 4-byte aligned at its boundaries. This is a cortex-m-rt bug."); */
+ASSERT(__eexceptions == ADDR(.vector_table) + 0x40, "
+BUG(cortex-m-rt): the exception vectors are missing");
-/* ASSERT(__sidata % 4 == 0, " */
-/* __sidata is not 4-byte aligned. This is a cortex-m-rt bug."); */
+ASSERT(SIZEOF(.vector_table) > 0x40, "
+ERROR(cortex-m-rt): The interrupt vectors are missing.
+Possible solutions, from most likely to less likely:
+- Link to a svd2rust generated device crate
+- Disable the 'device' feature of cortex-m-rt to build a generic application (a dependency
+may be enabling it)
+- Supply the interrupt handlers yourself. Check the documentation for details.");
-ASSERT(__sgot == __egot, "
-.got section detected in the input object files. Dynamic relocations are not supported.
-If you are linking to C code compiled using the `cc` crate then modify your build script
-to compile the C code _without_ the -fPIC flag. See the documentation of the
-`cc::Build.pic` method for details.");
+/* ## .text */
+ASSERT(ADDR(.vector_table) + SIZEOF(.vector_table) <= _stext, "
+ERROR(cortex-m-rt): The .text section can't be placed inside the .vector_table section
+Set _stext to an address greater than the end of .vector_table (See output of `nm`)");
+
+ASSERT(_stext + SIZEOF(.text) < ORIGIN(FLASH) + LENGTH(FLASH), "
+ERROR(cortex-m-rt): The .text section must be placed inside the FLASH memory.
+Set _stext to an address smaller than 'ORIGIN(FLASH) + LENGTH(FLASH)'");
+
+/* # Other checks */
+ASSERT(SIZEOF(.got) == 0, "
+ERROR(cortex-m-rt): .got section detected in the input object files
+Dynamic relocations are not supported. If you are linking to C code compiled using
+the 'cc' crate then modify your build script to compile the C code _without_
+the -fPIC flag. See the documentation of the `cc::Build.pic` method for details.");
/* Do not exceed this mark in the error messages above | */