diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:58 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:58 +0000 |
commit | da06c7cfa0388de29a4024d8d386e48f2fb13ed6 (patch) | |
tree | dc28e84fc2bb9a4a4d9873fe4d04946fe3f7f4c0 /ELF | |
parent | 267829774358b5aebd3e726ae318813bd48129bb (diff) | |
download | src-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.cpp | 45 | ||||
-rw-r--r-- | ELF/Arch/MipsArchTree.cpp | 6 | ||||
-rw-r--r-- | ELF/Config.h | 1 | ||||
-rw-r--r-- | ELF/Driver.cpp | 4 | ||||
-rw-r--r-- | ELF/EhFrame.h | 4 | ||||
-rw-r--r-- | ELF/Filesystem.h | 4 | ||||
-rw-r--r-- | ELF/GdbIndex.h | 2 | ||||
-rw-r--r-- | ELF/ICF.h | 2 | ||||
-rw-r--r-- | ELF/InputFiles.h | 4 | ||||
-rw-r--r-- | ELF/LTO.h | 6 | ||||
-rw-r--r-- | ELF/LinkerScript.cpp | 19 | ||||
-rw-r--r-- | ELF/MapFile.cpp | 2 | ||||
-rw-r--r-- | ELF/MapFile.h | 4 | ||||
-rw-r--r-- | ELF/Memory.h | 4 | ||||
-rw-r--r-- | ELF/Options.td | 7 | ||||
-rw-r--r-- | ELF/OutputSections.cpp | 8 | ||||
-rw-r--r-- | ELF/OutputSections.h | 7 | ||||
-rw-r--r-- | ELF/Relocations.cpp | 81 | ||||
-rw-r--r-- | ELF/Relocations.h | 11 | ||||
-rw-r--r-- | ELF/ScriptParser.cpp | 10 | ||||
-rw-r--r-- | ELF/Strings.cpp | 23 | ||||
-rw-r--r-- | ELF/Strings.h | 7 | ||||
-rw-r--r-- | ELF/SymbolTable.cpp | 43 | ||||
-rw-r--r-- | ELF/Symbols.cpp | 2 | ||||
-rw-r--r-- | ELF/SyntheticSections.cpp | 29 | ||||
-rw-r--r-- | ELF/Target.cpp | 5 | ||||
-rw-r--r-- | ELF/Target.h | 5 | ||||
-rw-r--r-- | ELF/Threads.h | 4 | ||||
-rw-r--r-- | ELF/Thunks.cpp | 18 | ||||
-rw-r--r-- | ELF/Thunks.h | 2 | ||||
-rw-r--r-- | ELF/Writer.cpp | 6 | ||||
-rw-r--r-- | ELF/Writer.h | 4 |
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 |