[lld] r281778 - Put SHF_ALLOC sections first, even with linker scripts.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 16 14:29:08 PDT 2016
Author: rafael
Date: Fri Sep 16 16:29:07 2016
New Revision: 281778
URL: http://llvm.org/viewvc/llvm-project?rev=281778&view=rev
Log:
Put SHF_ALLOC sections first, even with linker scripts.
This matches gold and bfd, and is pretty much required by some linker
scripts. They end with commands like
foo 0 : { *(bar) }
if we put any SHF_ALLOC sections after they can have an address that
is too low.
Modified:
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/linkerscript/non-alloc.s
lld/trunk/test/ELF/linkerscript/sections.s
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=281778&r1=281777&r2=281778&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Sep 16 16:29:07 2016
@@ -453,15 +453,42 @@ template <class ELFT> void LinkerScript<
// We place orphan sections at end of file.
// Other linkers places them using some heuristics as described in
// https://sourceware.org/binutils/docs/ld/Orphan-Sections.html#Orphan-Sections.
+
+ // The OutputSections are already in the correct order.
+ // This loops creates or moves commands as needed so that they are in the
+ // correct order.
+ int CmdIndex = 0;
for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
StringRef Name = Sec->getName();
- if (getSectionIndex(Name) == INT_MAX)
- Opt.Commands.push_back(llvm::make_unique<OutputSectionCommand>(Name));
+
+ // Find the last spot where we can insert a command and still get the
+ // correct order.
+ auto CmdIter = Opt.Commands.begin() + CmdIndex;
+ auto E = Opt.Commands.end();
+ while (CmdIter != E && !isa<OutputSectionCommand>(**CmdIter)) {
+ ++CmdIter;
+ ++CmdIndex;
+ }
+
+ auto Pos =
+ std::find_if(CmdIter, E, [&](const std::unique_ptr<BaseCommand> &Base) {
+ auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get());
+ return Cmd && Cmd->Name == Name;
+ });
+ if (Pos == E) {
+ Opt.Commands.insert(CmdIter,
+ llvm::make_unique<OutputSectionCommand>(Name));
+ } else {
+ // If linker script lists alloc/non-alloc sections is the wrong order,
+ // this does a right rotate to bring the desired command in place.
+ auto RPos = make_reverse_iterator(Pos + 1);
+ std::rotate(RPos, RPos + 1, make_reverse_iterator(CmdIter));
+ }
+ ++CmdIndex;
}
// Assign addresses as instructed by linker script SECTIONS sub-commands.
Dot = getHeaderSize();
- uintX_t MinVA = std::numeric_limits<uintX_t>::max();
for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
@@ -483,13 +510,17 @@ template <class ELFT> void LinkerScript<
if (Cmd->AddrExpr)
Dot = Cmd->AddrExpr(Dot);
- MinVA = std::min(MinVA, Dot);
assignOffsets(Cmd);
}
- for (OutputSectionBase<ELFT> *Sec : *OutputSections)
- if (!(Sec->getFlags() & SHF_ALLOC))
+ uintX_t MinVA = std::numeric_limits<uintX_t>::max();
+ for (OutputSectionBase<ELFT> *Sec : *OutputSections) {
+ if (Sec->getFlags() & SHF_ALLOC)
+ MinVA = std::min(MinVA, Sec->getVA());
+ else
Sec->setVA(0);
+ }
+
uintX_t HeaderSize =
Out<ELFT>::ElfHeader->getSize() + Out<ELFT>::ProgramHeaders->getSize();
if (HeaderSize > MinVA)
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=281778&r1=281777&r2=281778&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Fri Sep 16 16:29:07 2016
@@ -437,10 +437,6 @@ static bool compareSections(OutputSectio
OutputSectionBase<ELFT> *B) {
typedef typename ELFT::uint uintX_t;
- int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName());
- if (Comp != 0)
- return Comp < 0;
-
uintX_t AFlags = A->getFlags();
uintX_t BFlags = B->getFlags();
@@ -451,6 +447,10 @@ static bool compareSections(OutputSectio
if (AIsAlloc != BIsAlloc)
return AIsAlloc;
+ int Comp = Script<ELFT>::X->compareSections(A->getName(), B->getName());
+ if (Comp != 0)
+ return Comp < 0;
+
// We don't have any special requirements for the relative order of
// two non allocatable sections.
if (!AIsAlloc)
@@ -971,15 +971,8 @@ std::vector<PhdrEntry<ELFT>> Writer<ELFT
Phdr RelRo(PT_GNU_RELRO, PF_R);
Phdr Note(PT_NOTE, PF_R);
for (OutputSectionBase<ELFT> *Sec : OutputSections) {
- // Skip non alloc section.
- // The reason we skip instead of just breaking out of the loop is the way
- // we implement linker scripts. We always put the linker script sections
- // first, which means that a non alloc section can be in the middle of the
- // file. Continuing in here means it will be included in a PT_LOAD anyway.
- // We should probably sort sections based of SHF_ALLOC even if they are
- // on linker scripts.
if (!(Sec->getFlags() & SHF_ALLOC))
- continue;
+ break;
// If we meet TLS section then we create TLS header
// and put all TLS sections inside for futher use when
Modified: lld/trunk/test/ELF/linkerscript/non-alloc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/non-alloc.s?rev=281778&r1=281777&r2=281778&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/non-alloc.s (original)
+++ lld/trunk/test/ELF/linkerscript/non-alloc.s Fri Sep 16 16:29:07 2016
@@ -1,13 +1,12 @@
# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
-# RUN: echo "SECTIONS { .foo : {*(foo)} }" > %t.script
+# RUN: echo "SECTIONS { .foo 0 : {*(foo)} }" > %t.script
# RUN: ld.lld -o %t1 --script %t.script %t -shared
# RUN: llvm-readobj -elf-output-style=GNU -s -l %t1 | FileCheck %s
-# Test that we create all necessary PT_LOAD. It is a harmless oddity that
-# foo ends in a PT_LOAD. We use to stop at the first non-alloc, causing
-# us to not create PT_LOAD for linker generated sections.
+# Test that we create all necessary PT_LOAD. We use to stop at the first
+# non-alloc, causing us to not create PT_LOAD for linker generated sections.
# CHECK: Program Headers:
# CHECK-NEXT: Type
@@ -19,7 +18,7 @@
# CHECK: Section to Segment mapping:
# CHECK-NEXT: Segment Sections...
# CHECK-NEXT: 00
-# CHECK-NEXT: 01 .foo .dynsym .hash .dynstr
+# CHECK-NEXT: 01 .dynsym .hash .dynstr
# CHECK-NEXT: 02 .text
# CHECK-NEXT: 03 .dynamic
Modified: lld/trunk/test/ELF/linkerscript/sections.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/sections.s?rev=281778&r1=281777&r2=281778&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/sections.s (original)
+++ lld/trunk/test/ELF/linkerscript/sections.s Fri Sep 16 16:29:07 2016
@@ -25,7 +25,8 @@
# SEC-DEFAULT: 7 .shstrtab 00000032 {{[0-9a-f]*}}
# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
-# Sections are put in order specified in linker script.
+# Sections are put in order specified in linker script, other than alloc
+# sections going first.
# RUN: echo "SECTIONS { \
# RUN: .bss : { *(.bss) } \
# RUN: other : { *(other) } \
@@ -41,12 +42,12 @@
# Idx Name Size
# SEC-ORDER: 1 .bss 00000002 {{[0-9a-f]*}} BSS
# SEC-ORDER: 2 other 00000003 {{[0-9a-f]*}} DATA
-# SEC-ORDER: 3 .shstrtab 00000002 {{[0-9a-f]*}}
-# SEC-ORDER: 4 .shstrtab 00000032 {{[0-9a-f]*}}
-# SEC-ORDER: 5 .symtab 00000030 {{[0-9a-f]*}}
-# SEC-ORDER: 6 .strtab 00000008 {{[0-9a-f]*}}
-# SEC-ORDER: 7 .data 00000020 {{[0-9a-f]*}} DATA
-# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-ORDER: 3 .data 00000020 {{[0-9a-f]*}} DATA
+# SEC-ORDER: 4 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-ORDER: 5 .shstrtab 00000002 {{[0-9a-f]*}}
+# SEC-ORDER: 6 .shstrtab 00000032 {{[0-9a-f]*}}
+# SEC-ORDER: 7 .symtab 00000030 {{[0-9a-f]*}}
+# SEC-ORDER: 8 .strtab 00000008 {{[0-9a-f]*}}
# .text and .data have swapped names but proper sizes and types.
# RUN: echo "SECTIONS { \
More information about the llvm-commits
mailing list