diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 779f832f5d23..8f0c7f2ac0f9 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -558,6 +558,17 @@ template void Writer::assignAddresses() { FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8); } +static uint32_t convertSectionFlagsToSegmentFlags(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 void Writer::writeHeader() { uint8_t *Buf = Buffer->getBufferStart(); auto *EHdr = reinterpret_cast(Buf); @@ -572,8 +583,17 @@ template void Writer::writeHeader() { EHdr->e_ident[EI_VERSION] = EV_CURRENT; EHdr->e_ident[EI_OSABI] = ELFOSABI_NONE; - EHdr->e_type = ET_EXEC; + // FIXME: Generalize the segment construction similar to how we create + // output sections. + unsigned NumSegments = 1; const SymbolTable &Symtab = SymTable.getSymTable(); + const std::vector> &SharedFiles = + Symtab.getSharedFiles(); + bool HasDynamicSegment = !SharedFiles.empty(); + if (HasDynamicSegment) + NumSegments++; + + EHdr->e_type = ET_EXEC; auto &FirstObj = cast>(*Symtab.getFirstELF()); EHdr->e_machine = FirstObj.getEMachine(); EHdr->e_version = EV_CURRENT; @@ -582,7 +602,7 @@ template void Writer::writeHeader() { EHdr->e_shoff = SectionHeaderOff; EHdr->e_ehsize = sizeof(Elf_Ehdr); EHdr->e_phentsize = sizeof(Elf_Phdr); - EHdr->e_phnum = 1; + EHdr->e_phnum = NumSegments; EHdr->e_shentsize = sizeof(Elf_Shdr); EHdr->e_shnum = getNumSections(); EHdr->e_shstrndx = StringTable.getSectionIndex(); @@ -597,6 +617,18 @@ template void Writer::writeHeader() { PHdrs->p_memsz = FileSize; PHdrs->p_align = 0x4000; + if (HasDynamicSegment) { + PHdrs++; + PHdrs->p_type = PT_DYNAMIC; + PHdrs->p_flags = convertSectionFlagsToSegmentFlags(DynamicSec.getFlags()); + PHdrs->p_offset = DynamicSec.getFileOff(); + PHdrs->p_vaddr = DynamicSec.getVA(); + PHdrs->p_paddr = PHdrs->p_vaddr; + PHdrs->p_filesz = 0; + PHdrs->p_memsz = 0; + PHdrs->p_align = DynamicSec.getAlign(); + } + auto SHdrs = reinterpret_cast(Buf + EHdr->e_shoff); // First entry is null. ++SHdrs; diff --git a/lld/test/elf2/shared.s b/lld/test/elf2/shared.s index 7d8ac5a74292..7a45e34d8009 100644 --- a/lld/test/elf2/shared.s +++ b/lld/test/elf2/shared.s @@ -1,6 +1,6 @@ // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o // RUN: lld -flavor gnu2 %t.o %p/Inputs/i686-simple-library.so -o %t -// RUN: llvm-readobj -t -s %t | FileCheck %s +// RUN: llvm-readobj --program-headers -t -s %t | FileCheck %s // REQUIRES: x86 // CHECK: Name: .dynamic @@ -9,16 +9,16 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: -// CHECK-NEXT: Offset: -// CHECK-NEXT: Size: -// CHECK-NEXT: Link: 6 +// CHECK-NEXT: Address: [[ADDR:.*]] +// CHECK-NEXT: Offset: [[OFFSET:.*]] +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Link: [[STRTAB:.*]] // CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 4 +// CHECK-NEXT: AddressAlignment: [[ALIGN:.*]] // CHECK-NEXT: EntrySize: 8 // CHECK-NEXT: } -// CHECK: Index: 6 +// CHECK: Index: [[STRTAB]] // CHECK-NEXT: Name: .strtab // CHECK-NEXT: Type: SHT_STRTAB // CHECK-NEXT: Flags [ @@ -63,6 +63,21 @@ // CHECK-NEXT: } // CHECK-NEXT: ] + +// CHECK: ProgramHeader { +// CHECK: Type: PT_DYNAMIC +// CHECK-NEXT: Offset: [[OFFSET]] +// CHECK-NEXT: VirtualAddress: [[ADDR]] +// CHECK-NEXT: PhysicalAddress: [[ADDR]] +// CHECK-NEXT: FileSize: 0 +// CHECK-NEXT: MemSize: 0 +// CHECK-NEXT: Flags [ +// CHECK-NEXT: PF_R +// CHECK-NEXT: PF_W +// CHECK-NEXT: ] +// CHECK-NEXT: Alignment: [[ALIGN]] +// CHECK-NEXT: } + .global _start _start: .long bar