llvm / llvm/llvm-project

ld.lld: Linker script `.` counts from zero in non-SHF_ALLOC sections

Open
#202,266 9 comments 1 reaction 0 assignees View on GitHub
lld:ELF
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.