[PATCH] D67325: [ELF] Place the ELF header at imageBase

Fangrui Song via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sat Sep 7 22:53:03 PDT 2019


MaskRay created this revision.
MaskRay added reviewers: grimar, peter.smith, ruiu.
Herald added subscribers: llvm-commits, jrtc27, fedor.sergeev, kbarton, arichardson, nemanjai, emaste, jyknight.
Herald added a reviewer: espindola.
Herald added a project: LLVM.

If there is no readonly section, we place:

- The ELF header at imageBase+maxPageSize
- Program headers at imageBase+maxPageSize+sizeof(Ehdr)
- The first section .text at imageBase+maxPageSize+sizeof(Ehdr)+sizeof(program headers)

This is due to an interaction between Writer<ELFT>::fixSectionAlignments
and LinkerScript::allocateHeaders:

- fixSectionAlignments says .text should be placed at `imageBase+maxPageSize+sizeof(Ehdr)+sizeof(program headers)` (formula: `alignTo(dot, maxPageSize) + dot % config->maxPageSize`)
- allocateHeaders computes the minimum address among SHF_ALLOC sections, i.e. addr(.text)
- allocateHeaders places ELF header at `addr(.text)-sizeof(Ehdr)-sizeof(program headers) = imageBase+maxPageSize`

This causes the first two PT_LOAD to overlap, which will not have
runtime problems, but not ideal.

  // PHDR at 0x401034, should be 0x400034
    PHDR           0x000034 0x00401034 0x00401034 0x000a0 0x000a0 R   0x4
  // R PT_LOAD contains just Ehdr and program headers.
  // It overlaps with the RX PT_LOAD.
    LOAD           0x000000 0x00401000 0x00401000 0x000d4 0x000d4 R   0x1000
    LOAD           0x0000d4 0x004010d4 0x004010d4 0x00001 0x00001 R E 0x1000

To fix the placement of the ELF header and program headers, set their
addresses in LinkerScript::assignAddresses, and make allocateHeaders a
NOP. Also drop the `getInitialDot` special case for -T<section>.

Before and after this change, with -T<section>, ld.lld consistently
creates a PT_PHDR while ld.bfd doesn't:

  ld.bfd -o a -Ttext=0x3000 a.o => no PT_PHDR
  ld.bfd -o a -Ttext=0x3000 a.o dummy.so (--enable-separate-code [1]) => place .note.gnu.property at 0x4000e8.

After dropping the special rule, if -Ttext is smaller than the default image base, the ELF header will be mapped at a higher address, which may look strange:

  PHDR           0x000034 0x00400034 0x00400034 0x000a0 0x000a0 R   0x4
  LOAD           0x000000 0x00400000 0x00400000 0x000d4 0x000d4 R   0x1000
  LOAD           0x001000 0x00003000 0x00003000 0x00001 0x00001 R E 0x1000

This is probably OK because our behavior (the existence of PT_PHDR) has
already diverged from ld.bfd, and ld.bfd's own program headers can
change with or without -z separate-code.

It is advised to use a linker script with the PHDRS command to have a
consistent behavior across linkers. If PT_PHDR is needed, an explicit
--image-base can be a simpler alternative.

[1]: --enable-separate-code is the default on Linux x86-64 since binutils 2.31.


Repository:
  rLLD LLVM Linker

https://reviews.llvm.org/D67325

Files:
  ELF/LinkerScript.cpp
  test/ELF/basic-aarch64.s
  test/ELF/basic-i386.s
  test/ELF/basic-ppc.s
  test/ELF/basic-sparcv9.s
  test/ELF/ttext-tdata-tbss.s

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67325.219256.patch
Type: text/x-patch
Size: 8091 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190908/543d72ba/attachment.bin>


More information about the llvm-commits mailing list