aboutsummaryrefslogtreecommitdiffstats
path: root/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-04-26 19:24:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-04-26 19:24:42 +0000
commite06a19b85dfce9ea18be97247d4ca315963edc5c (patch)
treeea315682e394f1c39a30049e4497e1a723f18e3c /ELF
parentbe08ec96063be8c1a1a8621eccd05a4ebeecfb42 (diff)
downloadsrc-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.cpp75
-rw-r--r--ELF/Filesystem.cpp17
-rw-r--r--ELF/Filesystem.h2
-rw-r--r--ELF/InputFiles.cpp42
-rw-r--r--ELF/InputFiles.h12
-rw-r--r--ELF/Options.td2
-rw-r--r--ELF/OutputSections.cpp6
-rw-r--r--ELF/SymbolTable.cpp34
-rw-r--r--ELF/SymbolTable.h1
-rw-r--r--ELF/Symbols.cpp3
-rw-r--r--ELF/SyntheticSections.cpp4
-rw-r--r--ELF/Target.cpp17
-rw-r--r--ELF/Writer.cpp7
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.