[lld] [ELF] Warn if specified section address is smaller than image base (PR #140187)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Fri May 16 09:42:34 PDT 2025
MaskRay wrote:
Thanks for the analysis!
The GNU ld's text segment concept, often (ab)used to specify the image base, doesn't align well with our layout, which places .rodata before .text and uses the --rosegment option.
Our layout offers advantages like better -z separate-segment and PT_GNU_RELRO support with smaller file size, but it requires adjustments when users specify -Ttext or -Ttext-segment options.
To maintain simpler layout rules, we intentionally reject certain GNU ld behaviors, such as -Ttext-segment (https://reviews.llvm.org/D70468).
When there is a PT_LOAD segment that covers ELF header/program headers but no sections
* In the default --ro-segment case, the output is correct, though it may appear unusual (ignoring the non-ascending p_vaddr for now).
* In the --no-rosegment case, an `error: output file too large` occurs.
I agree that this diagnostic should be elevated to an error for clarity.
I have mild preference that we don't change program header allocation behavior
37 tests that use -Ttext= will need adjustment.
```
Failed Tests (37):
lld :: ELF/aarch64-reloc-implicit-addend.test
lld :: ELF/aarch64-thunk-align.s
lld :: ELF/arm-cmse-diagnostics.s
lld :: ELF/arm-cmse-implib.s
lld :: ELF/arm-cmse-keep-sections.s
lld :: ELF/arm-cmse-noveneers.s
lld :: ELF/arm-cmse-secure.s
lld :: ELF/arm-cmse-veneers.s
lld :: ELF/avr-reloc-error.s
lld :: ELF/basic-avr.s
lld :: ELF/compress-debug-sections-reloc.s
lld :: ELF/eh-frame-value-format7.s
lld :: ELF/eh-frame-value-format8.s
lld :: ELF/gdb-index-dwarf5-type-unit.s
lld :: ELF/gdb-index-icf.s
lld :: ELF/i386-pc16.test
lld :: ELF/i386-pc8.s
lld :: ELF/i386-reloc-16-large-addend.s
lld :: ELF/i386-reloc-8-large-addend.s
lld :: ELF/i386-reloc-large-addend.s
lld :: ELF/i386-reloc-range.s
lld :: ELF/i386-reloc8-reloc16-addend.s
lld :: ELF/just-symbols-cref.s
lld :: ELF/just-symbols.s
lld :: ELF/linkerscript/avr5.test
lld :: ELF/linkerscript/memory-no-sections.test
lld :: ELF/loongarch-pc-aligned.s
lld :: ELF/msp430.s
lld :: ELF/nmagic.s
lld :: ELF/oformat-binary-ttext.s
lld :: ELF/sectionstart-noallochdr.s
lld :: ELF/systemz-reloc-disp12.s
lld :: ELF/systemz-reloc-disp20.s
lld :: ELF/systemz-reloc-pc16.s
lld :: ELF/systemz-reloc-pc32.s
lld :: ELF/x86-64-reloc-32.s
lld :: ELF/x86-64-reloc-pc32.s
```
(Assemble sectionstart.s to a.o)
```
% /tmp/Debug/bin/ld.lld a.o -Ttext=0x3000 -o a && readelf -W -Sl a
ld.lld: warning: section '.text' address (0x3000) is smaller than image base (0x200000); specify --image-base
ld.lld: warning: section '.data' address (0x4001) is smaller than image base (0x200000); specify --image-base
ld.lld: warning: section '.bss' address (0x4005) is smaller than image base (0x200000); specify --image-base
There are 8 section headers, starting at offset 0x1088:
Section Headers:
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 0] NULL 0000000000000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 0000000000003000 001000 000001 00 AX 0 0 4
[ 2] .data PROGBITS 0000000000004001 001001 000004 00 WA 0 0 1
[ 3] .bss NOBITS 0000000000004005 001005 000004 00 WA 0 0 1
[ 4] .comment PROGBITS 0000000000000000 001005 000013 01 MS 0 0 1
[ 5] .symtab SYMTAB 0000000000000000 001018 000030 18 7 1 8
[ 6] .shstrtab STRTAB 0000000000000000 001048 000035 00 0 0 1
[ 7] .strtab STRTAB 0000000000000000 00107d 000008 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), l (large), p (processor specific)
Elf file type is EXEC (Executable file)
Entry point 0x3000
There are 5 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000200040 0x0000000000200040 0x000118 0x000118 R 0x8
LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000158 0x000158 R 0x1000
LOAD 0x001000 0x0000000000003000 0x0000000000003000 0x000001 0x000001 R E 0x1000
LOAD 0x001001 0x0000000000004001 0x0000000000004001 0x000004 0x000008 RW 0x1000
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0
Section to Segment mapping:
Segment Sections...
00
01
02 .text
03 .data .bss
04
% /tmp/Debug/bin/ld.lld --no-rosegment -Ttext 0x3000 a.o -o a3 && readelf -W -Sl a3
ld.lld: warning: section '.text' address (0x3000) is smaller than image base (0x200000); specify --image-base
ld.lld: warning: section '.data' address (0x4001) is smaller than image base (0x200000); specify --image-base
ld.lld: warning: section '.bss' address (0x4005) is smaller than image base (0x200000); specify --image-base
ld.lld: error: output file too large: 18446744073707467400 bytes
section sizes:
.text 1
.data 4
.bss 4
.comment 19
.symtab 48
.shstrtab 53
.strtab 8
```
https://github.com/llvm/llvm-project/pull/140187
More information about the llvm-commits
mailing list