From ef762f2639825306f0fe0814e22d7139dfa88859 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Wed, 10 Feb 2016 23:29:38 +0000 Subject: [PATCH] Don't include NOBITS TLS in PT_LOAD. They don't count for the memory or file size, so this is mostly just a simplification. The only noticeable difference should be fewer empty program headers. llvm-svn: 260465 --- lld/ELF/Writer.cpp | 66 +++++++++--------- lld/test/ELF/avoid-empty-program-headers.s | 78 ++++++++++++++++++++++ 2 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 lld/test/ELF/avoid-empty-program-headers.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 92a98902a016..3cddbf5706a9 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1184,8 +1184,16 @@ void Writer::addStartStopSymbols(OutputSectionBase *Sec) { Symtab.addSynthetic(Stop, *Sec, Sec->getSize()); } -template static bool needsPhdr(OutputSectionBase *Sec) { - return Sec->getFlags() & SHF_ALLOC; +template static bool needsPtLoad(OutputSectionBase *Sec) { + if (!(Sec->getFlags() & SHF_ALLOC)) + return false; + + // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is + // responsible for allocating space for them, not the PT_LOAD that + // contains the TLS initialization image. + if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) + return false; + return true; } static uint32_t toPhdrFlags(uint64_t Flags) { @@ -1241,9 +1249,18 @@ template void Writer::createPhdrs() { Phdr TlsHdr(PT_TLS, PF_R); Phdr RelRo(PT_GNU_RELRO, PF_R); for (OutputSectionBase *Sec : OutputSections) { - if (!needsPhdr(Sec)) + if (!(Sec->getFlags() & SHF_ALLOC)) break; + // If we meet TLS section then we create TLS header + // and put all TLS sections inside for futher use when + // assign addresses. + if (Sec->getFlags() & SHF_TLS) + AddSec(TlsHdr, Sec); + + if (!needsPtLoad(Sec)) + continue; + // If flags changed then we want new load segment. uintX_t NewFlags = toPhdrFlags(Sec->getFlags()); if (Flags != NewFlags) { @@ -1252,14 +1269,6 @@ template void Writer::createPhdrs() { Load = AddHdr(LoadType, NewFlags); Flags = NewFlags; } - // If we meet TLS section then we create TLS header - // and put all TLS sections inside for futher use when - // assign addresses. - if (Sec->getFlags() & SHF_TLS) { - AddSec(TlsHdr, Sec); - if (Sec->getType() == SHT_NOBITS) - continue; - } AddSec(*Load, Sec); @@ -1307,18 +1316,15 @@ template void Writer::assignAddresses() { SmallPtrSet *, 4> PageAlign; for (const Phdr &P : Phdrs) { if (P.H.p_type == PT_GNU_RELRO) { - // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD - // and is not tls, we have to align it to a page. We don't have to - // align tls since TLS NOBITS takes no space. + // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we + // have to align it to a page. auto I = std::find(OutputSections.begin(), OutputSections.end(), P.Last); ++I; - if (I != OutputSections.end() && needsPhdr(*I) && - !((*I)->getFlags() & SHF_TLS)) + if (I != OutputSections.end() && needsPtLoad(*I)) PageAlign.insert(*I); } - // FIXME: why create empty PT_LOAD? - if (P.H.p_type == PT_LOAD && P.First) + if (P.H.p_type == PT_LOAD) PageAlign.insert(P.First); } @@ -1337,21 +1343,15 @@ template void Writer::assignAddresses() { FileOff += Sec->getSize(); // We only assign VAs to allocated sections. - if (needsPhdr(Sec)) { - // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is - // responsible for allocating space for them, not the PT_LOAD that - // contains the TLS initialization image. - bool IsTls = Sec->getFlags() & SHF_TLS; - if (IsTls && Sec->getType() == SHT_NOBITS) { - uintX_t TVA = VA + ThreadBssOffset; - TVA = alignTo(TVA, Align); - Sec->setVA(TVA); - ThreadBssOffset = TVA - VA + Sec->getSize(); - } else { - VA = alignTo(VA, Align); - Sec->setVA(VA); - VA += Sec->getSize(); - } + if (needsPtLoad(Sec)) { + VA = alignTo(VA, Align); + Sec->setVA(VA); + VA += Sec->getSize(); + } else if (Sec->getFlags() & SHF_TLS && Sec->getType() == SHT_NOBITS) { + uintX_t TVA = VA + ThreadBssOffset; + TVA = alignTo(TVA, Align); + Sec->setVA(TVA); + ThreadBssOffset = TVA - VA + Sec->getSize(); } } diff --git a/lld/test/ELF/avoid-empty-program-headers.s b/lld/test/ELF/avoid-empty-program-headers.s new file mode 100644 index 000000000000..f7315677e1a3 --- /dev/null +++ b/lld/test/ELF/avoid-empty-program-headers.s @@ -0,0 +1,78 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +// RUN: ld.lld %t -o %tout +// RUN: llvm-readobj -program-headers %tout | FileCheck %s + +.global _start +_start: + retq + +.section .tbss,"awT",@nobits + .zero 4 +// FIXME: Test that we don't create unecessary empty PT_LOAD and PT_GNU_RELRO +// for the .tbss section. + +// CHECK: ProgramHeaders [ +// CHECK-NEXT: ProgramHeader { +// CHECK-NEXT: Type: PT_PHDR (0x6) +// CHECK-NEXT: Offset: 0x40 +// CHECK-NEXT: VirtualAddress: 0x10040 +// CHECK-NEXT: PhysicalAddress: 0x10040 +// CHECK-NEXT: FileSize: 280 +// CHECK-NEXT: MemSize: 280 +// CHECK-NEXT: Flags [ (0x4) +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 8 +// CHECK-NEXT: } +// CHECK-NEXT: ProgramHeader { +// CHECK-NEXT: Type: PT_LOAD (0x1) +// CHECK-NEXT: Offset: 0x0 +// CHECK-NEXT: VirtualAddress: 0x10000 +// CHECK-NEXT: PhysicalAddress: 0x10000 +// CHECK-NEXT: FileSize: 344 +// CHECK-NEXT: MemSize: 344 +// CHECK-NEXT: Flags [ (0x4) +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 4096 +// CHECK-NEXT: } +// CHECK-NEXT: ProgramHeader { +// CHECK-NEXT: Type: PT_LOAD (0x1) +// CHECK-NEXT: Offset: 0x1000 +// CHECK-NEXT: VirtualAddress: 0x11000 +// CHECK-NEXT: PhysicalAddress: 0x11000 +// CHECK-NEXT: FileSize: 1 +// CHECK-NEXT: MemSize: 1 +// CHECK-NEXT: Flags [ (0x5) +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: PF_X (0x1) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 4096 +// CHECK-NEXT: } +// CHECK-NEXT: ProgramHeader { +// CHECK-NEXT: Type: PT_TLS (0x7) +// CHECK-NEXT: Offset: 0x1001 +// CHECK-NEXT: VirtualAddress: 0x11001 +// CHECK-NEXT: PhysicalAddress: 0x11001 +// CHECK-NEXT: FileSize: 0 +// CHECK-NEXT: MemSize: 4 +// CHECK-NEXT: Flags [ (0x4) +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 1 +// CHECK-NEXT: } +// CHECK-NEXT: ProgramHeader { +// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551) +// CHECK-NEXT: Offset: 0x0 +// CHECK-NEXT: VirtualAddress: 0x0 +// CHECK-NEXT: PhysicalAddress: 0x0 +// CHECK-NEXT: FileSize: 0 +// CHECK-NEXT: MemSize: 0 +// CHECK-NEXT: Flags [ (0x6) +// CHECK-NEXT: PF_R (0x4) +// CHECK-NEXT: PF_W (0x2) +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: 0 +// CHECK-NEXT: } +// CHECK-NEXT: ]