summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/LinkerScript.cpp48
-rw-r--r--lld/ELF/LinkerScript.h1
-rw-r--r--lld/ELF/Writer.cpp2
-rw-r--r--lld/test/ELF/linkerscript/Inputs/implicit-program-header.script12
-rw-r--r--lld/test/ELF/linkerscript/implicit-program-header.s13
5 files changed, 58 insertions, 18 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 2cf088e91e2..c8ca74abd86 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -563,6 +563,35 @@ template <class ELFT> void LinkerScript<ELFT>::adjustSectionsBeforeSorting() {
auto *OutSec = make<OutputSection<ELFT>>(Cmd->Name, Type, Flags);
OutputSections->push_back(OutSec);
}
+}
+
+template <class ELFT> void LinkerScript<ELFT>::adjustSectionsAfterSorting() {
+ placeOrphanSections();
+
+ // 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) } }
+ std::vector<StringRef> DefPhdrs;
+ auto FirstPtLoad =
+ std::find_if(Opt.PhdrsCommands.begin(), Opt.PhdrsCommands.end(),
+ [](const PhdrsCommand &Cmd) { return Cmd.Type == PT_LOAD; });
+ if (FirstPtLoad != Opt.PhdrsCommands.end())
+ DefPhdrs.push_back(FirstPtLoad->Name);
+
+ // Walk the commands and propagate the program headers to commands that don't
+ // explicitly specify them.
+ for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
+ auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
+ if (!Cmd)
+ continue;
+ if (Cmd->Phdrs.empty())
+ Cmd->Phdrs = DefPhdrs;
+ else
+ DefPhdrs = Cmd->Phdrs;
+ }
removeEmptyCommands();
}
@@ -630,8 +659,6 @@ void LinkerScript<ELFT>::placeOrphanSections() {
template <class ELFT>
void LinkerScript<ELFT>::assignAddresses(std::vector<PhdrEntry<ELFT>> &Phdrs) {
- placeOrphanSections();
-
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = 0;
@@ -711,7 +738,6 @@ 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();
@@ -725,15 +751,6 @@ 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.
@@ -741,17 +758,12 @@ std::vector<PhdrEntry<ELFT>> LinkerScript<ELFT>::createPhdrs() {
if (!(Sec->Flags & SHF_ALLOC))
break;
- std::vector<size_t> PhdrIds = getPhdrIndices(Sec->getName());
- if (PhdrIds.empty())
- PhdrIds = std::move(DefPhdrIds);
-
// Assign headers specified by linker script
- for (size_t Id : PhdrIds) {
+ for (size_t Id : getPhdrIndices(Sec->getName())) {
Ret[Id].add(Sec);
if (Opt.PhdrsCommands[Id].Flags == UINT_MAX)
Ret[Id].H.p_flags |= Sec->getPhdrFlags();
}
- DefPhdrIds = std::move(PhdrIds);
}
return Ret;
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 6bd02f13c2f..ce645269f77 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -221,6 +221,7 @@ public:
void createSections(OutputSectionFactory<ELFT> &Factory);
void removeEmptyCommands();
void adjustSectionsBeforeSorting();
+ void adjustSectionsAfterSorting();
std::vector<PhdrEntry<ELFT>> createPhdrs();
bool ignoreInterpSection();
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 9776f62fdb6..2117e47e781 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -856,6 +856,8 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
std::rotate(BestPos, NonScriptI, NonScriptI + 1);
++NonScriptI;
}
+
+ Script<ELFT>::X->adjustSectionsAfterSorting();
}
// Create output section objects and add them to OutputSections.
diff --git a/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script b/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script
new file mode 100644
index 00000000000..27dbea84c4e
--- /dev/null
+++ b/lld/test/ELF/linkerscript/Inputs/implicit-program-header.script
@@ -0,0 +1,12 @@
+PHDRS
+{
+ ph_write PT_LOAD FLAGS(2);
+ ph_exec PT_LOAD FLAGS(1);
+}
+
+SECTIONS
+{
+ .bar : { *(.bar) } : ph_exec
+ .foo : { *(.foo) }
+ .text : { *(.text) } : ph_write
+}
diff --git a/lld/test/ELF/linkerscript/implicit-program-header.s b/lld/test/ELF/linkerscript/implicit-program-header.s
new file mode 100644
index 00000000000..9598a6abebb
--- /dev/null
+++ b/lld/test/ELF/linkerscript/implicit-program-header.s
@@ -0,0 +1,13 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -o %t1 --script %S/Inputs/implicit-program-header.script \
+# RUN: %t.o -shared
+# RUN: llvm-readobj -elf-output-style=GNU -l %t1 | FileCheck %s
+
+# CHECK: Segment Sections...
+# CHECK-NEXT: 00 .text .dynsym .hash .dynstr .dynamic
+# CHECK-NEXT: 01 .foo
+
+.quad 0
+.section .foo,"ax"
+.quad 0
OpenPOWER on IntegriCloud