4 Commits

Author SHA1 Message Date
Fangrui Song
3c9d86f951 [ELF][test] Avoid llvm-readelf/llvm-readobj one-dash long options 2021-07-16 10:02:47 -07:00
Fangrui Song
c49f83b6e9 [ELF] Don't advance sh_offset for an empty section whose PT_LOAD is removed (due to p_memsz=0)
removeEmptyPTLoad() removes empty (p_memsz=0) PT_LOAD segments.  In
assignFileOffsets(), setFileOffset() unnecessarily advances file offsets
for containing empty sections.

This is exposed by arm Linux kernel's multi_v5_defconfig
(see https://bugs.llvm.org/show_bug.cgi?id=45632)

```
ld.lld (max-page-size=65536):
  [34] .init.data        PROGBITS        c0c24000 c34000 0128ac 00  WA  0   0 4096
  [35] .text_itcm        PROGBITS        fffe0000 c50000 000000 00  WA  0   0  1
  [36] .data_dtcm        PROGBITS        fffe8000 c58000 000000 00  WA  0   0  1
  [37] .data             PROGBITS        c0c38000 c58000 0647a0 00  WA  0   0 32

arm-linux-gnueabi-ld (max-page-size=65536):
  [23] .init.data        PROGBITS        c0c12000 c22000 0128ac 00  WA  0   0 4096
  [24] .text_itcm        PROGBITS        fffe0000 ca2558 000000 00   W  0   0  1
  [25] .data_dtcm        PROGBITS        fffe8000 ca2558 000000 00   W  0   0  1
  [26] .data             PROGBITS        c0c26000 c36000 0647a0 00  WA  0   0 32
```

This patch clears OutputSection::ptLoad if ptLoad is removed by
removeEmptyPTLoad(). Conceptually this removes "dangling" references.

Reviewed By: psmith

Differential Revision: https://reviews.llvm.org/D79254
2020-05-04 08:07:34 -07:00
Fangrui Song
b498d99338 [ELF] Start a new PT_LOAD if LMA region is different
GNU ld has a counterintuitive lang_propagate_lma_regions rule.

```
// .foo's LMA region is propagated to .bar because their VMA region is the same,
// and .bar does not have an explicit output section address (addr_tree).
.foo : { *(.foo) } >RAM AT> FLASH
.bar : { *(.bar) } >RAM

// An explicit output section address disables propagation.
.foo : { *(.foo) } >RAM AT> FLASH
.bar . : { *(.bar) } >RAM
```

In both cases, lld thinks .foo's LMA region is propagated and
places .bar in the same PT_LOAD, so lld diverges from GNU ld w.r.t. the
second case (lma-align.test).

This patch changes Writer<ELFT>::createPhdrs to disable propagation
(start a new PT_LOAD). A user of the first case can make linker scripts
portable by explicitly specifying `AT>`. By contrast, there was no
workaround for the old behavior.

This change uncovers another LMA related bug in assignOffsets() where
`ctx->lmaOffset = 0;` was omitted. It caused a spurious "load address
range overlaps" error for at2.test

The new PT_LOAD rule is complex. For convenience, I listed the origins of some subexpressions:

* rL323449: `sec->memRegion == load->firstSec->memRegion`; linkerscript/at3.test
* D43284: `load->lastSec == Out::programHeaders` (don't start a new PT_LOAD after program headers); linkerscript/at4.test
* D58892: `sec != relroEnd` (start a new PT_LOAD after PT_GNU_RELRO)

Reviewed By: psmith

Differential Revision: https://reviews.llvm.org/D74297
2020-02-12 08:20:14 -08:00
George Rimar
acf8cef80f [LLD] Do not overwrite LMAOffset of PT_LOAD header
Patch by Konstantin Schwarz!

If more than a single output section is added to a PT_LOAD header,
only the first section should set the LMAOffset of the segment.
Otherwise, we get a load-address overlap error

Differential revision: https://reviews.llvm.org/D50133

llvm-svn: 338697
2018-08-02 10:45:46 +00:00