-
Notifications
You must be signed in to change notification settings - Fork 85
LLD support (AKA LLD *almost* works out of the box) #53
Comments
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/app
Reading symbols from target/thumbv7m-none-eabi/debug/app...done.
(gdb) target remote :3333
Remote debugging using :3333
0xfffffffe in ?? ()
(gdb) load
Loading section .vector_table, size 0x400 lma 0x8000000
Loading section .text, size 0x60ea lma 0x8000400
Loading section .rodata, size 0x1804 lma 0x80064f0
Loading section .data, size 0x10 lma 0x8007cee
Remote connection closed $ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg
(..)
Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'gdb' connection on tcp/3333
Info : device id = 0x20036410
Info : flash size = 64kbytes
target halted due to debug-request, current mode: Thread
xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
Info : 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 --version
LLD 7.0.0 (git://github.com/llvm-mirror/lld.git bceb08ce5f0055cee953673a3e098fef868a18d4) (compatible with GNU linkers)
$ xargo build
error: 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). $ arm-none-eabi-size -Ax target/thumbv7m-none-eabi/debug/app | grep rodata
.rodata 0x1804 0x80064f0
$ arm-none-eabi-nm -C target/thumbv7m-none-eabi/debug/app | grep sidata
08007cee A _sidata This shows that indeed 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. |
this commit adds LLD support by removing all INFO sections. LLD kind of supports INFO in the form of NOLOAD but when the linker script contains NOLOAD sections LLD emits a binary with false `size` information: for example, it reported a fake increase of 20KB in .text and a fake increase of 1KB in .bss when compiling a program that only allocates a single Box. As the INFO sections are gone we can no longer support the stack overflow protection added in #43 so all the other related changes, like making _stack_start overridable, have been removed as well. If you want to continue using stack overflow protection you can stick to v0.3.x. As the .debug_gdb_scripts output section has been removed from the linker script these changes will only reliably support both LD and LLD if/when rust-lang/rust#49728 lands. closes #53
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 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 ( $ arm-none-eabi-size -Ax target/thumbv7em-none-eabihf/debug/app | grep rodata
.rodata 0x4 0x80007a0
$ arm-none-eabi-nm -C target/thumbv7em-none-eabihf/debug/app | grep sidata
080007a4 A _sidata (with rustc LLD I get We probably only have to backport the fix. |
If you switch the linker from arm-none-eabi-ld to ld.lld you'll get the following error:
But if you modify this crate link.x like this:
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
: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.
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).
The text was updated successfully, but these errors were encountered: