diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:42 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-04-26 19:24:42 +0000 |
commit | e06a19b85dfce9ea18be97247d4ca315963edc5c (patch) | |
tree | ea315682e394f1c39a30049e4497e1a723f18e3c /ELF | |
parent | be08ec96063be8c1a1a8621eccd05a4ebeecfb42 (diff) | |
download | src-e06a19b85dfce9ea18be97247d4ca315963edc5c.tar.gz src-e06a19b85dfce9ea18be97247d4ca315963edc5c.zip |
Vendor import of lld trunk r301441:vendor/lld/lld-trunk-r301441
Notes
Notes:
svn path=/vendor/lld/dist/; revision=317453
svn path=/vendor/lld/lld-trunk-r301441/; revision=317454; tag=vendor/lld/lld-trunk-r301441
Diffstat (limited to 'ELF')
-rw-r--r-- | ELF/Driver.cpp | 75 | ||||
-rw-r--r-- | ELF/Filesystem.cpp | 17 | ||||
-rw-r--r-- | ELF/Filesystem.h | 2 | ||||
-rw-r--r-- | ELF/InputFiles.cpp | 42 | ||||
-rw-r--r-- | ELF/InputFiles.h | 12 | ||||
-rw-r--r-- | ELF/Options.td | 2 | ||||
-rw-r--r-- | ELF/OutputSections.cpp | 6 | ||||
-rw-r--r-- | ELF/SymbolTable.cpp | 34 | ||||
-rw-r--r-- | ELF/SymbolTable.h | 1 | ||||
-rw-r--r-- | ELF/Symbols.cpp | 3 | ||||
-rw-r--r-- | ELF/SyntheticSections.cpp | 4 | ||||
-rw-r--r-- | ELF/Target.cpp | 17 | ||||
-rw-r--r-- | ELF/Writer.cpp | 7 |
13 files changed, 129 insertions, 93 deletions
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp index 93924e4554c9..68eb5616a5c6 100644 --- a/ELF/Driver.cpp +++ b/ELF/Driver.cpp @@ -184,8 +184,6 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { error("attempted static link of dynamic object " + Path); return; } - Files.push_back(createSharedFile(MBRef)); - // DSOs usually have DT_SONAME tags in their ELF headers, and the // sonames are used to identify DSOs. But if they are missing, // they are identified by filenames. We don't know whether the new @@ -196,8 +194,8 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { // If a file was specified by -lfoo, the directory part is not // significant, as a user did not specify it. This behavior is // compatible with GNU. - Files.back()->DefaultSoName = - WithLOption ? sys::path::filename(Path) : Path; + Files.push_back(createSharedFile( + MBRef, WithLOption ? sys::path::filename(Path) : Path)); return; default: if (InLib) @@ -708,10 +706,6 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { if (!Config->Shared && !Config->AuxiliaryList.empty()) error("-f may not be used without -shared"); - for (auto *Arg : Args.filtered(OPT_dynamic_list)) - if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) - readDynamicList(*Buffer); - if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) Config->SymbolOrderingFile = getLines(*Buffer); @@ -726,21 +720,31 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { {S, /*IsExternCpp*/ false, /*HasWildcard*/ false}); } - for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) - Config->VersionScriptGlobals.push_back( - {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); - - // Dynamic lists are a simplified linker script that doesn't need the - // "global:" and implicitly ends with a "local:*". Set the variables needed to - // simulate that. - if (Args.hasArg(OPT_dynamic_list) || Args.hasArg(OPT_export_dynamic_symbol)) { - Config->ExportDynamic = true; - if (!Config->Shared) - Config->DefaultSymbolVersion = VER_NDX_LOCAL; - } + bool HasExportDynamic = + getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false); - if (getArg(Args, OPT_export_dynamic, OPT_no_export_dynamic, false)) - Config->DefaultSymbolVersion = VER_NDX_GLOBAL; + // Parses -dynamic-list and -export-dynamic-symbol. They make some + // symbols private. Note that -export-dynamic takes precedence over them + // as it says all symbols should be exported. + if (!HasExportDynamic) { + for (auto *Arg : Args.filtered(OPT_dynamic_list)) + if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) + readDynamicList(*Buffer); + + for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol)) + Config->VersionScriptGlobals.push_back( + {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false}); + + // Dynamic lists are a simplified linker script that doesn't need the + // "global:" and implicitly ends with a "local:*". Set the variables + // needed to simulate that. + if (Args.hasArg(OPT_dynamic_list) || + Args.hasArg(OPT_export_dynamic_symbol)) { + Config->ExportDynamic = true; + if (!Config->Shared) + Config->DefaultSymbolVersion = VER_NDX_LOCAL; + } + } if (auto *Arg = Args.getLastArg(OPT_version_script)) if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) @@ -876,6 +880,21 @@ static uint64_t getImageBase(opt::InputArgList &Args) { return V; } +// Parses --defsym=alias option. +static std::vector<std::pair<StringRef, StringRef>> +getDefsym(opt::InputArgList &Args) { + std::vector<std::pair<StringRef, StringRef>> Ret; + for (auto *Arg : Args.filtered(OPT_defsym)) { + StringRef From; + StringRef To; + std::tie(From, To) = StringRef(Arg->getValue()).split('='); + if (!isValidCIdentifier(To)) + error("--defsym: symbol name expected, but got " + To); + Ret.push_back({From, To}); + } + return Ret; +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { @@ -893,9 +912,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // Fail early if the output file or map file is not writable. If a user has a // long link, e.g. due to a large LTO link, they do not wish to run it and // find that it failed because there was a mistake in their command-line. - if (!isFileWritable(Config->OutputFile, "output file")) - return; - if (!isFileWritable(Config->MapFile, "map file")) + if (auto E = tryCreateFile(Config->OutputFile)) + error("cannot open output file " + Config->OutputFile + ": " + E.message()); + if (auto E = tryCreateFile(Config->MapFile)) + error("cannot open map file " + Config->MapFile + ": " + E.message()); + if (ErrorCount) return; // Use default entry point name if no name was given via the command @@ -941,6 +962,10 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { for (auto *Arg : Args.filtered(OPT_wrap)) Symtab.wrap(Arg->getValue()); + // Handle --defsym=sym=alias option. + for (std::pair<StringRef, StringRef> &Def : getDefsym(Args)) + Symtab.alias(Def.first, Def.second); + // Now that we have a complete list of input files. // Beyond this point, no new files are added. // Aggregate all input sections into one place. diff --git a/ELF/Filesystem.cpp b/ELF/Filesystem.cpp index 75f7bda75a23..b63d521a83b0 100644 --- a/ELF/Filesystem.cpp +++ b/ELF/Filesystem.cpp @@ -13,7 +13,6 @@ #include "Filesystem.h" #include "Config.h" -#include "Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileOutputBuffer.h" #include <thread> @@ -58,22 +57,20 @@ void elf::unlinkAsync(StringRef Path) { std::thread([=] { ::remove(TempPath.str().str().c_str()); }).detach(); } -// Returns true if a given file seems to be writable. +// Simulate file creation to see if Path is writable. // // Determining whether a file is writable or not is amazingly hard, // and after all the only reliable way of doing that is to actually // create a file. But we don't want to do that in this function // because LLD shouldn't update any file if it will end in a failure. -// We also don't want to reimplement heuristics. So we'll let -// FileOutputBuffer do the work. +// We also don't want to reimplement heuristics to determine if a +// file is writable. So we'll let FileOutputBuffer do the work. // // FileOutputBuffer doesn't touch a desitnation file until commit() // is called. We use that class without calling commit() to predict // if the given file is writable. -bool elf::isFileWritable(StringRef Path, StringRef Desc) { - if (auto EC = FileOutputBuffer::create(Path, 1).getError()) { - error("cannot open " + Desc + " " + Path + ": " + EC.message()); - return false; - } - return true; +std::error_code elf::tryCreateFile(StringRef Path) { + if (Path.empty()) + return std::error_code(); + return FileOutputBuffer::create(Path, 1).getError(); } diff --git a/ELF/Filesystem.h b/ELF/Filesystem.h index a33dc3651a4a..d56d067f7378 100644 --- a/ELF/Filesystem.h +++ b/ELF/Filesystem.h @@ -15,7 +15,7 @@ namespace lld { namespace elf { void unlinkAsync(StringRef Path); -bool isFileWritable(StringRef Path, StringRef FileDescription); +std::error_code tryCreateFile(StringRef Path); } } diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp index d651fbcad253..d99f71eb4aae 100644 --- a/ELF/InputFiles.cpp +++ b/ELF/InputFiles.cpp @@ -608,8 +608,9 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { } template <class ELFT> -SharedFile<ELFT>::SharedFile(MemoryBufferRef M) - : ELFFileBase<ELFT>(Base::SharedKind, M), AsNeeded(Config->AsNeeded) {} +SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) + : ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName), + AsNeeded(Config->AsNeeded) {} template <class ELFT> const typename ELFT::Shdr * @@ -619,12 +620,6 @@ SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const { toString(this)); } -template <class ELFT> StringRef SharedFile<ELFT>::getSoName() const { - if (SoName.empty()) - return this->DefaultSoName; - return SoName; -} - // Partially parse the shared object file so that we can call // getSoName on this object. template <class ELFT> void SharedFile<ELFT>::parseSoName() { @@ -867,8 +862,23 @@ void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) { Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, this)); } +// Small bit of template meta programming to handle the SharedFile constructor +// being the only one with a DefaultSoName parameter. +template <template <class> class T, class E> +typename std::enable_if<std::is_same<T<E>, SharedFile<E>>::value, + InputFile *>::type +createELFAux(MemoryBufferRef MB, StringRef DefaultSoName) { + return make<T<E>>(MB, DefaultSoName); +} +template <template <class> class T, class E> +typename std::enable_if<!std::is_same<T<E>, SharedFile<E>>::value, + InputFile *>::type +createELFAux(MemoryBufferRef MB, StringRef DefaultSoName) { + return make<T<E>>(MB); +} + template <template <class> class T> -static InputFile *createELFFile(MemoryBufferRef MB) { +static InputFile *createELFFile(MemoryBufferRef MB, StringRef DefaultSoName) { unsigned char Size; unsigned char Endian; std::tie(Size, Endian) = getElfArchType(MB.getBuffer()); @@ -882,13 +892,13 @@ static InputFile *createELFFile(MemoryBufferRef MB) { InputFile *Obj; if (Size == ELFCLASS32 && Endian == ELFDATA2LSB) - Obj = make<T<ELF32LE>>(MB); + Obj = createELFAux<T, ELF32LE>(MB, DefaultSoName); else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB) - Obj = make<T<ELF32BE>>(MB); + Obj = createELFAux<T, ELF32BE>(MB, DefaultSoName); else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB) - Obj = make<T<ELF64LE>>(MB); + Obj = createELFAux<T, ELF64LE>(MB, DefaultSoName); else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB) - Obj = make<T<ELF64BE>>(MB); + Obj = createELFAux<T, ELF64BE>(MB, DefaultSoName); else fatal(MB.getBufferIdentifier() + ": invalid file class"); @@ -933,13 +943,13 @@ InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName, uint64_t OffsetInArchive) { InputFile *F = isBitcode(MB) ? make<BitcodeFile>(MB, ArchiveName, OffsetInArchive) - : createELFFile<ObjectFile>(MB); + : createELFFile<ObjectFile>(MB, ""); F->ArchiveName = ArchiveName; return F; } -InputFile *elf::createSharedFile(MemoryBufferRef MB) { - return createELFFile<SharedFile>(MB); +InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) { + return createELFFile<SharedFile>(MB, DefaultSoName); } MemoryBufferRef LazyObjectFile::getBuffer() { diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h index 40a8b23c5ef4..4552270316d9 100644 --- a/ELF/InputFiles.h +++ b/ELF/InputFiles.h @@ -93,10 +93,6 @@ public: uint16_t EMachine = llvm::ELF::EM_NONE; uint8_t OSABI = 0; - // For SharedKind inputs, the string to use in DT_NEEDED when the library - // has no soname. - std::string DefaultSoName; - // Cache for toString(). Only toString() should use this member. mutable std::string ToStringCache; @@ -283,12 +279,12 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { typedef typename ELFT::Versym Elf_Versym; std::vector<StringRef> Undefs; - StringRef SoName; const Elf_Shdr *VersymSec = nullptr; const Elf_Shdr *VerdefSec = nullptr; public: - StringRef getSoName() const; + std::string SoName; + const Elf_Shdr *getSection(const Elf_Sym &Sym) const; llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } @@ -296,7 +292,7 @@ public: return F->kind() == Base::SharedKind; } - explicit SharedFile(MemoryBufferRef M); + SharedFile(MemoryBufferRef M, StringRef DefaultSoName); void parseSoName(); void parseRest(); @@ -329,7 +325,7 @@ public: InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "", uint64_t OffsetInArchive = 0); -InputFile *createSharedFile(MemoryBufferRef MB); +InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName); } // namespace elf } // namespace lld diff --git a/ELF/Options.td b/ELF/Options.td index 4cf14c9011c3..fda675449956 100644 --- a/ELF/Options.td +++ b/ELF/Options.td @@ -25,6 +25,8 @@ def build_id_eq: J<"build-id=">, HelpText<"Generate build ID note">; def compress_debug_sections : J<"compress-debug-sections=">, HelpText<"Compress DWARF debug sections">; +def defsym: J<"defsym=">, HelpText<"Define a symbol alias">; + def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">, HelpText<"Add a directory to the library search path">; diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp index a40818d2d301..71fc00ac35e7 100644 --- a/ELF/OutputSections.cpp +++ b/ELF/OutputSections.cpp @@ -405,8 +405,10 @@ void OutputSectionFactory::addInputSec(InputSectionBase *IS, OutputSection *&Sec = Map[Key]; if (Sec) { if (getIncompatibleFlags(Sec->Flags) != getIncompatibleFlags(IS->Flags)) - error("Section has flags incompatible with others with the same name " + - toString(IS)); + 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; diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp index 42b4fdc26faf..e55b8bf52c10 100644 --- a/ELF/SymbolTable.cpp +++ b/ELF/SymbolTable.cpp @@ -81,7 +81,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) { if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { // DSOs are uniquified not by filename but by soname. F->parseSoName(); - if (ErrorCount || !SoNames.insert(F->getSoName()).second) + if (ErrorCount || !SoNames.insert(F->SoName).second) return; SharedFiles.push_back(F); F->parseRest(); @@ -168,6 +168,19 @@ template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); } +// Creates alias for symbol. Used to implement --defsym=ALIAS=SYM. +template <class ELFT> +void SymbolTable<ELFT>::alias(StringRef Alias, StringRef Name) { + SymbolBody *B = find(Name); + if (!B) { + error("-defsym: undefined symbol: " + Name); + return; + } + Symbol *Sym = B->symbol(); + Symbol *AliasSym = addUndefined(Alias); + memcpy(AliasSym->Body.buffer, Sym->Body.buffer, sizeof(AliasSym->Body)); +} + static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { if (VA == STV_DEFAULT) return VB; @@ -548,11 +561,20 @@ template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() { // shared libraries can find them. // Except this, we ignore undefined symbols in DSOs. template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() { - for (SharedFile<ELFT> *File : SharedFiles) - for (StringRef U : File->getUndefinedSymbols()) - if (SymbolBody *Sym = find(U)) - if (Sym->isDefined()) - Sym->symbol()->ExportDynamic = true; + for (SharedFile<ELFT> *File : SharedFiles) { + for (StringRef U : File->getUndefinedSymbols()) { + SymbolBody *Sym = find(U); + if (!Sym || !Sym->isDefined()) + continue; + Sym->symbol()->ExportDynamic = true; + + // If -dynamic-list is given, the default version is set to + // VER_NDX_LOCAL, which prevents a symbol to be exported via .dynsym. + // Set to VER_NDX_GLOBAL so the symbol will be handled as if it were + // specified by -dynamic-list. + Sym->symbol()->VersionId = VER_NDX_GLOBAL; + } + } } // Initialize DemangledSyms with a map from demangled symbols to symbol diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h index a5395f5beaa1..1a745f9deea5 100644 --- a/ELF/SymbolTable.h +++ b/ELF/SymbolTable.h @@ -86,6 +86,7 @@ public: void trace(StringRef Name); void wrap(StringRef Name); + void alias(StringRef Alias, StringRef Name); private: std::vector<SymbolBody *> findByVersion(SymbolVersion Ver); diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp index 86f3162cae29..01caa6daa5ac 100644 --- a/ELF/Symbols.cpp +++ b/ELF/Symbols.cpp @@ -339,8 +339,7 @@ uint8_t Symbol::computeBinding() const { return Binding; if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) return STB_LOCAL; - const SymbolBody *Body = body(); - if (VersionId == VER_NDX_LOCAL && Body->isInCurrentDSO()) + if (VersionId == VER_NDX_LOCAL && body()->isInCurrentDSO()) return STB_LOCAL; if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) return STB_GLOBAL; diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp index 7009d3d34f66..e1f81940bb59 100644 --- a/ELF/SyntheticSections.cpp +++ b/ELF/SyntheticSections.cpp @@ -1027,7 +1027,7 @@ template <class ELFT> void DynamicSection<ELFT>::addEntries() { In<ELFT>::DynStrTab->addString(Config->RPath)}); for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) if (F->isNeeded()) - add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->getSoName())}); + add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->SoName)}); if (!Config->SoName.empty()) add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); @@ -2042,7 +2042,7 @@ void VersionNeedSection<ELFT>::addSymbol(SharedSymbol *SS) { // to create one by adding it to our needed list and creating a dynstr entry // for the soname. if (File->VerdefMap.empty()) - Needed.push_back({File, In<ELFT>::DynStrTab->addString(File->getSoName())}); + Needed.push_back({File, In<ELFT>::DynStrTab->addString(File->SoName)}); typename SharedFile<ELFT>::NeededVer &NV = File->VerdefMap[Ver]; // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef, // prepare to create one by allocating a version identifier and creating a diff --git a/ELF/Target.cpp b/ELF/Target.cpp index 664dcd1ed44e..7bc29e3d3de2 100644 --- a/ELF/Target.cpp +++ b/ELF/Target.cpp @@ -223,8 +223,6 @@ public: bool isPicRel(uint32_t Type) const override; uint32_t getDynRel(uint32_t Type) const override; int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; - bool isTlsLocalDynamicRel(uint32_t Type) const override; - bool isTlsInitialExecRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writeIgotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; @@ -245,7 +243,6 @@ public: int64_t getImplicitAddend(const uint8_t *Buf, uint32_t Type) const override; bool isPicRel(uint32_t Type) const override; uint32_t getDynRel(uint32_t Type) const override; - bool isTlsLocalDynamicRel(uint32_t Type) const override; void writeGotPlt(uint8_t *Buf, const SymbolBody &S) const override; void writePltHeader(uint8_t *Buf) const override; void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, @@ -532,6 +529,7 @@ int64_t X86TargetInfo::getImplicitAddend(const uint8_t *Buf, case R_386_GOTPC: case R_386_PC32: case R_386_PLT32: + case R_386_TLS_LDO_32: case R_386_TLS_LE: return SignExtend64<32>(read32le(Buf)); } @@ -2065,14 +2063,6 @@ int64_t ARMTargetInfo::getImplicitAddend(const uint8_t *Buf, } } -bool ARMTargetInfo::isTlsLocalDynamicRel(uint32_t Type) const { - return Type == R_ARM_TLS_LDO32 || Type == R_ARM_TLS_LDM32; -} - -bool ARMTargetInfo::isTlsInitialExecRel(uint32_t Type) const { - return Type == R_ARM_TLS_IE32; -} - template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() { GotPltHeaderEntriesNum = 2; DefaultMaxPageSize = 65536; @@ -2165,11 +2155,6 @@ uint32_t MipsTargetInfo<ELFT>::getDynRel(uint32_t Type) const { } template <class ELFT> -bool MipsTargetInfo<ELFT>::isTlsLocalDynamicRel(uint32_t Type) const { - return Type == R_MIPS_TLS_LDM; -} - -template <class ELFT> void MipsTargetInfo<ELFT>::writeGotPlt(uint8_t *Buf, const SymbolBody &) const { write32<ELFT::TargetEndianness>(Buf, In<ELFT>::Plt->getVA()); } diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp index e8718c258c77..989a55af1675 100644 --- a/ELF/Writer.cpp +++ b/ELF/Writer.cpp @@ -858,11 +858,8 @@ template <class ELFT> void Writer<ELFT>::addReservedSymbols() { // __tls_get_addr is defined by the dynamic linker for dynamic ELFs. For // static linking the linker is required to optimize away any references to // __tls_get_addr, so it's not defined anywhere. Create a hidden definition - // to avoid the undefined symbol error. As usual special cases are ARM and - // MIPS - the libc for these targets defines __tls_get_addr itself because - // there are no TLS optimizations for these targets. - if (!In<ELFT>::DynSymTab && - (Config->EMachine != EM_MIPS && Config->EMachine != EM_ARM)) + // to avoid the undefined symbol error. + if (!In<ELFT>::DynSymTab) Symtab<ELFT>::X->addIgnored("__tls_get_addr"); // If linker script do layout we do not need to create any standart symbols. |