[lld] r247925 - [elf2] Combine adjacent compatible OutputSections in PT_LOADs.

Michael Spencer via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 17 14:23:24 PDT 2015


On Thu, Sep 17, 2015 at 2:05 PM, Rafael EspĂ­ndola
<rafael.espindola at gmail.com> wrote:
> On the review thread I wrote:
>
>   LGTM on the condition that one extra test is added showing a read
> only section being included in the initial PT_LOAD.
>
> I don't see any such test.

r247947

>
> Also, elf2/dynamic-reloc.s is failing.

r247946

- Michael Spencer

>
>
> On 17 September 2015 at 15:58, Michael J. Spencer via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>> Author: mspencer
>> Date: Thu Sep 17 14:58:07 2015
>> New Revision: 247925
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=247925&view=rev
>> Log:
>> [elf2] Combine adjacent compatible OutputSections in PT_LOADs.
>>
>> Added:
>>     lld/trunk/test/elf2/program-header-layout.s
>> Modified:
>>     lld/trunk/ELF/Writer.cpp
>>     lld/trunk/test/elf2/dynamic-reloc.s
>>     lld/trunk/test/elf2/relocation.s
>>     lld/trunk/test/elf2/shared.s
>>
>> Modified: lld/trunk/ELF/Writer.cpp
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247925&r1=247924&r2=247925&view=diff
>> ==============================================================================
>> --- lld/trunk/ELF/Writer.cpp (original)
>> +++ lld/trunk/ELF/Writer.cpp Thu Sep 17 14:58:07 2015
>> @@ -446,6 +446,57 @@ private:
>>    SymbolTable &SymTab;
>>  };
>>
>> +static uint32_t convertSectionFlagsToPHDRFlags(uint64_t Flags) {
>> +  uint32_t Ret = PF_R;
>> +  if (Flags & SHF_WRITE)
>> +    Ret |= PF_W;
>> +
>> +  if (Flags & SHF_EXECINSTR)
>> +    Ret |= PF_X;
>> +
>> +  return Ret;
>> +}
>> +
>> +template <bool Is64Bits>
>> +class ProgramHeader {
>> +public:
>> +  typedef typename std::conditional<Is64Bits, uint64_t, uint32_t>::type uintX_t;
>> +  typedef
>> +    typename std::conditional<Is64Bits, Elf64_Phdr, Elf32_Phdr>::type HeaderT;
>> +
>> +  ProgramHeader(uintX_t p_type, uintX_t p_flags) {
>> +    std::memset(&Header, 0, sizeof(HeaderT));
>> +    Header.p_type = p_type;
>> +    Header.p_flags = p_flags;
>> +    Header.p_align = PageSize;
>> +  }
>> +
>> +  void setValuesFromSection(OutputSectionBase<Is64Bits> &Sec) {
>> +    Header.p_flags = convertSectionFlagsToPHDRFlags(Sec.getFlags());
>> +    Header.p_offset = Sec.getFileOff();
>> +    Header.p_vaddr = Sec.getVA();
>> +    Header.p_paddr = Header.p_vaddr;
>> +    Header.p_filesz = Sec.getSize();
>> +    Header.p_memsz = Header.p_filesz;
>> +    Header.p_align = Sec.getAlign();
>> +  }
>> +
>> +  template <endianness E>
>> +  void writeHeaderTo(typename ELFFile<ELFType<E, Is64Bits>>::Elf_Phdr *PHDR) {
>> +    PHDR->p_type = Header.p_type;
>> +    PHDR->p_flags = Header.p_flags;
>> +    PHDR->p_offset = Header.p_offset;
>> +    PHDR->p_vaddr = Header.p_vaddr;
>> +    PHDR->p_paddr = Header.p_paddr;
>> +    PHDR->p_filesz = Header.p_filesz;
>> +    PHDR->p_memsz = Header.p_memsz;
>> +    PHDR->p_align = Header.p_align;
>> +  }
>> +
>> +  HeaderT Header;
>> +  bool Closed = false;
>> +};
>> +
>>  // The writer writes a SymbolTable result to a file.
>>  template <class ELFT> class Writer {
>>  public:
>> @@ -487,14 +538,20 @@ private:
>>    unsigned getVAStart() const { return Config->Shared ? 0 : VAStart; }
>>
>>    std::unique_ptr<llvm::FileOutputBuffer> Buffer;
>> +
>>    llvm::SpecificBumpPtrAllocator<OutputSection<ELFT>> CAlloc;
>>    std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
>>    unsigned getNumSections() const { return OutputSections.size() + 1; }
>>
>> +  llvm::BumpPtrAllocator PAlloc;
>> +  std::vector<ProgramHeader<ELFT::Is64Bits> *> PHDRs;
>> +  ProgramHeader<ELFT::Is64Bits> FileHeaderPHDR{PT_LOAD, PF_R};
>> +  ProgramHeader<ELFT::Is64Bits> InterpPHDR{PT_INTERP, 0};
>> +  ProgramHeader<ELFT::Is64Bits> DynamicPHDR{PT_DYNAMIC, 0};
>> +
>>    uintX_t FileSize;
>>    uintX_t ProgramHeaderOff;
>>    uintX_t SectionHeaderOff;
>> -  unsigned NumPhdrs;
>>
>>    StringTableSection<ELFT::Is64Bits> StrTabSec = { /*dynamic=*/false };
>>    StringTableSection<ELFT::Is64Bits> DynStrSec = { /*dynamic=*/true };
>> @@ -950,12 +1007,13 @@ template <class ELFT> void Writer<ELFT>:
>>
>>  template <class ELFT>
>>  static bool outputSectionHasPHDR(OutputSectionBase<ELFT::Is64Bits> *Sec) {
>> -  return (Sec->getSize() != 0) && (Sec->getFlags() & SHF_ALLOC);
>> +  return Sec->getFlags() & SHF_ALLOC;
>>  }
>>
>>  // Visits all sections to assign incremental, non-overlapping RVAs and
>>  // file offsets.
>>  template <class ELFT> void Writer<ELFT>::assignAddresses() {
>> +  assert(!OutputSections.empty() && "No output sections to layout!");
>>    uintX_t VA = getVAStart();
>>    uintX_t FileOff = 0;
>>
>> @@ -967,26 +1025,41 @@ template <class ELFT> void Writer<ELFT>:
>>    FileOff = RoundUpToAlignment(FileOff, PageSize);
>>    VA = RoundUpToAlignment(VA, PageSize);
>>
>> -  NumPhdrs = 0;
>> -
>> -  // Add a PHDR for PT_INTERP.
>>    if (needsInterpSection())
>> -    ++NumPhdrs;
>> +    PHDRs.push_back(&InterpPHDR);
>>
>> -  // Add a PHDR for the elf header and program headers. Some dynamic linkers
>> -  // (musl at least) require them to be covered by a PT_LOAD.
>> -  ++NumPhdrs;
>> +  ProgramHeader<ELFT::Is64Bits> *LastPHDR = &FileHeaderPHDR;
>> +  // Create a PHDR for the file header.
>> +  PHDRs.push_back(&FileHeaderPHDR);
>> +  FileHeaderPHDR.Header.p_vaddr = getVAStart();
>> +  FileHeaderPHDR.Header.p_paddr = getVAStart();
>> +  FileHeaderPHDR.Header.p_align = PageSize;
>>
>>    for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) {
>>      StrTabSec.add(Sec->getName());
>>      Sec->finalize();
>>
>> -    // Since each output section gets its own PHDR, align each output section to
>> -    // a page.
>> -    if (outputSectionHasPHDR<ELFT>(Sec)) {
>> -      ++NumPhdrs;
>> -      VA = RoundUpToAlignment(VA, PageSize);
>> -      FileOff = RoundUpToAlignment(FileOff, PageSize);
>> +    if (Sec->getSize()) {
>> +      uintX_t Flags = convertSectionFlagsToPHDRFlags(Sec->getFlags());
>> +      if (LastPHDR->Header.p_flags != Flags ||
>> +          !outputSectionHasPHDR<ELFT>(Sec)) {
>> +        // Flags changed. End current PHDR and potentially create a new one.
>> +        if (!LastPHDR->Closed) {
>> +          LastPHDR->Header.p_filesz = FileOff - LastPHDR->Header.p_offset;
>> +          LastPHDR->Header.p_memsz = VA - LastPHDR->Header.p_vaddr;
>> +          LastPHDR->Closed = true;
>> +        }
>> +
>> +        if (outputSectionHasPHDR<ELFT>(Sec)) {
>> +          LastPHDR = new (PAlloc) ProgramHeader<ELFT::Is64Bits>(PT_LOAD, Flags);
>> +          PHDRs.push_back(LastPHDR);
>> +          VA = RoundUpToAlignment(VA, PageSize);
>> +          FileOff = RoundUpToAlignment(FileOff, PageSize);
>> +          LastPHDR->Header.p_offset = FileOff;
>> +          LastPHDR->Header.p_vaddr = VA;
>> +          LastPHDR->Header.p_paddr = VA;
>> +        }
>> +      }
>>      }
>>
>>      uintX_t Align = Sec->getAlign();
>> @@ -1004,7 +1077,7 @@ template <class ELFT> void Writer<ELFT>:
>>
>>    // Add a PHDR for the dynamic table.
>>    if (needsDynamicSections())
>> -    ++NumPhdrs;
>> +    PHDRs.push_back(&DynamicPHDR);
>>
>>    FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
>>
>> @@ -1014,29 +1087,6 @@ template <class ELFT> void Writer<ELFT>:
>>    FileSize = FileOff;
>>  }
>>
>> -static uint32_t convertSectionFlagsToPHDRFlags(uint64_t Flags) {
>> -  uint32_t Ret = PF_R;
>> -  if (Flags & SHF_WRITE)
>> -    Ret |= PF_W;
>> -
>> -  if (Flags & SHF_EXECINSTR)
>> -    Ret |= PF_X;
>> -
>> -  return Ret;
>> -}
>> -
>> -template <class ELFT>
>> -static void setValuesFromSection(typename ELFFile<ELFT>::Elf_Phdr &P,
>> -                                 OutputSectionBase<ELFT::Is64Bits> &S) {
>> -  P.p_flags = convertSectionFlagsToPHDRFlags(S.getFlags());
>> -  P.p_offset = S.getFileOff();
>> -  P.p_vaddr = S.getVA();
>> -  P.p_paddr = P.p_vaddr;
>> -  P.p_filesz = S.getSize();
>> -  P.p_memsz = P.p_filesz;
>> -  P.p_align = S.getAlign();
>> -}
>> -
>>  template <class ELFT> void Writer<ELFT>::writeHeader() {
>>    uint8_t *Buf = Buffer->getBufferStart();
>>    auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
>> @@ -1065,46 +1115,24 @@ template <class ELFT> void Writer<ELFT>:
>>    EHdr->e_shoff = SectionHeaderOff;
>>    EHdr->e_ehsize = sizeof(Elf_Ehdr);
>>    EHdr->e_phentsize = sizeof(Elf_Phdr);
>> -  EHdr->e_phnum = NumPhdrs;
>> +  EHdr->e_phnum = PHDRs.size();
>>    EHdr->e_shentsize = sizeof(Elf_Shdr);
>>    EHdr->e_shnum = getNumSections();
>>    EHdr->e_shstrndx = StrTabSec.getSectionIndex();
>>
>> -  auto PHdrs = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
>> -  if (needsInterpSection()) {
>> -    PHdrs->p_type = PT_INTERP;
>> -    setValuesFromSection<ELFT>(*PHdrs, InterpSec);
>> -    ++PHdrs;
>> -  }
>> -
>> -  PHdrs->p_type = PT_LOAD;
>> -  PHdrs->p_flags = PF_R;
>> -  PHdrs->p_offset = 0;
>> -  PHdrs->p_vaddr = getVAStart();
>> -  PHdrs->p_paddr = PHdrs->p_vaddr;
>> -  PHdrs->p_filesz = ProgramHeaderOff + NumPhdrs * sizeof(Elf_Phdr);
>> -  PHdrs->p_memsz = PHdrs->p_filesz;
>> -  PHdrs->p_align = PageSize;
>> -  ++PHdrs;
>> +  // If nothing was merged into the file header PT_LOAD, set the size correctly.
>> +  if (FileHeaderPHDR.Header.p_filesz == PageSize)
>> +    FileHeaderPHDR.Header.p_filesz = FileHeaderPHDR.Header.p_memsz =
>> +        sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * PHDRs.size();
>>
>> -  for (OutputSectionBase<ELFT::Is64Bits> *Sec : OutputSections) {
>> -    if (!outputSectionHasPHDR<ELFT>(Sec))
>> -      continue;
>> -    PHdrs->p_type = PT_LOAD;
>> -    PHdrs->p_flags = convertSectionFlagsToPHDRFlags(Sec->getFlags());
>> -    PHdrs->p_offset = Sec->getFileOff();
>> -    PHdrs->p_vaddr = Sec->getVA();
>> -    PHdrs->p_paddr = PHdrs->p_vaddr;
>> -    PHdrs->p_filesz = Sec->getType() == SHT_NOBITS ? 0 : Sec->getSize();
>> -    PHdrs->p_memsz = Sec->getSize();
>> -    PHdrs->p_align = PageSize;
>> -    ++PHdrs;
>> -  }
>> +  if (needsInterpSection())
>> +    InterpPHDR.setValuesFromSection(InterpSec);
>> +  if (needsDynamicSections())
>> +    DynamicPHDR.setValuesFromSection(DynamicSec);
>>
>> -  if (needsDynamicSections()) {
>> -    PHdrs->p_type = PT_DYNAMIC;
>> -    setValuesFromSection<ELFT>(*PHdrs, DynamicSec);
>> -  }
>> +  auto PHdrs = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
>> +  for (ProgramHeader<ELFT::Is64Bits> *PHDR : PHDRs)
>> +    PHDR->template writeHeaderTo<ELFT::TargetEndianness>(PHdrs++);
>>
>>    auto SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
>>    // First entry is null.
>>
>> Modified: lld/trunk/test/elf2/dynamic-reloc.s
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/dynamic-reloc.s?rev=247925&r1=247924&r2=247925&view=diff
>> ==============================================================================
>> --- lld/trunk/test/elf2/dynamic-reloc.s (original)
>> +++ lld/trunk/test/elf2/dynamic-reloc.s Thu Sep 17 14:58:07 2015
>> @@ -22,7 +22,7 @@
>>  // CHECK-NEXT:   SHF_ALLOC
>>  // CHECK-NEXT: ]
>>  // CHECK-NEXT: Address: [[RELAADDR:.*]]
>> -// CHECK-NEXT: Offset: 0x6000
>> +// CHECK-NEXT: Offset: 0x4058
>>  // CHECK-NEXT: Size: [[RELASIZE:.*]]
>>  // CHECK-NEXT: Link: 4
>>  // CHECK-NEXT: Info: 0
>>
>> Added: lld/trunk/test/elf2/program-header-layout.s
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/program-header-layout.s?rev=247925&view=auto
>> ==============================================================================
>> --- lld/trunk/test/elf2/program-header-layout.s (added)
>> +++ lld/trunk/test/elf2/program-header-layout.s Thu Sep 17 14:58:07 2015
>> @@ -0,0 +1,46 @@
>> +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
>> +# RUN: lld -flavor gnu2 %t -o %t2
>> +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s
>> +# REQUIRES: x86
>> +
>> +# Check that different output sections with the same flags are merged into a
>> +# single Read/Write PT_LOAD.
>> +
>> +.section .r,"a"
>> +.globl _start
>> +_start:
>> +.quad 0
>> +
>> +.section .a,"aw"
>> +.quad 1
>> +
>> +.section .b,"aw"
>> +.quad 2
>> +
>> +# CHECK:      ProgramHeaders [
>> +# CHECK-NEXT:   ProgramHeader {
>> +# CHECK-NEXT:     Type: PT_LOAD
>> +# CHECK-NEXT:     Offset: 0x0
>> +# CHECK-NEXT:     VirtualAddress:
>> +# CHECK-NEXT:     PhysicalAddress:
>> +# CHECK-NEXT:     FileSize:
>> +# CHECK-NEXT:     MemSize:
>> +# CHECK-NEXT:     Flags [
>> +# CHECK-NEXT:       PF_R
>> +# CHECK-NEXT:     ]
>> +# CHECK-NEXT:     Alignment:
>> +# CHECK-NEXT:   }
>> +# CHECK-NEXT:   ProgramHeader {
>> +# CHECK-NEXT:     Type: PT_LOAD
>> +# CHECK-NEXT:     Offset:
>> +# CHECK-NEXT:     VirtualAddress:
>> +# CHECK-NEXT:     PhysicalAddress:
>> +# CHECK-NEXT:     FileSize: 16
>> +# CHECK-NEXT:     MemSize: 16
>> +# CHECK-NEXT:     Flags [
>> +# CHECK-NEXT:       PF_R
>> +# CHECK-NEXT:       PF_W
>> +# CHECK-NEXT:     ]
>> +# CHECK-NEXT:     Alignment:
>> +# CHECK-NEXT:   }
>> +# CHECK-NEXT: ]
>>
>> Modified: lld/trunk/test/elf2/relocation.s
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation.s?rev=247925&r1=247924&r2=247925&view=diff
>> ==============================================================================
>> --- lld/trunk/test/elf2/relocation.s (original)
>> +++ lld/trunk/test/elf2/relocation.s Thu Sep 17 14:58:07 2015
>> @@ -33,7 +33,7 @@ R_X86_64_32:
>>  // constants in hex.
>>  // CHECK: Disassembly of section .text2:
>>  // CHECK-NEXT: R_X86_64_32:
>> -// CHECK-NEXT:  12000: {{.*}} movl $73728, %edx
>> +// CHECK-NEXT:  1100c: {{.*}} movl $69644, %edx
>>
>>  .section .R_X86_64_32S,"ax", at progbits
>>  .global R_X86_64_32S
>> @@ -50,4 +50,4 @@ R_X86_64_64:
>>   .quad R_X86_64_64
>>
>>  // CHECK:      Contents of section .R_X86_64_64:
>> -// CHECK-NEXT:   14000 00400100 00000000
>> +// CHECK-NEXT:   12000 00200100 00000000
>>
>> Modified: lld/trunk/test/elf2/shared.s
>> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247925&r1=247924&r2=247925&view=diff
>> ==============================================================================
>> --- lld/trunk/test/elf2/shared.s (original)
>> +++ lld/trunk/test/elf2/shared.s Thu Sep 17 14:58:07 2015
>> @@ -12,7 +12,7 @@
>>  // SO-NEXT: Flags [
>>  // SO-NEXT: ]
>>  // SO-NEXT: Address:
>> -// SO-NEXT: Offset: 0x400C
>> +// SO-NEXT: Offset: 0x300C
>>  // SO-NEXT: Size:
>>  // SO-NEXT: Link:
>>  // SO-NEXT: Info:
>> @@ -44,7 +44,7 @@
>>  // CHECK-NEXT:     SHF_ALLOC
>>  // CHECK-NEXT:   ]
>>  // CHECK-NEXT:   Address: [[DYNSYMADDR:.*]]
>> -// CHECK-NEXT:   Offset: 0x3000
>> +// CHECK-NEXT:   Offset: 0x201C
>>  // CHECK-NEXT:   Size: 48
>>  // CHECK-NEXT:   Link: [[DYNSTR:.*]]
>>  // CHECK-NEXT:   Info: 1
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits


More information about the llvm-commits mailing list