aboutsummaryrefslogtreecommitdiff
path: root/ELF/Writer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:50 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-24 01:00:50 +0000
commit0d9ba4fe26725cacc7253fc3c72c4574f26bc099 (patch)
tree90c426d54188ca226b29aaf8a308bba364a73d1a /ELF/Writer.cpp
parenteb1ff93d02b5f17b6b409e83c6d9be585f4a04b3 (diff)
downloadsrc-0d9ba4fe26725cacc7253fc3c72c4574f26bc099.tar.gz
src-0d9ba4fe26725cacc7253fc3c72c4574f26bc099.zip
Vendor import of lld trunk r321414:vendor/lld/lld-trunk-r321414
Notes
Notes: svn path=/vendor/lld/dist/; revision=327130 svn path=/vendor/lld/lld-trunk-r321414/; revision=327131; tag=vendor/lld/lld-trunk-r321414
Diffstat (limited to 'ELF/Writer.cpp')
-rw-r--r--ELF/Writer.cpp118
1 files changed, 59 insertions, 59 deletions
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index c7a3cae49ae6..15f382104756 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -54,7 +54,6 @@ private:
void resolveShfLinkOrder();
void sortInputSections();
void finalizeSections();
- void addPredefinedSections();
void setReservedSymbolSections();
std::vector<PhdrEntry *> createPhdrs();
@@ -157,35 +156,34 @@ template <class ELFT> static void combineEhFrameSections() {
V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
}
-template <class ELFT>
static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec,
uint64_t Val, uint8_t StOther = STV_HIDDEN,
uint8_t Binding = STB_GLOBAL) {
Symbol *S = Symtab->find(Name);
if (!S || S->isDefined())
return nullptr;
- Symbol *Sym = Symtab->addRegular<ELFT>(Name, StOther, STT_NOTYPE, Val,
- /*Size=*/0, Binding, Sec,
- /*File=*/nullptr);
+ Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val,
+ /*Size=*/0, Binding, Sec,
+ /*File=*/nullptr);
return cast<Defined>(Sym);
}
// The linker is expected to define some symbols depending on
// the linking result. This function defines such symbols.
-template <class ELFT> void elf::addReservedSymbols() {
+void elf::addReservedSymbols() {
if (Config->EMachine == EM_MIPS) {
// Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
// so that it points to an absolute address which by default is relative
// to GOT. Default offset is 0x7ff0.
// See "Global Data Symbols" in Chapter 6 in the following document:
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- ElfSym::MipsGp = Symtab->addAbsolute<ELFT>("_gp", STV_HIDDEN, STB_GLOBAL);
+ ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL);
// On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
// start of function and 'gp' pointer into GOT.
if (Symtab->find("_gp_disp"))
ElfSym::MipsGpDisp =
- Symtab->addAbsolute<ELFT>("_gp_disp", STV_HIDDEN, STB_GLOBAL);
+ Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL);
// The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
// pointer. This symbol is used in the code generated by .cpload pseudo-op
@@ -193,10 +191,10 @@ template <class ELFT> void elf::addReservedSymbols() {
// https://sourceware.org/ml/binutils/2004-12/msg00094.html
if (Symtab->find("__gnu_local_gp"))
ElfSym::MipsLocalGp =
- Symtab->addAbsolute<ELFT>("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
+ Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL);
}
- ElfSym::GlobalOffsetTable = addOptionalRegular<ELFT>(
+ ElfSym::GlobalOffsetTable = addOptionalRegular(
"_GLOBAL_OFFSET_TABLE_", Out::ElfHeader, Target->GotBaseSymOff);
// __ehdr_start is the location of ELF file headers. Note that we define
@@ -210,14 +208,14 @@ template <class ELFT> void elf::addReservedSymbols() {
// different in different DSOs, so we chose the start address of the DSO.
for (const char *Name :
{"__ehdr_start", "__executable_start", "__dso_handle"})
- addOptionalRegular<ELFT>(Name, Out::ElfHeader, 0, STV_HIDDEN);
+ addOptionalRegular(Name, Out::ElfHeader, 0, STV_HIDDEN);
// If linker script do layout we do not need to create any standart symbols.
if (Script->HasSectionsCommand)
return;
auto Add = [](StringRef S, int64_t Pos) {
- return addOptionalRegular<ELFT>(S, Out::ElfHeader, Pos, STV_DEFAULT);
+ return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT);
};
ElfSym::Bss = Add("__bss_start", 0);
@@ -390,6 +388,11 @@ template <class ELFT> static void createSyntheticSections() {
Add(InX::ShStrTab);
if (InX::StrTab)
Add(InX::StrTab);
+
+ if (Config->EMachine == EM_ARM && !Config->Relocatable)
+ // Add a sentinel to terminate .ARM.exidx. It helps an unwinder
+ // to find the exact address range of the last entry.
+ Add(make<ARMExidxSentinelSection>());
}
// The main function of the writer.
@@ -830,10 +833,10 @@ template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (!Config->Static)
return;
StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalRegular<ELFT>(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
+ addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);
S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- addOptionalRegular<ELFT>(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
+ addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
}
template <class ELFT>
@@ -1145,10 +1148,10 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
}
static bool compareByFilePosition(InputSection *A, InputSection *B) {
- // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+ // Synthetic, i. e. a sentinel section, should go last.
if (A->kind() == InputSectionBase::Synthetic ||
B->kind() == InputSectionBase::Synthetic)
- return false;
+ return A->kind() != InputSectionBase::Synthetic;
InputSection *LA = A->getLinkOrderDep();
InputSection *LB = B->getLinkOrderDep();
OutputSection *AOut = LA->getParent();
@@ -1231,23 +1234,37 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
}
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
- if (Config->MergeArmExidx && !Config->Relocatable &&
- Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) {
- // The EHABI for the Arm Architecture permits consecutive identical
- // table entries to be merged. We use a simple implementation that
- // removes a .ARM.exidx Input Section if it can be merged into the
- // previous one. This does not require any rewriting of InputSection
- // contents but misses opportunities for fine grained deduplication where
- // only a subset of the InputSection contents can be merged.
- int Cur = 1;
- int Prev = 0;
- int N = Sections.size();
- while (Cur < N) {
- if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
- Sections[Cur] = nullptr;
- else
- Prev = Cur;
- ++Cur;
+ if (!Config->Relocatable && Config->EMachine == EM_ARM &&
+ Sec->Type == SHT_ARM_EXIDX) {
+
+ if (!Sections.empty() && isa<ARMExidxSentinelSection>(Sections.back())) {
+ assert(Sections.size() >= 2 &&
+ "We should create a sentinel section only if there are "
+ "alive regular exidx sections.");
+ // The last executable section is required to fill the sentinel.
+ // Remember it here so that we don't have to find it again.
+ auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back());
+ Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
+ }
+
+ if (Config->MergeArmExidx) {
+ // The EHABI for the Arm Architecture permits consecutive identical
+ // table entries to be merged. We use a simple implementation that
+ // removes a .ARM.exidx Input Section if it can be merged into the
+ // previous one. This does not require any rewriting of InputSection
+ // contents but misses opportunities for fine grained deduplication
+ // where only a subset of the InputSection contents can be merged.
+ int Cur = 1;
+ int Prev = 0;
+ // The last one is a sentinel entry which should not be removed.
+ int N = Sections.size() - 1;
+ while (Cur < N) {
+ if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
+ Sections[Cur] = nullptr;
+ else
+ Prev = Cur;
+ ++Cur;
+ }
}
}
@@ -1367,9 +1384,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// Even the author of gold doesn't remember why gold behaves that way.
// https://sourceware.org/ml/binutils/2002-03/msg00360.html
if (InX::DynSymTab)
- Symtab->addRegular<ELFT>("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
- /*Size=*/0, STB_WEAK, InX::Dynamic,
- /*File=*/nullptr);
+ Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,
+ /*Size=*/0, STB_WEAK, InX::Dynamic,
+ /*File=*/nullptr);
// Define __rel[a]_iplt_{start,end} symbols if needed.
addRelIpltSymbols();
@@ -1413,7 +1430,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (errorCount())
return;
- addPredefinedSections();
removeUnusedSyntheticSections();
sortSections();
@@ -1510,17 +1526,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
[](SyntheticSection *SS) { SS->postThunkContents(); });
}
-template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
- // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
- // We have the terminater synthetic section class. Add that at the end.
- OutputSection *Cmd = findSection(".ARM.exidx");
- if (!Cmd || !Cmd->Live || Config->Relocatable)
- return;
-
- auto *Sentinel = make<ARMExidxSentinelSection>();
- Cmd->addSection(Sentinel);
-}
-
// The linker is expected to define SECNAME_start and SECNAME_end
// symbols for a few sections. This function defines them.
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
@@ -1528,13 +1533,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
// These symbols resolve to the image base if the section does not exist.
// A special value -1 indicates end of the section.
if (OS) {
- addOptionalRegular<ELFT>(Start, OS, 0);
- addOptionalRegular<ELFT>(End, OS, -1);
+ addOptionalRegular(Start, OS, 0);
+ addOptionalRegular(End, OS, -1);
} else {
if (Config->Pic)
OS = Out::ElfHeader;
- addOptionalRegular<ELFT>(Start, OS, 0);
- addOptionalRegular<ELFT>(End, OS, 0);
+ addOptionalRegular(Start, OS, 0);
+ addOptionalRegular(End, OS, 0);
}
};
@@ -1556,8 +1561,8 @@ void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {
StringRef S = Sec->Name;
if (!isValidCIdentifier(S))
return;
- addOptionalRegular<ELFT>(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
- addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
+ addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_DEFAULT);
+ addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
}
static bool needsPtLoad(OutputSection *Sec) {
@@ -2057,8 +2062,3 @@ template void elf::writeResult<ELF32LE>();
template void elf::writeResult<ELF32BE>();
template void elf::writeResult<ELF64LE>();
template void elf::writeResult<ELF64BE>();
-
-template void elf::addReservedSymbols<ELF32LE>();
-template void elf::addReservedSymbols<ELF32BE>();
-template void elf::addReservedSymbols<ELF64LE>();
-template void elf::addReservedSymbols<ELF64BE>();