Skip to content

Commit 721f107

Browse files
authored
Merge pull request #127 from rust-embedded/new_build
build.rs now adapts link.x for the target arch
2 parents 0383469 + f2b1dea commit 721f107

File tree

4 files changed

+56
-196
lines changed

4 files changed

+56
-196
lines changed

riscv-rt/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2020
- Removed bors in favor of GitHub Merge Queue
2121
- `start_trap_rust` is now marked as `unsafe`
2222
- Implement `r0` as inline assembly
23+
- Use `${ARCH_WIDTH}` in `link.x.in` to adapt to different archs
2324
- mhartid CSR is no longer read in single-hart mode, assumed zero
2425
- Ensure stack pointer is 16-byte aligned before jumping to Rust entry point
2526

riscv-rt/build.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
// NOTE: Adapted from cortex-m/build.rs
22

33
use riscv_target::Target;
4-
use std::env;
5-
use std::fs;
6-
use std::path::PathBuf;
4+
use std::{env, fs, io, path::PathBuf};
5+
6+
fn add_linker_script(arch_width: u32) -> io::Result<()> {
7+
// Read the file to a string and replace all occurrences of ${ARCH_WIDTH} with the arch width
8+
let mut content = fs::read_to_string("link.x.in")?;
9+
content = content.replace("${ARCH_WIDTH}", &arch_width.to_string());
710

8-
fn add_linker_script(bytes: &[u8]) {
911
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
1012

1113
// Put the linker script somewhere the linker can find it
12-
fs::write(out_dir.join("link.x"), bytes).unwrap();
14+
fs::write(out_dir.join("link.x"), content)?;
1315
println!("cargo:rustc-link-search={}", out_dir.display());
1416
println!("cargo:rerun-if-changed=link.x");
17+
18+
Ok(())
1519
}
1620

1721
fn main() {
@@ -22,19 +26,24 @@ fn main() {
2226
if target.starts_with("riscv") {
2327
println!("cargo:rustc-cfg=riscv");
2428
let target = Target::from_target_str(&target);
25-
match target.bits {
29+
30+
// generate the linker script
31+
let arch_width = match target.bits {
2632
32 => {
2733
println!("cargo:rustc-cfg=riscv32");
28-
add_linker_script(include_bytes!("link-rv32.x"));
34+
4
2935
}
3036
64 => {
3137
println!("cargo:rustc-cfg=riscv64");
32-
add_linker_script(include_bytes!("link-rv64.x"));
38+
8
3339
}
3440
_ => panic!("Unsupported bit width"),
35-
}
41+
};
42+
add_linker_script(arch_width).unwrap();
43+
44+
// expose the ISA extensions
3645
if target.has_extension('m') {
37-
println!("cargo:rustc-cfg=riscvm"); // we can expose extensions this way
46+
println!("cargo:rustc-cfg=riscvm");
3847
}
3948
}
4049
}

riscv-rt/link-rv64.x

Lines changed: 0 additions & 174 deletions
This file was deleted.

riscv-rt/link-rv32.x renamed to riscv-rt/link.x.in

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
1+
/* # Developer notes
2+
3+
- Symbols that start with a double underscore (__) are considered "private"
4+
5+
- Symbols that start with a single underscore (_) are considered "semi-public"; they can be
6+
overridden in a user linker script, but should not be referred from user code (e.g. `extern "C" {
7+
static mut _heap_size }`).
8+
9+
- `EXTERN` forces the linker to keep a symbol in the final binary. We use this to make sure a
10+
symbol if not dropped if it appears in or near the front of the linker arguments and "it's not
11+
needed" by any of the preceding objects (linker arguments)
12+
13+
- `PROVIDE` is used to provide default values that can be overridden by a user linker script
14+
15+
- In this linker script, you may find symbols that look like `${...}` (e.g., `${ARCH_WIDTH}`).
16+
These are wildcards used by the `build.rs` script to adapt to different target particularities.
17+
Check `build.rs` for more details about these symbols.
18+
19+
- On alignment: it's important for correctness that the VMA boundaries of both .bss and .data *and*
20+
the LMA of .data are all `${ARCH_WIDTH}`-byte aligned. These alignments are assumed by the RAM
21+
initialization routine. There's also a second benefit: `${ARCH_WIDTH}`-byte aligned boundaries
22+
means that you won't see "Address (..) is out of bounds" in the disassembly produced by `objdump`.
23+
*/
24+
125
PROVIDE(_stext = ORIGIN(REGION_TEXT));
226
PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK));
327
PROVIDE(_max_hart_id = 0);
@@ -72,23 +96,23 @@ SECTIONS
7296
. = ALIGN(4);
7397
} > REGION_RODATA
7498

75-
.data : ALIGN(4)
99+
.data : ALIGN(${ARCH_WIDTH})
76100
{
77101
_sidata = LOADADDR(.data);
78102
_sdata = .;
79103
/* Must be called __global_pointer$ for linker relaxations to work. */
80104
PROVIDE(__global_pointer$ = . + 0x800);
81105
*(.sdata .sdata.* .sdata2 .sdata2.*);
82106
*(.data .data.*);
83-
. = ALIGN(4);
107+
. = ALIGN(${ARCH_WIDTH});
84108
_edata = .;
85109
} > REGION_DATA AT > REGION_RODATA
86110

87-
.bss (NOLOAD) : ALIGN(4)
111+
.bss (NOLOAD) : ALIGN(${ARCH_WIDTH})
88112
{
89113
_sbss = .;
90114
*(.sbss .sbss.* .bss .bss.*);
91-
. = ALIGN(4);
115+
. = ALIGN(${ARCH_WIDTH});
92116
_ebss = .;
93117
} > REGION_BSS
94118

@@ -129,8 +153,8 @@ ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");
129153
ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, "
130154
ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned");
131155

132-
ASSERT(ORIGIN(REGION_DATA) % 4 == 0, "
133-
ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned");
156+
ASSERT(ORIGIN(REGION_DATA) % ${ARCH_WIDTH} == 0, "
157+
ERROR(riscv-rt): the start of the REGION_DATA must be ${ARCH_WIDTH}-byte aligned");
134158

135159
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
136160
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");
@@ -144,14 +168,14 @@ ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");
144168
ASSERT(_stext % 4 == 0, "
145169
ERROR(riscv-rt): `_stext` must be 4-byte aligned");
146170

147-
ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, "
148-
BUG(riscv-rt): .data is not 4-byte aligned");
171+
ASSERT(_sdata % ${ARCH_WIDTH} == 0 && _edata % ${ARCH_WIDTH} == 0, "
172+
BUG(riscv-rt): .data is not ${ARCH_WIDTH}-byte aligned");
149173

150-
ASSERT(_sidata % 4 == 0, "
151-
BUG(riscv-rt): the LMA of .data is not 4-byte aligned");
174+
ASSERT(_sidata % ${ARCH_WIDTH} == 0, "
175+
BUG(riscv-rt): the LMA of .data is not ${ARCH_WIDTH}-byte aligned");
152176

153-
ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, "
154-
BUG(riscv-rt): .bss is not 4-byte aligned");
177+
ASSERT(_sbss % ${ARCH_WIDTH} == 0 && _ebss % ${ARCH_WIDTH} == 0, "
178+
BUG(riscv-rt): .bss is not ${ARCH_WIDTH}-byte aligned");
155179

156180
ASSERT(_sheap % 4 == 0, "
157181
BUG(riscv-rt): start of .heap is not 4-byte aligned");

0 commit comments

Comments
 (0)