aboutsummaryrefslogtreecommitdiffstats
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-07-19 07:02:58 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-07-19 07:02:58 +0000
commitda06c7cfa0388de29a4024d8d386e48f2fb13ed6 (patch)
treedc28e84fc2bb9a4a4d9873fe4d04946fe3f7f4c0 /ELF
parent267829774358b5aebd3e726ae318813bd48129bb (diff)
downloadsrc-da06c7cfa0388de29a4024d8d386e48f2fb13ed6.tar.gz
src-da06c7cfa0388de29a4024d8d386e48f2fb13ed6.zip
Vendor import of lld trunk r308421:vendor/lld/lld-trunk-r308421
Notes
Notes: svn path=/vendor/lld/dist/; revision=321192 svn path=/vendor/lld/lld-trunk-r308421/; revision=321193; tag=vendor/lld/lld-trunk-r308421
Diffstat (limited to 'ELF')
-rw-r--r--ELF/Arch/ARM.cpp45
-rw-r--r--ELF/Arch/MipsArchTree.cpp6
-rw-r--r--ELF/Config.h1
-rw-r--r--ELF/Driver.cpp4
-rw-r--r--ELF/EhFrame.h4
-rw-r--r--ELF/Filesystem.h4
-rw-r--r--ELF/GdbIndex.h2
-rw-r--r--ELF/ICF.h2
-rw-r--r--ELF/InputFiles.h4
-rw-r--r--ELF/LTO.h6
-rw-r--r--ELF/LinkerScript.cpp19
-rw-r--r--ELF/MapFile.cpp2
-rw-r--r--ELF/MapFile.h4
-rw-r--r--ELF/Memory.h4
-rw-r--r--ELF/Options.td7
-rw-r--r--ELF/OutputSections.cpp8
-rw-r--r--ELF/OutputSections.h7
-rw-r--r--ELF/Relocations.cpp81
-rw-r--r--ELF/Relocations.h11
-rw-r--r--ELF/ScriptParser.cpp10
-rw-r--r--ELF/Strings.cpp23
-rw-r--r--ELF/Strings.h7
-rw-r--r--ELF/SymbolTable.cpp43
-rw-r--r--ELF/Symbols.cpp2
-rw-r--r--ELF/SyntheticSections.cpp29
-rw-r--r--ELF/Target.cpp5
-rw-r--r--ELF/Target.h5
-rw-r--r--ELF/Threads.h4
-rw-r--r--ELF/Thunks.cpp18
-rw-r--r--ELF/Thunks.h2
-rw-r--r--ELF/Writer.cpp6
-rw-r--r--ELF/Writer.h4
32 files changed, 223 insertions, 156 deletions
diff --git a/ELF/Arch/ARM.cpp b/ELF/Arch/ARM.cpp
index e4b06ade4487..106021de7d32 100644
--- a/ELF/Arch/ARM.cpp
+++ b/ELF/Arch/ARM.cpp
@@ -40,6 +40,8 @@ public:
void addPltHeaderSymbols(InputSectionBase *ISD) const override;
bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
const SymbolBody &S) const override;
+ bool inBranchRange(uint32_t RelocType, uint64_t Src,
+ uint64_t Dst) const override;
void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
};
} // namespace
@@ -218,6 +220,49 @@ bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
return false;
}
+bool ARM::inBranchRange(uint32_t RelocType, uint64_t Src, uint64_t Dst) const {
+ uint64_t Range;
+ uint64_t InstrSize;
+
+ switch (RelocType) {
+ case R_ARM_PC24:
+ case R_ARM_PLT32:
+ case R_ARM_JUMP24:
+ case R_ARM_CALL:
+ Range = 0x2000000;
+ InstrSize = 4;
+ break;
+ case R_ARM_THM_JUMP19:
+ Range = 0x100000;
+ InstrSize = 2;
+ break;
+ case R_ARM_THM_JUMP24:
+ case R_ARM_THM_CALL:
+ Range = 0x1000000;
+ InstrSize = 2;
+ break;
+ default:
+ return true;
+ }
+ // PC at Src is 2 instructions ahead, immediate of branch is signed
+ if (Src > Dst)
+ Range -= 2 * InstrSize;
+ else
+ Range += InstrSize;
+
+ if ((Dst & 0x1) == 0)
+ // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
+ // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
+ // destination will be 4 byte aligned.
+ Src &= ~0x3;
+ else
+ // Bit 0 == 1 denotes Thumb state, it is not part of the range
+ Dst &= ~0x1;
+
+ uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;
+ return Distance <= Range;
+}
+
void ARM::relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const {
switch (Type) {
case R_ARM_ABS32:
diff --git a/ELF/Arch/MipsArchTree.cpp b/ELF/Arch/MipsArchTree.cpp
index ed183e9a3061..3d1dc1daf0c1 100644
--- a/ELF/Arch/MipsArchTree.cpp
+++ b/ELF/Arch/MipsArchTree.cpp
@@ -37,7 +37,7 @@ struct FileFlags {
StringRef Filename;
uint32_t Flags;
};
-}
+} // namespace
static StringRef getAbiName(uint32_t Flags) {
switch (Flags) {
@@ -337,8 +337,8 @@ uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
return NewFlag;
if (compareMipsFpAbi(OldFlag, NewFlag) < 0)
error("target floating point ABI '" + getMipsFpAbiName(OldFlag) +
- "' is incompatible with '" + getMipsFpAbiName(NewFlag) + "': " +
- FileName);
+ "' is incompatible with '" + getMipsFpAbiName(NewFlag) +
+ "': " + FileName);
return OldFlag;
}
diff --git a/ELF/Config.h b/ELF/Config.h
index 5e3b77637316..23627dd812db 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -99,6 +99,7 @@ struct Configuration {
std::vector<VersionDefinition> VersionDefinitions;
std::vector<llvm::StringRef> Argv;
std::vector<llvm::StringRef> AuxiliaryList;
+ std::vector<llvm::StringRef> FilterList;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> SymbolOrderingFile;
std::vector<llvm::StringRef> Undefined;
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index 10ad13f214d5..4630e110bcd8 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -259,6 +259,9 @@ static void checkOptions(opt::InputArgList &Args) {
if (Config->Pie && Config->Shared)
error("-shared and -pie may not be used together");
+ if (!Config->Shared && !Config->FilterList.empty())
+ error("-F may not be used without -shared");
+
if (!Config->Shared && !Config->AuxiliaryList.empty())
error("-f may not be used without -shared");
@@ -631,6 +634,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false);
Config->FatalWarnings =
getArg(Args, OPT_fatal_warnings, OPT_no_fatal_warnings, false);
+ Config->FilterList = getArgs(Args, OPT_filter);
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
Config->GcSections = getArg(Args, OPT_gc_sections, OPT_no_gc_sections, false);
Config->GdbIndex = Args.hasArg(OPT_gdb_index);
diff --git a/ELF/EhFrame.h b/ELF/EhFrame.h
index 4e2b6f83a294..07d1aaa3cbb3 100644
--- a/ELF/EhFrame.h
+++ b/ELF/EhFrame.h
@@ -19,7 +19,7 @@ struct EhSectionPiece;
template <class ELFT> size_t readEhRecordSize(InputSectionBase *S, size_t Off);
template <class ELFT> uint8_t getFdeEncoding(EhSectionPiece *P);
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/Filesystem.h b/ELF/Filesystem.h
index d56d067f7378..dbeadac5a96b 100644
--- a/ELF/Filesystem.h
+++ b/ELF/Filesystem.h
@@ -16,7 +16,7 @@ namespace lld {
namespace elf {
void unlinkAsync(StringRef Path);
std::error_code tryCreateFile(StringRef Path);
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/GdbIndex.h b/ELF/GdbIndex.h
index c49f8946e199..bc024e6689ef 100644
--- a/ELF/GdbIndex.h
+++ b/ELF/GdbIndex.h
@@ -11,8 +11,8 @@
#define LLD_ELF_GDB_INDEX_H
#include "InputFiles.h"
-#include "llvm/Object/ELF.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/ELF.h"
namespace lld {
namespace elf {
diff --git a/ELF/ICF.h b/ELF/ICF.h
index 502e128c8109..24219855fc17 100644
--- a/ELF/ICF.h
+++ b/ELF/ICF.h
@@ -14,6 +14,6 @@ namespace lld {
namespace elf {
template <class ELFT> void doIcf();
}
-}
+} // namespace lld
#endif
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
index 544a0b009b39..f6d3f907850c 100644
--- a/ELF/InputFiles.h
+++ b/ELF/InputFiles.h
@@ -11,8 +11,8 @@
#define LLD_ELF_INPUT_FILES_H
#include "Config.h"
-#include "InputSection.h"
#include "Error.h"
+#include "InputSection.h"
#include "Symbols.h"
#include "lld/Core/LLVM.h"
@@ -34,7 +34,7 @@ struct DILineInfo;
namespace lto {
class InputFile;
}
-}
+} // namespace llvm
namespace lld {
namespace elf {
diff --git a/ELF/LTO.h b/ELF/LTO.h
index 28afa0e83add..d19923c90a99 100644
--- a/ELF/LTO.h
+++ b/ELF/LTO.h
@@ -30,7 +30,7 @@ namespace llvm {
namespace lto {
class LTO;
}
-}
+} // namespace llvm
namespace lld {
namespace elf {
@@ -51,7 +51,7 @@ private:
std::vector<SmallString<0>> Buff;
std::vector<std::unique_ptr<MemoryBuffer>> Files;
};
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
index a182d5a3a096..8bdbd8db20ad 100644
--- a/ELF/LinkerScript.cpp
+++ b/ELF/LinkerScript.cpp
@@ -229,6 +229,19 @@ bool LinkerScript::shouldKeep(InputSectionBase *S) {
return false;
}
+// If an input string is in the form of "foo.N" where N is a number,
+// return N. Otherwise, returns 65536, which is one greater than the
+// lowest priority.
+static int getPriority(StringRef S) {
+ size_t Pos = S.rfind('.');
+ if (Pos == StringRef::npos)
+ return 65536;
+ int V;
+ if (!to_integer(S.substr(Pos + 1), V, 10))
+ return 65536;
+ return V;
+}
+
// A helper function for the SORT() command.
static std::function<bool(InputSectionBase *, InputSectionBase *)>
getComparator(SortSectionPolicy K) {
@@ -449,7 +462,7 @@ void LinkerScript::fabricateDefaultCommands() {
// The Sections with -T<section> have been sorted in order of ascending
// address. We must lower StartAddr if the lowest -T<section address> as
// calls to setDot() must be monotonically increasing.
- for (auto& KV : Config->SectionStartMap)
+ for (auto &KV : Config->SectionStartMap)
StartAddr = std::min(StartAddr, KV.second);
Commands.push_back(make<SymbolAssignment>(
@@ -739,7 +752,7 @@ void LinkerScript::adjustSectionsAfterSorting() {
Cmd->MemRegion = findMemoryRegion(Cmd);
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
if (Cmd->AlignExpr)
- Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
+ Cmd->Sec->updateAlignment(Cmd->AlignExpr().getValue());
}
}
@@ -1071,7 +1084,7 @@ template <class ELFT> void OutputSectionCommand::finalize() {
}
if ((Sec->Flags & SHF_LINK_ORDER)) {
- std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
+ std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
for (int I = 0, N = Sections.size(); I < N; ++I)
*ScriptSections[I] = Sections[I];
diff --git a/ELF/MapFile.cpp b/ELF/MapFile.cpp
index e0c7d8cd8b1b..2b2a95c47cf9 100644
--- a/ELF/MapFile.cpp
+++ b/ELF/MapFile.cpp
@@ -55,7 +55,7 @@ template <class ELFT> std::vector<DefinedRegular *> getSymbols() {
for (SymbolBody *B : File->getSymbols())
if (B->File == File && !B->isSection())
if (auto *Sym = dyn_cast<DefinedRegular>(B))
- if (Sym->Section)
+ if (Sym->Section && Sym->Section->Live)
V.push_back(Sym);
return V;
}
diff --git a/ELF/MapFile.h b/ELF/MapFile.h
index 68d8ba8d4a04..460848ff24d3 100644
--- a/ELF/MapFile.h
+++ b/ELF/MapFile.h
@@ -17,7 +17,7 @@ namespace elf {
struct OutputSectionCommand;
template <class ELFT>
void writeMapFile(llvm::ArrayRef<OutputSectionCommand *> Script);
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/Memory.h b/ELF/Memory.h
index e5a04ed1e5a8..4000f2f9f1c9 100644
--- a/ELF/Memory.h
+++ b/ELF/Memory.h
@@ -61,7 +61,7 @@ inline void freeArena() {
Alloc->reset();
BAlloc.Reset();
}
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/Options.td b/ELF/Options.td
index 29e14c530c6a..9c78608118cc 100644
--- a/ELF/Options.td
+++ b/ELF/Options.td
@@ -104,6 +104,8 @@ def export_dynamic_symbol: S<"export-dynamic-symbol">,
def fatal_warnings: F<"fatal-warnings">,
HelpText<"Treat warnings as errors">;
+def filter: J<"filter=">, HelpText<"Set DT_FILTER field to the specified name">;
+
def fini: S<"fini">, MetaVarName<"<symbol>">,
HelpText<"Specify a finalizer function">;
@@ -305,6 +307,7 @@ def alias_exclude_libs: J<"exclude-libs=">, Alias<exclude_libs>;
def alias_export_dynamic_E: Flag<["-"], "E">, Alias<export_dynamic>;
def alias_export_dynamic_symbol: J<"export-dynamic-symbol=">,
Alias<export_dynamic_symbol>;
+def alias_filter: Separate<["-"], "F">, Alias<filter>;
def alias_fini_fini: J<"fini=">, Alias<fini>;
def alias_format_b: S<"b">, Alias<format>;
def alias_hash_style_hash_style: J<"hash-style=">, Alias<hash_style>;
@@ -339,6 +342,7 @@ def alias_Ttext_segment: S<"Ttext-segment">, Alias<Ttext>;
def alias_Ttext_segment_eq: J<"Ttext-segment=">, Alias<Ttext>;
def alias_undefined_eq: J<"undefined=">, Alias<undefined>;
def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
+def alias_version_script_eq: J<"version-script=">, Alias<version_script>;
def alias_version_V: Flag<["-"], "V">, Alias<version>;
def alias_wrap_wrap: J<"wrap=">, Alias<wrap>;
@@ -406,6 +410,3 @@ def EL : F<"EL">;
def G: JoinedOrSeparate<["-"], "G">;
def Qy : F<"Qy">;
-// Aliases for ignored options
-def alias_version_script_version_script: J<"version-script=">,
- Alias<version_script>;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index d6ae5dcae167..abe548165866 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -222,16 +222,16 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS,
if (Sec) {
if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags))
- error("incompatible section flags for " + Sec->Name +
- "\n>>> " + toString(IS) + ": 0x" + utohexstr(IS->Flags) +
+ error("incompatible section flags for " + Sec->Name + "\n>>> " +
+ toString(IS) + ": 0x" + utohexstr(IS->Flags) +
"\n>>> output section " + Sec->Name + ": 0x" +
utohexstr(Sec->Flags));
if (Sec->Type != IS->Type) {
if (canMergeToProgbits(Sec->Type) && canMergeToProgbits(IS->Type))
Sec->Type = SHT_PROGBITS;
else
- error("section type mismatch for " + IS->Name +
- "\n>>> " + toString(IS) + ": " +
+ error("section type mismatch for " + IS->Name + "\n>>> " +
+ toString(IS) + ": " +
getELFSectionTypeName(Config->EMachine, IS->Type) +
"\n>>> output section " + Sec->Name + ": " +
getELFSectionTypeName(Config->EMachine, Sec->Type));
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
index 68ee066a13da..68b46ebf6a7b 100644
--- a/ELF/OutputSections.h
+++ b/ELF/OutputSections.h
@@ -111,8 +111,8 @@ struct SectionKey {
uint64_t Flags;
uint32_t Alignment;
};
-}
-}
+} // namespace elf
+} // namespace lld
namespace llvm {
template <> struct DenseMapInfo<lld::elf::SectionKey> {
static lld::elf::SectionKey getEmptyKey();
@@ -121,7 +121,7 @@ template <> struct DenseMapInfo<lld::elf::SectionKey> {
static bool isEqual(const lld::elf::SectionKey &LHS,
const lld::elf::SectionKey &RHS);
};
-}
+} // namespace llvm
namespace lld {
namespace elf {
@@ -150,5 +150,4 @@ extern std::vector<OutputSectionCommand *> OutputSectionCommands;
} // namespace elf
} // namespace lld
-
#endif
diff --git a/ELF/Relocations.cpp b/ELF/Relocations.cpp
index 52dbe4b583d0..e5fcb2dcc582 100644
--- a/ELF/Relocations.cpp
+++ b/ELF/Relocations.cpp
@@ -276,7 +276,7 @@ handleTlsRelocation(uint32_t Type, SymbolBody &Body, InputSectionBase &C,
} else {
C.Relocations.push_back(
{Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type,
- Offset, Addend, &Body});
+ Offset, Addend, &Body});
}
return Target->TlsGdRelaxSkip;
}
@@ -1000,16 +1000,20 @@ void ThunkCreator::mergeThunks() {
}
}
-ThunkSection *ThunkCreator::getOSThunkSec(OutputSection *OS,
+static uint32_t findEndOfFirstNonExec(OutputSectionCommand &Cmd) {
+ for (BaseCommand *Base : Cmd.Commands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
+ for (auto *IS : ISD->Sections)
+ if ((IS->Flags & SHF_EXECINSTR) == 0)
+ return IS->OutSecOff + IS->getSize();
+ return 0;
+}
+
+ThunkSection *ThunkCreator::getOSThunkSec(OutputSectionCommand *Cmd,
std::vector<InputSection *> *ISR) {
if (CurTS == nullptr) {
- uint32_t Off = 0;
- for (auto *IS : OS->Sections) {
- Off = IS->OutSecOff + IS->getSize();
- if ((IS->Flags & SHF_EXECINSTR) == 0)
- break;
- }
- CurTS = addThunkSection(OS, ISR, Off);
+ uint32_t Off = findEndOfFirstNonExec(*Cmd);
+ CurTS = addThunkSection(Cmd->Sec, ISR, Off);
}
return CurTS;
}
@@ -1024,7 +1028,7 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS, OutputSection *OS) {
OutputSectionCommand *C = Script->getCmd(TOS);
std::vector<InputSection *> *Range = nullptr;
for (BaseCommand *BC : C->Commands)
- if (auto *ISD = dyn_cast<InputSectionDescription> (BC)) {
+ if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
InputSection *first = ISD->Sections.front();
InputSection *last = ISD->Sections.back();
if (IS->OutSecOff >= first->OutSecOff &&
@@ -1046,7 +1050,6 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
return TS;
}
-
std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
uint32_t Type) {
auto Res = ThunkedSymbols.insert({&Body, std::vector<Thunk *>()});
@@ -1066,7 +1069,7 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
// InputSectionDescription::Sections.
void ThunkCreator::forEachExecInputSection(
ArrayRef<OutputSectionCommand *> OutputSections,
- std::function<void(OutputSection *, std::vector<InputSection *> *,
+ std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
InputSection *)>
Fn) {
for (OutputSectionCommand *Cmd : OutputSections) {
@@ -1077,7 +1080,7 @@ void ThunkCreator::forEachExecInputSection(
if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {
CurTS = nullptr;
for (InputSection *IS : ISD->Sections)
- Fn(OS, &ISD->Sections, IS);
+ Fn(Cmd, &ISD->Sections, IS);
}
}
}
@@ -1103,32 +1106,32 @@ bool ThunkCreator::createThunks(
// We separate the creation of ThunkSections from the insertion of the
// ThunkSections back into the OutputSection as ThunkSections are not always
// inserted into the same OutputSection as the caller.
- forEachExecInputSection(
- OutputSections, [&](OutputSection *OS, std::vector<InputSection*> *ISR,
- InputSection *IS) {
- for (Relocation &Rel : IS->Relocations) {
- SymbolBody &Body = *Rel.Sym;
- if (Thunks.find(&Body) != Thunks.end() ||
- !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
- continue;
- Thunk *T;
- bool IsNew;
- std::tie(T, IsNew) = getThunk(Body, Rel.Type);
- if (IsNew) {
- // Find or create a ThunkSection for the new Thunk
- ThunkSection *TS;
- if (auto *TIS = T->getTargetInputSection())
- TS = getISThunkSec(TIS, OS);
- else
- TS = getOSThunkSec(OS, ISR);
- TS->addThunk(T);
- Thunks[T->ThunkSym] = T;
- }
- // Redirect relocation to Thunk, we never go via the PLT to a Thunk
- Rel.Sym = T->ThunkSym;
- Rel.Expr = fromPlt(Rel.Expr);
- }
- });
+ forEachExecInputSection(OutputSections, [&](OutputSectionCommand *Cmd,
+ std::vector<InputSection *> *ISR,
+ InputSection *IS) {
+ for (Relocation &Rel : IS->Relocations) {
+ SymbolBody &Body = *Rel.Sym;
+ if (Thunks.find(&Body) != Thunks.end() ||
+ !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+ continue;
+ Thunk *T;
+ bool IsNew;
+ std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+ if (IsNew) {
+ // Find or create a ThunkSection for the new Thunk
+ ThunkSection *TS;
+ if (auto *TIS = T->getTargetInputSection())
+ TS = getISThunkSec(TIS, Cmd->Sec);
+ else
+ TS = getOSThunkSec(Cmd, ISR);
+ TS->addThunk(T);
+ Thunks[T->ThunkSym] = T;
+ }
+ // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+ Rel.Sym = T->ThunkSym;
+ Rel.Expr = fromPlt(Rel.Expr);
+ }
+ });
// Merge all created synthetic ThunkSections back into OutputSection
mergeThunks();
++Pass;
diff --git a/ELF/Relocations.h b/ELF/Relocations.h
index fc3e3444ac24..ea046d248474 100644
--- a/ELF/Relocations.h
+++ b/ELF/Relocations.h
@@ -103,7 +103,8 @@ struct RelExprMaskBuilder<Head, Tail...> {
// RelExpr's as a constant bit mask and test for membership with a
// couple cheap bitwise operations.
template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) {
- assert(0 <= Expr && (int)Expr < 64 && "RelExpr is too large for 64-bit mask!");
+ assert(0 <= Expr && (int)Expr < 64 &&
+ "RelExpr is too large for 64-bit mask!");
return (uint64_t(1) << Expr) & RelExprMaskBuilder<Exprs...>::build();
}
@@ -133,12 +134,12 @@ public:
private:
void mergeThunks();
- ThunkSection *getOSThunkSec(OutputSection *OS,
+ ThunkSection *getOSThunkSec(OutputSectionCommand *Cmd,
std::vector<InputSection *> *ISR);
ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
void forEachExecInputSection(
ArrayRef<OutputSectionCommand *> OutputSections,
- std::function<void(OutputSection *, std::vector<InputSection *> *,
+ std::function<void(OutputSectionCommand *, std::vector<InputSection *> *,
InputSection *)>
Fn);
std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
@@ -178,7 +179,7 @@ template <class ELFT>
static inline int64_t getAddend(const typename ELFT::Rela &Rel) {
return Rel.r_addend;
}
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/ScriptParser.cpp b/ELF/ScriptParser.cpp
index 72940ca0cfd4..b3847081697c 100644
--- a/ELF/ScriptParser.cpp
+++ b/ELF/ScriptParser.cpp
@@ -113,6 +113,12 @@ private:
};
} // namespace
+static StringRef unquote(StringRef S) {
+ if (S.startswith("\""))
+ return S.substr(1, S.size() - 2);
+ return S;
+}
+
static bool isUnderSysroot(StringRef Path) {
if (Config->Sysroot == "")
return false;
@@ -1103,6 +1109,10 @@ void ScriptParser::readVersionDeclaration(StringRef VerStr) {
expect(";");
}
+static bool hasWildcard(StringRef S) {
+ return S.find_first_of("?*[") != StringRef::npos;
+}
+
// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
ScriptParser::readSymbols() {
diff --git a/ELF/Strings.cpp b/ELF/Strings.cpp
index 2e88bfba0fc1..bca86384002d 100644
--- a/ELF/Strings.cpp
+++ b/ELF/Strings.cpp
@@ -38,29 +38,6 @@ bool StringMatcher::match(StringRef S) const {
return false;
}
-// If an input string is in the form of "foo.N" where N is a number,
-// return N. Otherwise, returns 65536, which is one greater than the
-// lowest priority.
-int elf::getPriority(StringRef S) {
- size_t Pos = S.rfind('.');
- if (Pos == StringRef::npos)
- return 65536;
- int V;
- if (!to_integer(S.substr(Pos + 1), V, 10))
- return 65536;
- return V;
-}
-
-bool elf::hasWildcard(StringRef S) {
- return S.find_first_of("?*[") != StringRef::npos;
-}
-
-StringRef elf::unquote(StringRef S) {
- if (!S.startswith("\""))
- return S;
- return S.substr(1, S.size() - 2);
-}
-
// Converts a hex string (e.g. "deadbeef") to a vector.
std::vector<uint8_t> elf::parseHex(StringRef S) {
std::vector<uint8_t> Hex;
diff --git a/ELF/Strings.h b/ELF/Strings.h
index fd1aa40539d2..68ccafa2ff17 100644
--- a/ELF/Strings.h
+++ b/ELF/Strings.h
@@ -21,11 +21,8 @@
namespace lld {
namespace elf {
-int getPriority(StringRef S);
-bool hasWildcard(StringRef S);
std::vector<uint8_t> parseHex(StringRef S);
bool isValidCIdentifier(StringRef S);
-StringRef unquote(StringRef S);
// This is a lazy version of StringRef. String size is computed lazily
// when it is needed. It is more efficient than StringRef to instantiate
@@ -76,7 +73,7 @@ llvm::Optional<std::string> demangle(StringRef Name);
inline ArrayRef<uint8_t> toArrayRef(StringRef S) {
return {(const uint8_t *)S.data(), S.size()};
}
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index c802d74b8ff8..83091057ebed 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -172,8 +172,8 @@ template <class ELFT> void SymbolTable<ELFT>::addSymbolWrap(StringRef Name) {
}
// Creates alias for symbol. Used to implement --defsym=ALIAS=SYM.
-template <class ELFT> void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias,
- StringRef Name) {
+template <class ELFT>
+void SymbolTable<ELFT>::addSymbolAlias(StringRef Alias, StringRef Name) {
SymbolBody *B = find(Name);
if (!B) {
error("-defsym: undefined symbol: " + Name);
@@ -211,13 +211,6 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
// Find an existing symbol or create and insert a new one.
template <class ELFT>
std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
- // <name>@@<version> means the symbol is the default version. In that
- // case symbol <name> must exist and <name>@@<version> will be used to
- // resolve references to <name>.
- size_t Pos = Name.find("@@");
- if (Pos != StringRef::npos)
- Name = Name.take_front(Pos);
-
auto P = Symtab.insert(
{CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)});
SymIndex &V = P.first->second;
@@ -400,9 +393,8 @@ static void warnOrError(const Twine &Msg) {
}
static void reportDuplicate(SymbolBody *Sym, InputFile *NewFile) {
- warnOrError("duplicate symbol: " + toString(*Sym) +
- "\n>>> defined in " + toString(Sym->File) +
- "\n>>> defined in " + toString(NewFile));
+ warnOrError("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
+ toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
}
template <class ELFT>
@@ -680,7 +672,8 @@ template <class ELFT> void SymbolTable<ELFT>::handleAnonymousVersion() {
// Set symbol versions to symbols. This function handles patterns
// containing no wildcard characters.
template <class ELFT>
-void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
+void SymbolTable<ELFT>::assignExactVersion(SymbolVersion Ver,
+ uint16_t VersionId,
StringRef VersionName) {
if (Ver.HasWildcard)
return;
@@ -724,13 +717,35 @@ void SymbolTable<ELFT>::assignWildcardVersion(SymbolVersion Ver,
B->symbol()->VersionId = VersionId;
}
+static bool isDefaultVersion(SymbolBody *B) {
+ return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos;
+}
+
// This function processes version scripts by updating VersionId
// member of symbols.
template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
+ // Symbol themselves might know their versions because symbols
+ // can contain versions in the form of <name>@<version>.
+ // Let them parse and update their names to exclude version suffix.
+ for (Symbol *Sym : SymVector) {
+ SymbolBody *Body = Sym->body();
+ bool IsDefault = isDefaultVersion(Body);
+ Body->parseSymbolVersion();
+
+ if (!IsDefault)
+ continue;
+
+ // <name>@@<version> means the symbol is the default version. If that's the
+ // case, the symbol is not used only to resolve <name> of version <version>
+ // but also undefined unversioned symbols with name <name>.
+ SymbolBody *S = find(Body->getName());
+ if (S && S->isUndefined())
+ S->copy(Body);
+ }
+
// Handle edge cases first.
handleAnonymousVersion();
-
// Now we have version definitions, so we need to set version ids to symbols.
// Each version definition has a glob pattern, and all symbols that match
// with the pattern get that version.
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 1d17f57f0c30..c69007e781a6 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -94,7 +94,7 @@ static uint64_t getSymVA(const SymbolBody &Body, int64_t &Addend) {
if (D.isTls() && !Config->Relocatable) {
if (!Out::TlsPhdr)
fatal(toString(D.File) +
- " has a STT_TLS symbol but doesn't have a PT_TLS section");
+ " has an STT_TLS symbol but doesn't have an SHF_TLS section");
return VA - Out::TlsPhdr->p_vaddr;
}
return VA;
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index fd724fac327c..4bbec4ab34bd 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -662,7 +662,12 @@ bool GotSection::empty() const {
return NumEntries == 0 && !HasGotOffRel;
}
-void GotSection::writeTo(uint8_t *Buf) { relocateAlloc(Buf, Buf + Size); }
+void GotSection::writeTo(uint8_t *Buf) {
+ // Buf points to the start of this section's buffer,
+ // whereas InputSectionBase::relocateAlloc() expects its argument
+ // to point to the start of the output section.
+ relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);
+}
MipsGotSection::MipsGotSection()
: SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,
@@ -812,9 +817,7 @@ unsigned MipsGotSection::getLocalEntriesNum() const {
LocalEntries32.size();
}
-void MipsGotSection::finalizeContents() {
- updateAllocSize();
-}
+void MipsGotSection::finalizeContents() { updateAllocSize(); }
void MipsGotSection::updateAllocSize() {
PageEntriesNum = 0;
@@ -838,9 +841,7 @@ bool MipsGotSection::empty() const {
return Config->Relocatable;
}
-uint64_t MipsGotSection::getGp() const {
- return ElfSym::MipsGp->getVA(0);
-}
+uint64_t MipsGotSection::getGp() const { return ElfSym::MipsGp->getVA(0); }
static uint64_t readUint(uint8_t *Buf) {
if (Config->Is64)
@@ -1019,6 +1020,8 @@ DynamicSection<ELFT>::DynamicSection()
template <class ELFT> void DynamicSection<ELFT>::addEntries() {
// Add strings to .dynstr early so that .dynstr's size will be
// fixed early.
+ for (StringRef S : Config->FilterList)
+ add({DT_FILTER, InX::DynStrTab->addString(S)});
for (StringRef S : Config->AuxiliaryList)
add({DT_AUXILIARY, InX::DynStrTab->addString(S)});
if (!Config->Rpath.empty())
@@ -1607,7 +1610,7 @@ HashTableSection<ELFT>::HashTableSection()
template <class ELFT> void HashTableSection<ELFT>::finalizeContents() {
getParent()->Link = InX::DynSymTab->getParent()->SectionIndex;
- unsigned NumEntries = 2; // nbucket and nchain.
+ unsigned NumEntries = 2; // nbucket and nchain.
NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries.
// Create as many buckets as there are symbols.
@@ -1926,9 +1929,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) {
StringPool.write(Buf);
}
-bool GdbIndexSection::empty() const {
- return !Out::DebugInfo;
-}
+bool GdbIndexSection::empty() const { return !Out::DebugInfo; }
template <class ELFT>
EhFrameHeader<ELFT>::EhFrameHeader()
@@ -2211,9 +2212,7 @@ void MergeSyntheticSection::finalizeContents() {
finalizeNoTailMerge();
}
-size_t MergeSyntheticSection::getSize() const {
- return Builder.getSize();
-}
+size_t MergeSyntheticSection::getSize() const { return Builder.getSize(); }
// This function decompresses compressed sections and scans over the input
// sections to create mergeable synthetic sections. It removes
@@ -2312,7 +2311,7 @@ ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
}
void ThunkSection::addThunk(Thunk *T) {
- uint64_t Off = alignTo(Size, T->alignment);
+ uint64_t Off = alignTo(Size, T->Alignment);
T->Offset = Off;
Thunks.push_back(T);
T->addSymbols(*this);
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
index c886419971bc..11986efc746f 100644
--- a/ELF/Target.cpp
+++ b/ELF/Target.cpp
@@ -128,6 +128,11 @@ bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
return false;
}
+bool TargetInfo::inBranchRange(uint32_t RelocType, uint64_t Src,
+ uint64_t Dst) const {
+ return true;
+}
+
void TargetInfo::writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const {
writeGotPlt(Buf, S);
}
diff --git a/ELF/Target.h b/ELF/Target.h
index 5914d9bbb7ef..1658a81c9b71 100644
--- a/ELF/Target.h
+++ b/ELF/Target.h
@@ -51,6 +51,9 @@ public:
// targeting S.
virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
const InputFile *File, const SymbolBody &S) const;
+ // Return true if we can reach Dst from Src with Relocation RelocType
+ virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
+ uint64_t Dst) const;
virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S,
const uint8_t *Loc) const = 0;
virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const = 0;
@@ -154,6 +157,6 @@ static void checkAlignment(uint8_t *Loc, uint64_t V, uint32_t Type) {
lld::toString(Type));
}
} // namespace elf
-}
+} // namespace lld
#endif
diff --git a/ELF/Threads.h b/ELF/Threads.h
index e01afd4d3fc9..9feb8683976c 100644
--- a/ELF/Threads.h
+++ b/ELF/Threads.h
@@ -82,7 +82,7 @@ inline void parallelForEachN(size_t Begin, size_t End,
else
for_each_n(llvm::parallel::seq, Begin, End, Fn);
}
-}
-}
+} // namespace elf
+} // namespace lld
#endif
diff --git a/ELF/Thunks.cpp b/ELF/Thunks.cpp
index cae31027e557..07289d0efdf1 100644
--- a/ELF/Thunks.cpp
+++ b/ELF/Thunks.cpp
@@ -72,9 +72,7 @@ public:
class ThumbV7ABSLongThunk final : public Thunk {
public:
- ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) {
- alignment = 2;
- }
+ ThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; }
uint32_t size() const override { return 10; }
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
@@ -84,9 +82,7 @@ public:
class ThumbV7PILongThunk final : public Thunk {
public:
- ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) {
- alignment = 2;
- }
+ ThumbV7PILongThunk(const SymbolBody &Dest) : Thunk(Dest) { Alignment = 2; }
uint32_t size() const override { return 12; }
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
@@ -218,10 +214,10 @@ bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
uint64_t S = Destination.getVA();
- write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
+ write32(Buf, 0x3c190000, Config->Endianness); // lui $25, %hi(func)
write32(Buf + 4, 0x08000000 | (S >> 2), Config->Endianness); // j func
- write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
- write32(Buf + 12, 0x00000000, Config->Endianness); // nop
+ write32(Buf + 8, 0x27390000, Config->Endianness); // addiu $25, $25, %lo(func)
+ write32(Buf + 12, 0x00000000, Config->Endianness); // nop
Target->relocateOne(Buf, R_MIPS_HI16, S);
Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
}
@@ -262,9 +258,7 @@ static Thunk *addThunkArm(uint32_t Reloc, SymbolBody &S) {
fatal("unrecognized relocation type");
}
-static Thunk *addThunkMips(SymbolBody &S) {
- return make<MipsThunk>(S);
-}
+static Thunk *addThunkMips(SymbolBody &S) { return make<MipsThunk>(S); }
Thunk *addThunk(uint32_t RelocType, SymbolBody &S) {
if (Config->EMachine == EM_ARM)
diff --git a/ELF/Thunks.h b/ELF/Thunks.h
index 00b6b2cf2994..21eba699fe4f 100644
--- a/ELF/Thunks.h
+++ b/ELF/Thunks.h
@@ -50,7 +50,7 @@ public:
const SymbolBody &Destination;
SymbolBody *ThunkSym;
uint64_t Offset;
- uint32_t alignment = 4;
+ uint32_t Alignment = 4;
};
// For a Relocation to symbol S create a Thunk to be added to a synthetic
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index bf43ee5c5f91..1853f99bc600 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -257,7 +257,6 @@ template <class ELFT> void Writer<ELFT>::run() {
if (ErrorCount)
return;
-
// Handle -Map option.
writeMapFile<ELFT>(OutputSectionCommands);
if (ErrorCount)
@@ -1331,7 +1330,7 @@ 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.
OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx");
- if (!Cmd || Cmd->Commands.empty() || Config->Relocatable)
+ if (!Cmd || !Cmd->Sec || Config->Relocatable)
return;
auto *Sentinel = make<ARMExidxSentinelSection>();
@@ -1392,7 +1391,8 @@ OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
return nullptr;
}
-template <class ELFT> OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
+template <class ELFT>
+OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
if (OutputSectionCommand *Cmd = findSectionCommand(Name))
return Cmd->Sec;
return nullptr;
diff --git a/ELF/Writer.h b/ELF/Writer.h
index e935b6419de6..7fa56bea1c35 100644
--- a/ELF/Writer.h
+++ b/ELF/Writer.h
@@ -55,7 +55,7 @@ uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
llvm::StringRef FileName);
bool isMipsN32Abi(const InputFile *F);
-}
-}
+} // namespace elf
+} // namespace lld
#endif