Skip to content

Commit

Permalink
Merge pull request #236 from rust-embedded/clean_linker_file
Browse files Browse the repository at this point in the history
Fix linker file for RISCV-64 targets
  • Loading branch information
romancardenas authored Nov 8, 2024
2 parents afc3efb + 8f57be8 commit fdc3bb6
Show file tree
Hide file tree
Showing 5 changed files with 318 additions and 174 deletions.
26 changes: 26 additions & 0 deletions riscv-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Changed

- `link.x.in`: remove references to `eh_frame`.
- Rename start/end section symbols to align with `cortex-m-rt`:
- `_stext`: it remains, as linker files can modify it.
- `__stext`: it coincides with `_stext`.
- `__etext`: new symbol. It points to the end of the text section.
- `__srodata`: new symbol. It points to the start of the read-only data section.
- `__erodata`: new symbol. It points to the end of the read-only data section.
- `__sdata`: substitutes `_sdata`. It points to the start of the on-flash data section.
- `__edata`: substitutes `_edata`. It points to the end of the on-flash data section.
- `__idata`: substitutes `_idata`. It points to the start of the on-RAM data section.
- `__sbss`: substitutes `_sbss`. It points to the start of the BSS section.
- `__ebss`: substitutes `_ebss`. It points to the end of the BSS section.
- `__sheap`: substitutes `_sheap`. It points to the start of the heap section.
- `__eheap`: substitutes `_eheap`. It points to the end of the heap section.
- `__estack`: substitutes `_estack`. It points to the end of the stack section.
- `__sstack`: substitutes `_sstack`. It points to the start of the stack section.
- `__edata` and `__ebss` are now defined outside of their respective sections.
In this way, users can inject custom sections and benefit from the copying and
zeroing routines, respectively.
- As `__sheap` is now private, `riscv-rt` now provides a `heap_start` function to
allow users get the initial address of the heap when initializing an allocator.
- Update documentation.
- Removed `.init.rust` section, as it is no longer required.

## [v0.13.0] - 2024-10-19

### Added
Expand Down
2 changes: 1 addition & 1 deletion riscv-rt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ riscv-pac = { path = "../riscv-pac", version = "0.2.0" }
riscv-rt-macros = { path = "macros", version = "0.2.2" }

[dev-dependencies]
panic-halt = "0.2.0"
panic-halt = "1.0.0"

[features]
s-mode = ["riscv-rt-macros/s-mode"]
Expand Down
75 changes: 46 additions & 29 deletions riscv-rt/link.x.in
Original file line number Diff line number Diff line change
Expand Up @@ -100,65 +100,88 @@ SECTIONS

.text _stext :
{
__stext = .;

/* Put reset handler first in .text section so it ends up as the entry */
/* point of the program. */
KEEP(*(.init));
KEEP(*(.init.rust));
. = ALIGN(4);
KEEP(*(.init.trap));
. = ALIGN(4);
*(.trap);
*(.trap.rust);
*(.text.abort);
*(.text .text.*);

. = ALIGN(4);
__etext = .;
} > REGION_TEXT

.rodata : ALIGN(4)
{
. = ALIGN(4);
__srodata = .;

*(.srodata .srodata.*);
*(.rodata .rodata.*);

/* 4-byte align the end (VMA) of this section.
/* ${ARCH_WIDTH}-byte align the end (VMA) of this section.
This is required by LLD to ensure the LMA of the following .data
section will have the correct alignment. */
. = ALIGN(4);
. = ALIGN(${ARCH_WIDTH});
__erodata = .;
} > REGION_RODATA

.data : ALIGN(${ARCH_WIDTH})
{
_sidata = LOADADDR(.data);
_sdata = .;
. = ALIGN(${ARCH_WIDTH});
__sdata = .;

/* Must be called __global_pointer$ for linker relaxations to work. */
PROVIDE(__global_pointer$ = . + 0x800);
*(.sdata .sdata.* .sdata2 .sdata2.*);
*(.data .data.*);
. = ALIGN(${ARCH_WIDTH});
_edata = .;

} > REGION_DATA AT > REGION_RODATA

/* Allow sections from user `memory.x` injected using `INSERT AFTER .data` to
* use the .data loading mechanism by pushing __edata. Note: do not change
* output region or load region in those user sections! */
. = ALIGN(${ARCH_WIDTH});
__edata = .;

