summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-11-14 15:39:38 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-11-14 15:39:38 +0000
commitf7a17448034721548bf26884df9349acd6e149a2 (patch)
treec193c9b71d9af10ae26c55d7195cddf7f58f23cf
parent2b46120a090e8270a46dfdc1c377cfd4f7c13966 (diff)
downloadbcm5719-llvm-f7a17448034721548bf26884df9349acd6e149a2.tar.gz
bcm5719-llvm-f7a17448034721548bf26884df9349acd6e149a2.zip
Fix program header propagation.
Propagate program headers by walking the commands, not the sections. This allows us to propagate program headers even from sections that don't end up in the output. Fixes pr30997. llvm-svn: 286837
-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