[ELF] Choose default segment when it is not specified
authorEugene Leviant <evgeny.leviant@gmail.com>
Wed, 19 Oct 2016 15:04:49 +0000 (15:04 +0000)
committerEugene Leviant <evgeny.leviant@gmail.com>
Wed, 19 Oct 2016 15:04:49 +0000 (15:04 +0000)
Linker scripts may specify PHDRS, but not specify section to
segment assignments, i.e:

PHDRS { seg PT_LOAD; }
SECTIONS {
  .sec1 {} : seg
  .sec2 {}
}

In such case linker should still choose some segment for .sec2 section.
This patch will add .sec2 to previously opened segments (seg) or to the
very first PT_LOAD segment, if no section-to-segment assignments has been
made

Differential revision: https://reviews.llvm.org/D24795

llvm-svn: 284600

lld/ELF/LinkerScript.cpp
lld/test/ELF/linkerscript/openbsd-randomize.s
lld/test/ELF/linkerscript/phdrs-flags.s
lld/test/ELF/linkerscript/phdrs.s

index fb74541..b7783e4 100644 (file)
@@ -682,6 +682,7 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
 
   // Process PHDRS and FILEHDR keywords because they are not
   // real output sections and cannot be added in the following loop.
+  std::vector<size_t> DefPhdrIds;
   for (const PhdrsCommand &Cmd : Opt.PhdrsCommands) {
     Ret.emplace_back(Cmd.Type, Cmd.Flags == UINT_MAX ? PF_R : Cmd.Flags);
     PhdrEntry<ELFT> &Phdr = Ret.back();
@@ -695,33 +696,33 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
       Phdr.H.p_paddr = Cmd.LMAExpr(0);
       Phdr.HasLMA = true;
     }
+
+    // If output section command doesn't specify any segments,
+    // and we haven't previously assigned any section to segment,
+    // then we simply assign section to the very first load segment.
+    // Below is an example of such linker script:
+    // PHDRS { seg PT_LOAD; }
+    // SECTIONS { .aaa : { *(.aaa) } }
+    if (DefPhdrIds.empty() && Phdr.H.p_type == PT_LOAD)
+      DefPhdrIds.push_back(Ret.size() - 1);
   }
 
   // Add output sections to program headers.
-  PhdrEntry<ELFT> *Load = nullptr;
-  uintX_t Flags = PF_R;
   for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
     if (!(Sec->getFlags() & SHF_ALLOC))
       break;
 
     std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName());
-    if (!PhdrIds.empty()) {
-      // Assign headers specified by linker script
-      for (size_t Id : PhdrIds) {
-        Ret[Id].add(Sec);
-        if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
-          Ret[Id].H.p_flags |= Sec->getPhdrFlags();
-      }
-    } else {
-      // If we have no load segment or flags've changed then we want new load
-      // segment.
-      uintX_t NewFlags = Sec->getPhdrFlags();
-      if (Load == nullptr || Flags != NewFlags) {
-        Load = &*Ret.emplace(Ret.end(), PT_LOAD, NewFlags);
-        Flags = NewFlags;
-      }
-      Load->add(Sec);
+    if (PhdrIds.empty())
+      PhdrIds = std::move(DefPhdrIds);
+
+    // Assign headers specified by linker script
+    for (size_t Id : PhdrIds) {
+      Ret[Id].add(Sec);
+      if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
+        Ret[Id].H.p_flags |= Sec->getPhdrFlags();
     }
+    DefPhdrIds = std::move(PhdrIds);
   }
   return Ret;
 }
index a6cd9ab..bf885f4 100644 (file)
@@ -1,15 +1,16 @@
 # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
 # RUN: echo "PHDRS { text PT_LOAD FILEHDR PHDRS; rand PT_OPENBSD_RANDOMIZE; } \
 # RUN:       SECTIONS { . = SIZEOF_HEADERS; \
