diff options
| -rw-r--r-- | lld/ELF/Writer.cpp | 67 | ||||
| -rw-r--r-- | lld/test/elf2/basic.s | 6 | ||||
| -rw-r--r-- | lld/test/elf2/basic32.s | 6 | ||||
| -rw-r--r-- | lld/test/elf2/basic32be.s | 6 | ||||
| -rw-r--r-- | lld/test/elf2/basic64be.s | 55 | ||||
| -rw-r--r-- | lld/test/elf2/relocation.s | 2 | ||||
| -rw-r--r-- | lld/test/elf2/symbols.s | 16 |
7 files changed, 96 insertions, 62 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index af615abf711..ff5d58ae7ea 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -250,8 +250,9 @@ private: unsigned getNumSections() const { return OutputSections.size() + 1; } uintX_t FileSize; - uintX_t SizeOfHeaders; + uintX_t ProgramHeaderOff; uintX_t SectionHeaderOff; + unsigned NumPhdrs; StringTableSection<ELFT::Is64Bits> StrTabSec; StringTableSection<ELFT::Is64Bits> DynStrSec; @@ -578,17 +579,34 @@ template <class ELFT> void Writer<ELFT>::createSections() { OutputSections[I]->setSectionIndex(I + 1); } +template <class ELFT> +static bool outputSectionHasPHDR(OutputSectionBase<ELFT::Is64Bits> *Sec) { + return (Sec->getSize() != 0) && (Sec->getFlags() & SHF_ALLOC); +} + // Visits all sections to assign incremental, non-overlapping RVAs and // file offsets. template <class ELFT> void Writer<ELFT>::assignAddresses() { - SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr), PageSize); uintX_t VA = 0x1000; // The first page is kept unmapped. - uintX_t FileOff = SizeOfHeaders; + uintX_t FileOff = sizeof(Elf_Ehdr); + + // Reserve space for PHDRs. + ProgramHeaderOff = FileOff; + FileOff = RoundUpToAlignment(FileOff, PageSize); + NumPhdrs = 0; 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); + } + uintX_t Align = Sec->getAlign(); uintX_t Size = Sec->getSize(); if (Sec->getFlags() & SHF_ALLOC) { @@ -600,15 +618,19 @@ template <class ELFT> void Writer<ELFT>::assignAddresses() { FileOff += RoundUpToAlignment(Size, Align); } + // Add a PHDR for the dynamic table. + if (!SymTable.getSymTable().getSharedFiles().empty()) + ++NumPhdrs; + FileOff += OffsetToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4); // Add space for section headers. SectionHeaderOff = FileOff; FileOff += getNumSections() * sizeof(Elf_Shdr); - FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8); + FileSize = FileOff; } -static uint32_t convertSectionFlagsToSegmentFlags(uint64_t Flags) { +static uint32_t convertSectionFlagsToPHDRFlags(uint64_t Flags) { uint32_t Ret = PF_R; if (Flags & SHF_WRITE) Ret |= PF_W; @@ -635,42 +657,41 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { // FIXME: Generalize the segment construction similar to how we create // output sections. - unsigned NumSegments = 1; const SymbolTable &Symtab = SymTable.getSymTable(); - const std::vector<std::unique_ptr<SharedFileBase>> &SharedFiles = - Symtab.getSharedFiles(); - bool HasDynamicSegment = !SharedFiles.empty(); - if (HasDynamicSegment) - NumSegments++; + bool HasDynamicSegment = !Symtab.getSharedFiles().empty(); EHdr->e_type = ET_EXEC; auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF()); EHdr->e_machine = FirstObj.getEMachine(); EHdr->e_version = EV_CURRENT; EHdr->e_entry = getSymVA(cast<DefinedRegular<ELFT>>(Symtab.getEntrySym())); - EHdr->e_phoff = sizeof(Elf_Ehdr); + EHdr->e_phoff = ProgramHeaderOff; EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr); EHdr->e_phentsize = sizeof(Elf_Phdr); - EHdr->e_phnum = NumSegments; + EHdr->e_phnum = NumPhdrs; 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); - PHdrs->p_type = PT_LOAD; - PHdrs->p_flags = PF_R | PF_X; - PHdrs->p_offset = 0x1000; - PHdrs->p_vaddr = 0x1000; - PHdrs->p_paddr = PHdrs->p_vaddr; - PHdrs->p_filesz = FileSize; - PHdrs->p_memsz = FileSize; - PHdrs->p_align = 0x4000; + 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 (HasDynamicSegment) { - PHdrs++; PHdrs->p_type = PT_DYNAMIC; - PHdrs->p_flags = convertSectionFlagsToSegmentFlags(DynamicSec.getFlags()); + PHdrs->p_flags = convertSectionFlagsToPHDRFlags(DynamicSec.getFlags()); PHdrs->p_offset = DynamicSec.getFileOff(); PHdrs->p_vaddr = DynamicSec.getVA(); PHdrs->p_paddr = PHdrs->p_vaddr; diff --git a/lld/test/elf2/basic.s b/lld/test/elf2/basic.s index a977b740006..004cf7d7b4c 100644 --- a/lld/test/elf2/basic.s +++ b/lld/test/elf2/basic.s @@ -154,13 +154,13 @@ _start: # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x1000 # CHECK-NEXT: PhysicalAddress: 0x1000 -# CHECK-NEXT: FileSize: 4592 -# CHECK-NEXT: MemSize: 4592 +# CHECK-NEXT: FileSize: 16 +# CHECK-NEXT: MemSize: 16 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) # CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: Alignment: 4096 # CHECK-NEXT: } # CHECK-NEXT: ] diff --git a/lld/test/elf2/basic32.s b/lld/test/elf2/basic32.s index 54a9cb6b94b..7c477efd1ff 100644 --- a/lld/test/elf2/basic32.s +++ b/lld/test/elf2/basic32.s @@ -133,12 +133,12 @@ _start: # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x1000 # CHECK-NEXT: PhysicalAddress: 0x1000 -# CHECK-NEXT: FileSize: 4424 -# CHECK-NEXT: MemSize: 4424 +# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: MemSize: 12 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) # CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: Alignment: 4096 # CHECK-NEXT: } # CHECK-NEXT: ] diff --git a/lld/test/elf2/basic32be.s b/lld/test/elf2/basic32be.s index 8b5be744485..be6d55a1030 100644 --- a/lld/test/elf2/basic32be.s +++ b/lld/test/elf2/basic32be.s @@ -133,12 +133,12 @@ _start: # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x1000 # CHECK-NEXT: PhysicalAddress: 0x1000 -# CHECK-NEXT: FileSize: 4424 -# CHECK-NEXT: MemSize: 4424 +# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: MemSize: 12 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) # CHECK-NEXT: PF_X (0x1) # CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 16384 +# CHECK-NEXT: Alignment: 4096 # CHECK-NEXT: } # CHECK-NEXT: ] diff --git a/lld/test/elf2/basic64be.s b/lld/test/elf2/basic64be.s index f065afd4e3d..1fe61817289 100644 --- a/lld/test/elf2/basic64be.s +++ b/lld/test/elf2/basic64be.s @@ -28,14 +28,14 @@ _start: # CHECK-NEXT: Type: Executable (0x2) # CHECK-NEXT: Machine: EM_PPC64 (0x15) # CHECK-NEXT: Version: 1 -# CHECK-NEXT: Entry: 0x100C +# CHECK-NEXT: Entry: 0x2000 # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x1088 +# CHECK-NEXT: SectionHeaderOffset: 0x2078 # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 64 # CHECK-NEXT: ProgramHeaderEntrySize: 56 -# CHECK-NEXT: ProgramHeaderCount: 1 +# CHECK-NEXT: ProgramHeaderCount: 2 # CHECK-NEXT: SectionHeaderEntrySize: 64 # CHECK-NEXT: SectionHeaderCount: 7 # CHECK-NEXT: StringTableSectionIndex: 6 @@ -111,8 +111,8 @@ _start: # CHECK-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] -# CHECK-NEXT: Address: 0x100C -# CHECK-NEXT: Offset: 0x100C +# CHECK-NEXT: Address: 0x2000 +# CHECK-NEXT: Offset: 0x2000 # CHECK-NEXT: Size: 24 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -126,7 +126,7 @@ _start: # CHECK-NEXT: Flags [ # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1024 +# CHECK-NEXT: Offset: 0x2018 # CHECK-NEXT: Size: 48 # CHECK-NEXT: Link: 6 # CHECK-NEXT: Info: 1 @@ -140,7 +140,7 @@ _start: # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1054 +# CHECK-NEXT: Offset: 0x2048 # CHECK-NEXT: Size: 46 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -149,17 +149,30 @@ _start: # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: ProgramHeaders [ -# CHECK-NEXT: ProgramHeader { -# CHECK-NEXT: Type: PT_LOAD (0x1) -# CHECK-NEXT: Offset: 0x1000 -# CHECK-NEXT: VirtualAddress: 0x1000 -# CHECK-NEXT: PhysicalAddress: 0x1000 -# CHECK-NEXT: FileSize: 4680 -# CHECK-NEXT: MemSize: 4680 -# CHECK-NEXT: Flags [ (0x5) -# CHECK-NEXT: PF_R (0x4) -# CHECK-NEXT: PF_X (0x1) -# CHECK-NEXT: ] -# CHECK-NEXT: Alignment: 16384 -# CHECK-NEXT: } -# CHECK-NEXT: ] +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_LOAD (0x1) +# CHECK-NEXT: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: 0x1000 +# CHECK-NEXT: PhysicalAddress: 0x1000 +# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: MemSize: 12 +# 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_LOAD (0x1) +# CHECK-NEXT: Offset: 0x2000 +# CHECK-NEXT: VirtualAddress: 0x2000 +# CHECK-NEXT: PhysicalAddress: 0x2000 +# CHECK-NEXT: FileSize: 24 +# CHECK-NEXT: MemSize: 24 +# CHECK-NEXT: Flags [ (0x6) +# CHECK-NEXT: PF_R (0x4) +# CHECK-NEXT: PF_W (0x2) +# CHECK-NEXT: ] +# CHECK-NEXT: Alignment: 4096 +# CHECK-NEXT: } +# CHECK-NEXT:] diff --git a/lld/test/elf2/relocation.s b/lld/test/elf2/relocation.s index 054846ea403..7c1e920d38e 100644 --- a/lld/test/elf2/relocation.s +++ b/lld/test/elf2/relocation.s @@ -26,4 +26,4 @@ bar: // CHECK: e8 04 00 00 00 callq 4 // Also check that symbols match. -// CHECK: 0000000000001000 .text 00000000 bar +// CHECK: 000000000001000 .text 00000000 bar diff --git a/lld/test/elf2/symbols.s b/lld/test/elf2/symbols.s index eb8a549f410..8fb9a0cac5b 100644 --- a/lld/test/elf2/symbols.s +++ b/lld/test/elf2/symbols.s @@ -59,8 +59,8 @@ internal: // CHECK-NEXT: SHF_ALLOC (0x2) // CHECK-NEXT: SHF_WRITE (0x1) // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1004 -// CHECK-NEXT: Offset: 0x1004 +// CHECK-NEXT: Address: 0x2000 +// CHECK-NEXT: Offset: 0x2000 // CHECK-NEXT: Size: 4 // CHECK: Name: foobar @@ -68,7 +68,7 @@ internal: // CHECK-NEXT: Flags [ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x1008 +// CHECK-NEXT: Address: 0x3000 // CHECK: Symbols [ // CHECK-NEXT: Symbol { @@ -118,7 +118,7 @@ internal: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: common (34) -// CHECK-NEXT: Value: 0x1004 +// CHECK-NEXT: Value: 0x2000 // CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Global (0x1) // CHECK-NEXT: Type: Object (0x1) @@ -127,7 +127,7 @@ internal: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed -// CHECK-NEXT: Value: 0x1008 +// CHECK-NEXT: Value: 0x3000 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global (0x1) // CHECK-NEXT: Type: None @@ -136,7 +136,7 @@ internal: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: protected -// CHECK-NEXT: Value: 0x1010 +// CHECK-NEXT: Value: 0x3008 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None @@ -145,7 +145,7 @@ internal: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed3 -// CHECK-NEXT: Value: 0x1010 +// CHECK-NEXT: Value: 0x3008 // CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None @@ -154,7 +154,7 @@ internal: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: zed2 -// CHECK-NEXT: Value: 0x100C +// CHECK-NEXT: Value: 0x3004 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None |

