This is a minimal implementation to produce legal output. Future patches will combine multiple compatible PT_LOADs.
llvm-svn: 247185
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;
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) {
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;
// 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;
# 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: ]
# 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: ]
# 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: ]
# 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
# 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
# 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
# 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
# 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:]
// CHECK: e8 04 00 00 00 callq 4
// Also check that symbols match.
-// CHECK: 0000000000001000 .text 00000000 bar
+// CHECK: 000000000001000 .text 00000000 bar
// 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
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x1008
+// CHECK-NEXT: Address: 0x3000
// CHECK: Symbols [
// CHECK-NEXT: Symbol {
// 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)
// 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
// 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
// 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
// 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