+# RUN:         .text : { *(.text) } \
 # RUN:         .openbsd.randomdata : { *(.openbsd.randomdata) } : rand }" > %t.script
 # RUN: ld.lld --script %t.script %t.o -o %t
 # RUN: llvm-readobj --program-headers -s %t | FileCheck %s
 
 # CHECK:      ProgramHeader {
 # CHECK:        Type: PT_OPENBSD_RANDOMIZE (0x65A3DBE6)
-# CHECK-NEXT:   Offset: 0x94
-# CHECK-NEXT:   VirtualAddress: 0x94
-# CHECK-NEXT:   PhysicalAddress: 0x94
+# CHECK-NEXT:   Offset: 0x74
+# CHECK-NEXT:   VirtualAddress: 0x74
+# CHECK-NEXT:   PhysicalAddress: 0x74
 # CHECK-NEXT:   FileSize: 8
 # CHECK-NEXT:   MemSize: 8
 # CHECK-NEXT:   Flags [ (0x4)
index d90c042..3cb6432 100644 (file)
@@ -6,9 +6,18 @@
 # RUN:           .text : {*(.text*)} :all \
 # RUN:           .foo : {*(.foo.*)} :all \
 # RUN:           .data : {*(.data.*)} :all}" > %t.script
-
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-readobj -program-headers %t1 | FileCheck %s
+
+# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (0x1);} \
+# RUN:       SECTIONS { \
+# RUN:           . = 0x10000200; \
+# RUN:           .text : {*(.text*)} :all \
+# RUN:           .foo : {*(.foo.*)}  \
+# RUN:           .data : {*(.data.*)} }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s
+
 # CHECK:     ProgramHeaders [
 # CHECK-NEXT:  ProgramHeader {
 # CHECK-NEXT:    Type: PT_LOAD (0x1)
 # CHECK-NEXT:      PF_X (0x1)
 # CHECK-NEXT:    ]
 
+# DEFHDR:     ProgramHeaders [
+# DEFHDR-NEXT:  ProgramHeader {
+# DEFHDR-NEXT:    Type: PT_LOAD (0x1)
+# DEFHDR-NEXT:    Offset: 0x0
+# DEFHDR-NEXT:    VirtualAddress: 0x10000000
+# DEFHDR-NEXT:    PhysicalAddress: 0x10000000
+# DEFHDR-NEXT:    FileSize: 521
+# DEFHDR-NEXT:    MemSize: 521
+# DEFHDR-NEXT:    Flags [ (0x1)
+# DEFHDR-NEXT:      PF_X (0x1)
+# DEFHDR-NEXT:    ]
+# DEFHDR-NEXT:    Alignment: 4096
+# DEFHDR-NEXT:  }
+
 .global _start
 _start:
  nop
index 7d5201c..67c1e35 100644 (file)
 # RUN: ld.lld -o %t1 --script %t.script %t
 # RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s
 
+# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \
+# RUN:       SECTIONS { \
+# RUN:           . = 0x10000200; \
+# RUN:           .text : {*(.text*)} :all \
+# RUN:           .foo : {*(.foo.*)}  \
+# RUN:           .data : {*(.data.*)} }" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s
+
 # CHECK:     ProgramHeaders [
 # CHECK-NEXT:  ProgramHeader {
 # CHECK-NEXT:    Type: PT_LOAD (0x1)
 # INT-PHDRS-NEXT:    }
 # INT-PHDRS-NEXT:  ]
 
+# DEFHDR:     ProgramHeaders [
+# DEFHDR-NEXT:  ProgramHeader {
+# DEFHDR-NEXT:    Type: PT_LOAD (0x1)
+# DEFHDR-NEXT:    Offset: 0x0
+# DEFHDR-NEXT:    VirtualAddress: 0x10000000
+# DEFHDR-NEXT:    PhysicalAddress: 0x10000000
+# DEFHDR-NEXT:    FileSize: 521
+# DEFHDR-NEXT:    MemSize: 521
+# DEFHDR-NEXT:    Flags [ (0x7)
+# DEFHDR-NEXT:      PF_R (0x4)
+# DEFHDR-NEXT:      PF_W (0x2)
+# DEFHDR-NEXT:      PF_X (0x1)
+# DEFHDR-NEXT:    ]
+
 .global _start
 _start:
  nop