Don't error if we can't put the header in a PT_LOAD.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 29 Sep 2016 18:50:34 +0000 (18:50 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 29 Sep 2016 18:50:34 +0000 (18:50 +0000)
If there is not sufficient address space, just give up and don't put
the header in the PT_LOAD.

This matches bfd behaviour and I found at least one script that
depends on having a section at address 0.

llvm-svn: 282750

lld/ELF/LinkerScript.cpp
lld/ELF/LinkerScript.h
lld/ELF/Writer.cpp
lld/test/ELF/linkerscript/no-space.s

index e9885d4..b979d06 100644 (file)
@@ -553,7 +553,8 @@ static bool shouldSkip(const BaseCommand &Cmd) {
   return Assign->Name != ".";
 }
 
-template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
+template <class ELFT>
+void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
   // Orphan sections are sections present in the input files which
   // are not explicitly placed into the output file by the linker script.
   // We place orphan sections at end of file.
@@ -628,14 +629,20 @@ template <class ELFT> void LinkerScript<ELFT>::assignAddresses() {
   }
 
   uintX_t HeaderSize = getHeaderSize();
-  if (HeaderSize > MinVA)
-    fatal("Not enough space for ELF and program headers");
-
-  // ELF and Program headers need to be right before the first section in
-  // memory. Set their addresses accordingly.
-  MinVA = alignDown(MinVA - HeaderSize, Target->PageSize);
-  Out<ELFT>::ElfHeader->setVA(MinVA);
-  Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
+  auto FirstPTLoad =
+      std::find_if(Phdrs.begin(), Phdrs.end(), [](const PhdrEntry<ELFT> &E) {
+        return E.H.p_type == PT_LOAD;
+      });
+  if (HeaderSize <= MinVA && FirstPTLoad != Phdrs.end()) {
+    // ELF and Program headers need to be right before the first section in
+    // memory. Set their addresses accordingly.
+    MinVA = alignDown(MinVA - HeaderSize, Target->PageSize);
+    Out<ELFT>::ElfHeader->setVA(MinVA);
+    Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + MinVA);
+    FirstPTLoad->First = Out<ELFT>::ElfHeader;
+    if (!FirstPTLoad->Last)
+      FirstPTLoad->Last = Out<ELFT>::ProgramHeaders;
+  }
 }
 
 // Creates program headers as instructed by PHDRS linker script command.
index 59f47d6..47b7b68 100644 (file)
@@ -208,7 +208,7 @@ public:
   Expr getLma(StringRef Name);
   bool shouldKeep(InputSectionBase<ELFT> *S);
   void assignOffsets(OutputSectionCommand *Cmd);
-  void assignAddresses();
+  void assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs);
   bool hasPhdrsCommands();
   uint64_t getOutputSectionAddress(StringRef Name) override;
   uint64_t getOutputSectionSize(StringRef Name) override;
index ac1d159..9f1346c 100644 (file)
@@ -275,7 +275,7 @@ template <class ELFT> void Writer<ELFT>::run() {
                                                 : createPhdrs();
     fixHeaders();
     if (ScriptConfig->HasSections) {
-      Script<ELFT>::X->assignAddresses();
+      Script<ELFT>::X->assignAddresses(Phdrs);
     } else {
       fixSectionAlignments();
       assignAddresses();
@@ -1047,8 +1047,10 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
   // Add the first PT_LOAD segment for regular output sections.
   uintX_t Flags = computeFlags<ELFT>(PF_R);
   Phdr *Load = AddHdr(PT_LOAD, Flags);
-  Load->add(Out<ELFT>::ElfHeader);
-  Load->add(Out<ELFT>::ProgramHeaders);
+  if (!ScriptConfig->HasSections) {
+    Load->add(Out<ELFT>::ElfHeader);
+    Load->add(Out<ELFT>::ProgramHeaders);
+  }
 
   Phdr TlsHdr(PT_TLS, PF_R);
   Phdr RelRo(PT_GNU_RELRO, PF_R);
index f24a72a..e8b6be7 100644 (file)
@@ -2,9 +2,21 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 
 # RUN: echo "SECTIONS {foo 0 : {*(foo*)} }" > %t.script
-# RUN: not ld.lld -o %t --script %t.script %t.o -shared 2>&1 | FileCheck %s
+# RUN: ld.lld -o %t --script %t.script %t.o -shared
+# RUN: llvm-readobj -elf-output-style=GNU -l %t | FileCheck %s
 
-# CHECK: Not enough space for ELF and program headers
+# There is not enough address space available for the header, so just start the PT_LOAD
+# after it.
+
+# CHECK: Program Headers:
+# CHECK-NEXT: Type  Offset   VirtAddr           PhysAddr
+# CHECK-NEXT: PHDR
+# CHECK-NEXT: LOAD  0x001000 0x0000000000000000 0x0000000000000000
+
+# CHECK:      Section to Segment mapping:
+# CHECK-NEXT:  Segment Sections...
+# CHECK-NEXT:   00
+# CHECK-NEXT:   01     foo .dynsym .hash .dynstr
 
 .section foo, "a"
 .quad 0