You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Jan 24, 2022. It is now read-only.
Repository navigation
This repository was archived by the owner on Jan 24, 2022. It is now read-only.
LLD support (AKA LLD *almost* works out of the box) #53
If you switch the linker from arm-none-eabi-ld to ld.lld you'll get the following error:
$ ld.lld --versionLLD 7.0.0 (https://github.com/llvm-mirror/lld 527f7fd20d23a54ae30ccdf5071312b24e28776b) (compatible with GNU linkers)
$ xargo builderror: linking with `ld.lld` failed: exit code: 1 | = note: "ld.lld" (..) = note: ld.lld: error: $PWD/target/thumbv7em-none-eabihf/debug/build/cortex-m-rt-f07298b7bbb47f59/out/link.x:92: NOLOAD expected, but got INFO >>> .debug_gdb_scripts _stext (INFO) : { >>> ^
But if you modify this crate link.x like this:
/* 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) : {+ .debug_gdb_scripts _stext (NOLOAD) : {
KEEP(*(.debug_gdb_scripts))
- }+ } > FLASH
Programs link correctly. The resulting binaries are well formed and debug information works. 🎉
However, this results in an artifical increase of size of the text section as reported by arm-none-eabi-size:
$ # before (linked with GNU ld)
$ arm-none-eabi-size (..) text data bss dec hex filename 1300 0 0 1300 514 (..)
$ arm-none-eabi-size -Ax (..)section size addr.vector_table 0x188 0x8000000.text 0x384 0x8000188.rodata 0x8 0x800050c.bss 0x0 0x20000000.data 0x0 0x20000000.debug_gdb_scripts 0x88 0x8000188
$ # after (linked with GNU ld)
$ arm-none-eabi-size (..) text data bss dec hex filename 1436 0 0 1436 59c (..)
$ arm-none-eabi-size -Ax (..)section size addr.vector_table 0x188 0x8000000.text 0x384 0x8000188.rodata 0x8 0x800050c.bss 0x0 0x20000000.data 0x0 0x20000000.debug_gdb_scripts 0x88 0x8000188 <- NOTE overlaps with .text
$ # after (linked with LLVM lld)
$ arm-none-eabi-size (..) text data bss dec hex filename 1436 0 0 1436 59c (..)
$ arm-none-eabi-size -Ax (..)section size addr.vector_table 0x188 0x8000000.text 0x384 0x8000188.rodata 0x8 0x800050c.bss 0x0 0x20000000.data 0x0 0x20000000.got 0x0 0x20000000.debug_gdb_scripts 0x88 0x8000514 <- NOTE comes after .text
This is just an error in the report though. The .debug_gdb_scripts doesn't end up in FLASH even with the linker script changes.
> # GDB console after flashing the binary linked using LLD
> x/12x 0x80005140x8000514 <__rustc_debug_gdb_scripts_section__>: 0xffffffff 0xffffffff 0xffffffff 0xffffffff0x8000524 <__rustc_debug_gdb_scripts_section__+16>: 0xffffffff 0xffffffff 0xffffffff 0xffffffff0x8000534 <__rustc_debug_gdb_scripts_section__+32>: 0xffffffff 0xffffffff 0xffffffff 0xffffffff
This issue is to gauge interested in adding LLD support right now (by applying the above diff).
Alternatively we can hold off until LLD lands in rustc (hopefully sometime this year) since it's only then when we'll be able to drop the dependency on a external linker (arm-none-eabi-ld).
update: Once PR rust-lang/rust#48125 lands a standalone LLD (version 6.0) binary will ship with the Rust distribution on some (all?) tier 1 platforms. We'll be able to use that lld to link ARM Cortex-M binaries so we should revisit this issue after that PR lands.
Update: LLD is now being shipped with the Rust toolchain. You'll need Xargo v0.3.11 to be able to use it though.
I was testing this again and had to patch things a bit more after #43 landed:
diff --git a/link.x b/link.x
index 6f39655..64bf73b 100644
--- a/link.x+++ b/link.x@@ -56,11 +56,11 @@ SECTIONS
/* 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);- }+ /* /\* 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)
@@ -84,11 +84,11 @@ SECTIONS
_sheap = _edata;
_eheap = _sheap + _heap_size;
- /* fictitious region that represents the memory available for the heap */- .heap _sheap (INFO) : ALIGN(4)- {- . += _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
@@ -114,9 +114,9 @@ SECTIONS
/* 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) : {+ .debug_gdb_scripts _stext (NOLOAD) : {
KEEP(*(.debug_gdb_scripts))
- }+ } > FLASH
/DISCARD/ :
{
(This actually breaks cortex-m-rt-ld but it doesn't matter right now as I'm just testing LLD)
It seems to me that LLD is producing bad binaries in some cases: when flashing the allocator example from cortex-m-quickstart v0.2.5 I get a segfault in OpenOCD:
$ # compiled using the LLD in $(rustc --print sysroot)
$ arm-none-eabi-gdb -q target/thumbv7m-none-eabi/debug/appReading symbols from target/thumbv7m-none-eabi/debug/app...done.(gdb) target remote :3333Remote debugging using :33330xfffffffe in ?? ()(gdb) loadLoading section .vector_table, size 0x400 lma 0x8000000Loading section .text, size 0x60ea lma 0x8000400Loading section .rodata, size 0x1804 lma 0x80064f0Loading section .data, size 0x10 lma 0x8007ceeRemote connection closed
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg(..)Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpointsInfo : accepting 'gdb' connection on tcp/3333Info : device id = 0x20036410Info : flash size = 64kbytestarget halted due to debug-request, current mode: ThreadxPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffcInfo : Padding image section 0 with 6 bytes[1] 3342 segmentation fault (core dumped) openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
I was wondering if this was a bug in the LLD version shipped with the toolchain so I tried a more recent version and I got this error:
$ ld.lld --versionLLD 7.0.0 (git://github.com/llvm-mirror/lld.git bceb08ce5f0055cee953673a3e098fef868a18d4) (compatible with GNU linkers)
$ xargo builderror: linking with `ld.lld` failed: exit code: 1 | = note: "ld.lld" "-L" (..) = note: ld.lld: error: section .rodata load address range overlaps with .data >>> .rodata range is [0x80064F0, 0x8007CF3] >>> .data range is [0x8007CEE, 0x8007CFD]
which I don't understand because the program does fit in Flash memory -- GNU LD can link it within the memory constraints.
So I went back to inspect the binary linked using rustc's LLD (version 6.0).
This shows that indeed .rodata, which spans [0x80064f0, 0x8007cf3], is overlapping with the load memory of .data, which starts at address 0x08007cee. This doesn't occur in the binary linked using GNU LD; there the LMA is equal to the end address of .rodata (no overlap).
So it seems that LLD is not ready for prime time yet. It would be great to report this issue or see if it has already been reported in LLVM's bug tracker. Unfortunately, I won't have time to follow up on that.
Turns out the overlap problem I mentioned above also occurs with GNU LD in some scenarios (I don't know the exact cause). However, #63 fixes the issue for both LD and LLD. Will re-test LLD in a bit.
So .rodata is [0x800007a0, 0x800007a4] and .data starts at [0x080007a2].
Looking at the symbol table in detail:
$ arm-none-eabi-objdump -t target/thumbv7em-none-eabihf/debug/examples/minimal
target/thumbv7em-none-eabihf/debug/examples/minimal: file format elf32-littlearm
SYMBOL TABLE:
08000040 l O .vector_table 000003c0 _ZN7minimal10INTERRUPTS17h7464d2ddc3029b6cE
080004d8 l F .text 00000006 _ZN7minimal15default_handler17h114b49b69a086ceaE
20000000 l O .data 00000004 _ZN7minimal4TICK17ha5ad9028c8af9fbfE
080004ae l F .text 0000002a _ZN7minimal4main17hd2384a11f0fa43e7E
08000004 l O .vector_table 00000004 _ZN11cortex_m_rt12RESET_VECTOR17he036e15b38aad01bE
08000400 l F .text 00000062 _ZN11cortex_m_rt13reset_handler17he9975823b9c4d19dE
0800050e l F .text 0000001e _ZN11cortex_m_rt13reset_handler4main17hb8aca15aff884cf3E
0800052c l F .text 0000000e _ZN11cortex_m_rt15default_handler17h529c8bd85d78d9daE
08000462 l F .text 0000002a .hidden _ZN11cortex_m_rt10lang_items5start17h06853a5574522047E
0800048c l F .text 00000022 .hidden _ZN4core3num21_$LT$impl$u20$u32$GT$12wrapping_add17h04659799d93a58e6E
080004de g F .text 00000030 main
080005f6 g F .text 00000012 _ZN4core3mem6zeroed17hb3ed4c80b6965fd6E
0800053a w F .text 0000000a BUS_FAULT
0800053a w F .text 0000000a DEBUG_MONITOR
0800053a w F .text 0000000a DEFAULT_HANDLER
08000008 g O .vector_table 00000038 EXCEPTIONS
0800053a w F .text 0000000a HARD_FAULT
0800053a w F .text 0000000a MEM_MANAGE
0800053a w F .text 0000000a NMI
0800053a w F .text 0000000a PENDSV
0800053a w F .text 0000000a SVCALL
0800053a w F .text 0000000a SYS_TICK
0800053a w F .text 0000000a USAGE_FAULT
080006a0 g F .text 00000024 _ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$6offset17hcf0d1f6785eda00eE
080006c4 g F .text 00000004 _ZN4core3ptr4null17hbdffd19ec01e4a11E
080006c8 g F .text 00000018 _ZN4core3ptr5write17h2066dcf92f7e2ad9E
08000544 g F .text 0000004a _ZN2r08zero_bss17h7ad2bf41c077011dE
0800058e g F .text 00000068 _ZN2r09init_data17h861ee0448484f224E
0800076c g F .text 00000024 _ZN8cortex_m10peripheral3SCB10enable_fpu17h80d211e9d53267a5E
080006e0 g F .text 0000008c _ZN8cortex_m10peripheral3SCB19set_fpu_access_mode17h5a760d49cb9277eeE
08000682 g F .text 00000010 _ZN40_$LT$bare_metal..Peripheral$LT$T$GT$$GT$3get17hb0a006b9114bda39E
08000692 g F .text 0000000e _ZN4core3mem13uninitialized17h748acbeff95d4744E
08000790 g F .text 0000000e _ZN40_$LT$core..cell..UnsafeCell$LT$T$GT$$GT$3get17ha98494ecb41d2659E
08000608 g F .text 0000001a _ZN4core3ptr13read_volatile17h67d516ad79d70fe2E
08000622 g F .text 0000001a _ZN4core3ptr14write_volatile17h2ab28f223f4d509bE
0800063c g F .text 00000024 _ZN4core3ptr33_$LT$impl$u20$$BP$const$u20$T$GT$6offset17h3f8f4ebea9f8c4d8E
08000660 g F .text 00000022 _ZN4core3ptr4read17h695db441e027dbf6E
20050000 g *ABS* 00000000 _stack_start
08000400 g .vector_table 00000000 _einterrupts
08000400 g .vector_table 00000000 _stext
20000000 g *ABS* 00000000 _sbss
20000004 g .data 00000000 _edata
08000040 g .vector_table 00000000 _eexceptions
20000004 g .got 00000000 _sgot
20000004 g .got 00000000 _egot
20000000 g .bss 00000000 _ebss
20000000 g .data 00000000 _sdata
080007a2 g *ABS* 00000000 _sidata
08000000 g .vector_table 00000000 _svector_table
20000004 g .data 00000000 _sheap
The last function in .text is [0x08000790, 0x0800079e] (core::cell::UnsafeCell::get())
08000790 g F .text 0000000e _ZN40_$LT$core..cell..UnsafeCell$LT$T$GT$$GT$3get17ha98494ecb41d2659E
The first (and only) entry in .data is
20000000 l O .data 00000004 _ZN7minimal4TICK17ha5ad9028c8af9fbfE
which presumably is being loaded from [0x0800079e, 0x080007a2] if _sidata
is [0x080007a2,...], but this conflicts with .rodata at [0x800007a0, 0x800007a4], which is causing the problems.
So it looks like lld is not respecting the .rodata alignment when writing out the initializer.
This appears to be fixed in the latest LLD (LLD 7.0.0 (git://github.com/llvm-mirror/lld.git 31f297161e44ba84e5e257a9213e32dc73b540e3) (compatible with GNU linkers)). I get:
Activity
japaric commentedon Feb 10, 2018
update: Once PR rust-lang/rust#48125 lands a standalone LLD (version 6.0) binary will ship with the Rust distribution on some (all?) tier 1 platforms. We'll be able to use that lld to link ARM Cortex-M binaries so we should revisit this issue after that PR lands.
japaric commentedon Mar 9, 2018
Update: LLD is now being shipped with the Rust toolchain. You'll need Xargo v0.3.11 to be able to use it though.
I was testing this again and had to patch things a bit more after #43 landed:
(This actually breaks cortex-m-rt-ld but it doesn't matter right now as I'm just testing LLD)
It seems to me that LLD is producing bad binaries in some cases: when flashing the allocator example from cortex-m-quickstart v0.2.5 I get a segfault in OpenOCD:
I was wondering if this was a bug in the LLD version shipped with the toolchain so I tried a more recent version and I got this error:
which I don't understand because the program does fit in Flash memory -- GNU LD can link it within the memory constraints.
So I went back to inspect the binary linked using rustc's LLD (version 6.0).
This shows that indeed
.rodata, which spans[0x80064f0, 0x8007cf3], is overlapping with the load memory of.data, which starts at address0x08007cee. This doesn't occur in the binary linked using GNU LD; there the LMA is equal to the end address of.rodata(no overlap).So it seems that LLD is not ready for prime time yet. It would be great to report this issue or see if it has already been reported in LLVM's bug tracker. Unfortunately, I won't have time to follow up on that.
japaric commentedon Apr 6, 2018
Turns out the overlap problem I mentioned above also occurs with GNU LD in some scenarios (I don't know the exact cause). However, #63 fixes the issue for both LD and LLD. Will re-test LLD in a bit.
add LLD support
add LLD support
jcsoo commentedon Apr 23, 2018
I'm still seeing the overlap problem when there is static data. I was able to reproduce using cortex-m-quickstart with the following changes:
.cargo/config
Cargo.toml
examples/minimal.rs
So .rodata is [0x800007a0, 0x800007a4] and .data starts at [0x080007a2].
Looking at the symbol table in detail:
The last function in .text is [0x08000790, 0x0800079e] (core::cell::UnsafeCell::get())
The first (and only) entry in .data is
which presumably is being loaded from [0x0800079e, 0x080007a2] if _sidata
is [0x080007a2,...], but this conflicts with .rodata at [0x800007a0, 0x800007a4], which is causing the problems.
So it looks like lld is not respecting the .rodata alignment when writing out the initializer.
japaric commentedon Apr 23, 2018
This appears to be fixed in the latest LLD (
LLD 7.0.0 (git://github.com/llvm-mirror/lld.git 31f297161e44ba84e5e257a9213e32dc73b540e3) (compatible with GNU linkers)). I get:(with rustc LLD I get
080007a2 A _sidata)We probably only have to backport the fix.