ld.lld: Linker script `.` counts from zero in non-SHF_ALLOC sections
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Some linker scripts perform pointer arithmetic in non-SHF_ALLOC sections in order to plan memory layout without altering the memory image. For example, [Das U-Boot does this](https://elixir.bootlin.com/u-boot/v2026.04/source/arch/arm/cpu/u-boot.lds#L173) to position its `.bss` at the same address as the runtime relocation information (`.bss` is unused until relocation finishes):
```
.bss ADDR(.rel.dyn) (OVERLAY): {
__bss_start = .;
*(.bss*)
. = ALIGN(4);
__bss_end = .;
}
```
However, LLD since commit ec29538af2e08 places all non-SHF_ALLOC sections at address zero (in compliance with the ELF spec), but this is implemented in a way that is visible via the location counter (`.`) inside the section. In the above example, `__bss_start == 0` due to this issue; however, `__bss_start == ADDR(.rel.dyn)` was expected per the start expression (and is what GNU ld does).
For now, a plausible workaround is to assign `.` the start expression explicitly, e.g.:
```
.bss ADDR(.rel.dyn) (OVERLAY): {
. = ADDR(.rel.dyn); # <<- workaround
__bss_start = .;
*(.bss*)
. = ALIGN(4);
__bss_end = .;
}
```
I am willing to take on this issue and already have a WIP patch that fixes it, but I'm first seeking consensus on my assumptions:
- The `sh_addr` of non-SHF_ALLOC output sections should still be 0.
- The script-observable value of `.` within those sections should be as if the output section was SHF_ALLOC (i.e. equal to the start expression if present, and determined by section alignment of the current position if not).
- The symbols defined within those sections are still section-relative, but because the section base is 0, the symbol offset makes up the full absolute address.
- Assignments to `.` within the non-SHF_ALLOC section are not visible outside the section, as is the case today.
Contributor guide
Research direction
Start with commit ec29538af2e08 and the linked Das U-Boot linker script at arch/arm/cpu/u-boot.lds#L173. Compare LLD's behavior with GNU ld and the ELF-spec interpretation for non-SHF_ALLOC sections. Done means consensus on the four stated assumptions and a validated fix for the location counter behavior.
Written by the indexing model from the issue text.
Assessment
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100