summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Writer.cpp36
-rw-r--r--lld/test/elf2/shared.s29
2 files changed, 56 insertions, 9 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 779f832f5d2..8f0c7f2ac0f 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -558,6 +558,17 @@ template <class ELFT> void Writer<ELFT>::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 <class ELFT> void Writer<ELFT>::writeHeader() {
uint8_t *Buf = Buffer->getBufferStart();
auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
@@ -572,8 +583,17 @@ template <class ELFT> void Writer<ELFT>::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<std::unique_ptr<SharedFileBase>> &SharedFiles =
+ Symtab.getSharedFiles();
+ bool HasDynamicSegment = !SharedFiles.empty();
+ if (HasDynamicSegment)
+ NumSegments++;
+
+ EHdr->e_type = ET_EXEC;
auto &FirstObj = cast<ObjectFile<ELFT>>(*Symtab.getFirstELF());
EHdr->e_machine = FirstObj.getEMachine();
EHdr->e_version = EV_CURRENT;
@@ -582,7 +602,7 @@ template <class ELFT> void Writer<ELFT>::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 <class ELFT> void Writer<ELFT>::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<Elf_Shdr *>(Buf + EHdr->e_shoff);
// First entry is null.
++SHdrs;
diff --git a/lld/test/elf2/shared.s b/lld/test/elf2/shared.s
index 7d8ac5a7429..7a45e34d800 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
OpenPOWER on IntegriCloud