Pull in r369828 from upstream lld trunk (by Fāng-ruì Sòng):

[ELF] Align the first section of a PT_LOAD even if its type is
  SHT_NOBITS

  Reported at https://reviews.llvm.org/D64930#1642223

  If the only section of a PT_LOAD is a SHT_NOBITS section (e.g. .bss),
  we may not align its sh_offset. p_offset of the PT_LOAD will be set
  to sh_offset, and we will get p_offset!=p_vaddr (mod p_align).  If
  such executable is mapped by the Linux kernel, it will segfault.

  After D64906, this may happen the non-linker script case.

  The linker script case has had this issue for a long time.  This was
  fixed by rL321657 (but the test linkerscript/nobits-offset.s failed
  to test a SHT_NOBITS section), but broken by rL345154.

  Reviewed By: peter.smith

  Differential Revision: https://reviews.llvm.org/D66658

Pull in r371013 from upstream lld trunk (by Rui Ueyama):

  Align output segments correctly

  Previously, segments were aligned according to their first section's
  alignment requirements. That was not correct, but segments are also
  aligned to a page boundary, and a page boundary is usually much
  larger than a section alignment requirement, so no one noticed this
  bug before.

  Now, lld has --nmagic option which sets maxPageSize to 1 to
  effectively disable page alignment, which reveals the issue.

  Fixes https://bugs.llvm.org/show_bug.cgi?id=43212

  Differential Revision: https://reviews.llvm.org/D67152

Together, these should ensure gpboot.out gets a correctly aligned offset
for its .rodata section, and fix "layout constraint violation" errors
from objcopy.
This commit is contained in:
Dimitry Andric 2019-09-05 17:53:41 +00:00
parent c5c3ba6b43
commit 24ea14660b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang900-import/; revision=351879

View File

@ -2230,25 +2230,27 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// same with its virtual address modulo the page size, so that the loader can
// load executables without any address adjustment.
static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
// File offsets are not significant for .bss sections. By convention, we keep
// section offsets monotonically increasing rather than setting to zero.
if (os->type == SHT_NOBITS)
return off;
// The first section in a PT_LOAD has to have congruent offset and address
// module the page size.
if (os->ptLoad && os->ptLoad->firstSec == os) {
uint64_t alignment =
std::max<uint64_t>(os->ptLoad->p_align, config->maxPageSize);
return alignTo(off, alignment, os->addr);
}
// File offsets are not significant for .bss sections other than the first one
// in a PT_LOAD. By convention, we keep section offsets monotonically
// increasing rather than setting to zero.
if (os->type == SHT_NOBITS)
return off;
// If the section is not in a PT_LOAD, we just have to align it.
if (!os->ptLoad)
return alignTo(off, os->alignment);
// The first section in a PT_LOAD has to have congruent offset and address
// module the page size.
OutputSection *first = os->ptLoad->firstSec;
if (os == first) {
uint64_t alignment = std::max<uint64_t>(os->alignment, config->maxPageSize);
return alignTo(off, alignment, os->addr);
}
// If two sections share the same PT_LOAD the file offset is calculated
// using this formula: Off2 = Off1 + (VA2 - VA1).
OutputSection *first = os->ptLoad->firstSec;
return first->offset + os->addr - first->addr;
}