/* LMA of .data */
__sidata = LOADADDR(.data);

.bss (NOLOAD) : ALIGN(${ARCH_WIDTH})
{
_sbss = .;
*(.sbss .sbss.* .bss .bss.*);
. = ALIGN(${ARCH_WIDTH});
_ebss = .;
__sbss = .;

*(.sbss .sbss.* .bss .bss.*);
} > REGION_BSS

/* Allow sections from user `memory.x` injected using `INSERT AFTER .bss` to
* use the .bss zeroing mechanism by pushing __ebss. Note: do not change
* output region or load region in those user sections! */
. = ALIGN(${ARCH_WIDTH});
__ebss = .;

/* fictitious region that represents the memory available for the heap */
.heap (NOLOAD) :
{
_sheap = .;
__sheap = .;
. += _heap_size;
. = ALIGN(4);
_eheap = .;
__eheap = .;
} > REGION_HEAP

/* fictitious region that represents the memory available for the stack */
.stack (NOLOAD) :
{
_estack = .;
__estack = .;
. = ABSOLUTE(_stack_start);
_sstack = .;
__sstack = .;
} > REGION_STACK

/* fake output .got section */
Expand All @@ -169,9 +192,6 @@ SECTIONS
{
KEEP(*(.got .got.*));
}

.eh_frame (INFO) : { KEEP(*(.eh_frame)) }
.eh_frame_hdr (INFO) : { *(.eh_frame_hdr) }
}

/* Do not exceed this mark in the error messages above | */
Expand All @@ -187,25 +207,22 @@ ERROR(riscv-rt): the start of the REGION_DATA must be ${ARCH_WIDTH}-byte aligned
ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned");

ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned");

ASSERT(ORIGIN(REGION_STACK) % 4 == 0, "
ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned");

ASSERT(_stext % 4 == 0, "
ERROR(riscv-rt): `_stext` must be 4-byte aligned");

ASSERT(_sdata % ${ARCH_WIDTH} == 0 && _edata % ${ARCH_WIDTH} == 0, "
ASSERT(__sdata % ${ARCH_WIDTH} == 0 && __edata % ${ARCH_WIDTH} == 0, "
BUG(riscv-rt): .data is not ${ARCH_WIDTH}-byte aligned");

ASSERT(_sidata % ${ARCH_WIDTH} == 0, "
ASSERT(__sidata % ${ARCH_WIDTH} == 0, "
BUG(riscv-rt): the LMA of .data is not ${ARCH_WIDTH}-byte aligned");

ASSERT(_sbss % ${ARCH_WIDTH} == 0 && _ebss % ${ARCH_WIDTH} == 0, "
ASSERT(__sbss % ${ARCH_WIDTH} == 0 && __ebss % ${ARCH_WIDTH} == 0, "
BUG(riscv-rt): .bss is not ${ARCH_WIDTH}-byte aligned");

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

ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
Expand All @@ -216,11 +233,11 @@ ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, "
ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts.
Consider changing `_max_hart_id` or `_hart_stack_size`.");

/* # Other checks */
ASSERT(SIZEOF(.got) == 0, "
.got section detected in the input files. Dynamic relocations are not
supported. If you are linking to C code compiled using the `gcc` crate
then modify your build script to compile the C code _without_ the
-fPIC flag. See the documentation of the `gcc::Config.fpic` method for
details.");
ERROR(riscv-rt): .got section detected in the input 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 | */
10 changes: 5 additions & 5 deletions riscv-rt/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ cfg_global_asm!(
cfg_global_asm!(
"call __pre_init
// Copy .data from flash to RAM
la t0, _sdata
la t2, _edata
la t1, _sidata
la t0, __sdata
la t2, __edata
la t1, __sidata
bgeu t0, t2, 2f
1: ",
#[cfg(target_arch = "riscv32")]
Expand All @@ -171,8 +171,8 @@ cfg_global_asm!(
bltu t0, t2, 1b",
"
2: // Zero out .bss
la t0, _sbss
la t2, _ebss
la t0, __sbss
la t2, __ebss
bgeu t0, t2, 4f
3: ",
#[cfg(target_arch = "riscv32")]
Expand Down
Loading

0 comments on commit fdc3bb6

Please sign in to comment.