[lld] r247925 - [elf2] Combine adjacent compatible OutputSections in PT_LOADs.
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 17 14:05:39 PDT 2015
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.
Also, elf2/dynamic-reloc.s is failing.
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