[PATCH] D24668: [ELF] Linkerscript: do not fail if there is no space for program headers and there is PHDRS directive

Eugene Leviant via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 16 08:08:41 PDT 2016


evgeny777 created this revision.
evgeny777 added reviewers: ruiu, rafael.
evgeny777 added subscribers: grimar, llvm-commits.
evgeny777 set the repository for this revision to rL LLVM.
evgeny777 added a project: lld.

After http://llvm.org/viewvc/llvm-project?view=revision&revision=281660
linking no works for me, because if first section VA is less than size of headers lld emits fatal error.

However in case we have PHDRS directive it doesn't really have to do so, because with PHDRS we can tell lld not to emit program headers or assign separate segment for them.
This patch does two things:

a) Do not emit fatal error in case hasPhdrsCommands() is true
b) Set elf headers VA to the end of the section, so there are more chances it is valid.

Repository:
  rL LLVM

https://reviews.llvm.org/D24668

Files:
  ELF/LinkerScript.cpp
  test/ELF/linkerscript/phdrs.s

Index: test/ELF/linkerscript/phdrs.s
===================================================================
--- test/ELF/linkerscript/phdrs.s
+++ test/ELF/linkerscript/phdrs.s
@@ -19,6 +19,16 @@
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s
 
+## Check PHDR VA.
+# RUN: echo "PHDRS { header PT_PHDR PHDRS; other PT_LOAD; } \
+# RUN:       SECTIONS { \
+# RUN:           . = 0; \
+# RUN:           .text : {*(.text*)} : other \
+# RUN:           .foo : {*(.foo.*)} : other \
+# RUN:           .data : {*(.data.*)} : other }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=PHDR %s
+
 # CHECK:     ProgramHeaders [
 # CHECK-NEXT:  ProgramHeader {
 # CHECK-NEXT:    Type: PT_LOAD (0x1)
@@ -47,6 +57,35 @@
 # AT-NEXT:        PF_X (0x1)
 # AT-NEXT:      ]
 
+# PHDR:     ProgramHeaders [
+# PHDR-NEXT:  ProgramHeader {
+# PHDR-NEXT:    Type: PT_PHDR (0x6)
+# PHDR-NEXT:    Offset: 0x40
+# PHDR-NEXT:    VirtualAddress: 0x1040
+# PHDR-NEXT:    PhysicalAddress: 0x1040
+# PHDR-NEXT:    FileSize: 112
+# PHDR-NEXT:    MemSize: 112
+# PHDR-NEXT:    Flags [ (0x4)
+# PHDR-NEXT:      PF_R (0x4)
+# PHDR-NEXT:    ]
+# PHDR-NEXT:    Alignment: 8
+# PHDR-NEXT:  }
+# PHDR-NEXT:  ProgramHeader {
+# PHDR-NEXT:    Type: PT_LOAD (0x1)
+# PHDR-NEXT:    Offset: 0x1000
+# PHDR-NEXT:    VirtualAddress: 0x0
+# PHDR-NEXT:    PhysicalAddress: 0x0
+# PHDR-NEXT:    FileSize: 9
+# PHDR-NEXT:    MemSize: 9
+# PHDR-NEXT:    Flags [ (0x7)
+# PHDR-NEXT:      PF_R (0x4)
+# PHDR-NEXT:      PF_W (0x2)
+# PHDR-NEXT:      PF_X (0x1)
+# PHDR-NEXT:    ]
+# PHDR-NEXT:    Alignment: 4096
+# PHDR-NEXT:  }
+# PHDR-NEXT: ]
+
 .global _start
 _start:
  nop
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -420,7 +420,7 @@
 
   // Assign addresses as instructed by linker script SECTIONS sub-commands.
   Dot = getHeaderSize();
-  uintX_t MinVA = std::numeric_limits<uintX_t>::max();
+  uintX_t HeaderVA = std::numeric_limits<uintX_t>::max();
   uintX_t ThreadBssOffset = 0;
 
   for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
@@ -462,21 +462,21 @@
       Dot = alignTo(Dot, Sec->getAlignment());
       Sec->setVA(Dot);
       assignOffsets(Cmd, Sec);
-      MinVA = std::min(MinVA, Dot);
+      HeaderVA = std::min(HeaderVA, Dot);
       Dot += Sec->getSize();
     }
   }
 
   uintX_t HeaderSize =
       Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
-  if (HeaderSize > MinVA)
+  if (HeaderSize > HeaderVA && !hasPhdrsCommands())
     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);
+  HeaderVA = HeaderSize > HeaderVA
+                 ? alignTo(Dot, Target->PageSize)
+                 : alignDown(HeaderVA - HeaderSize, Target->PageSize);
+  Out<ELFT>::ElfHeader->setVA(HeaderVA);
+  Out<ELFT>::ProgramHeaders->setVA(Out<ELFT>::ElfHeader->getSize() + HeaderVA);
 }
 
 // Creates program headers as instructed by PHDRS linker script command.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D24668.71648.patch
Type: text/x-patch
Size: 3410 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160916/9e434258/attachment.bin>


More information about the llvm-commits mailing list