aboutsummaryrefslogtreecommitdiff
path: root/ELF/SymbolTable.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-01-13 20:06:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-01-13 20:06:04 +0000
commitb289257c7f3ed78b7d3971c596d7c60a9050c705 (patch)
treed6b57e29a5a86347a020d6f0cae76cc2d0f3bf8d /ELF/SymbolTable.cpp
parentfba2c04f31e119eacf142fcbbaabd5a9e63a39ed (diff)
downloadsrc-b289257c7f3ed78b7d3971c596d7c60a9050c705.tar.gz
src-b289257c7f3ed78b7d3971c596d7c60a9050c705.zip
Vendor import of lld trunk r257626:vendor/lld/lld-trunk-r257626
Notes
Notes: svn path=/vendor/lld/dist/; revision=293846 svn path=/vendor/lld/lld-trunk-r257626/; revision=293847; tag=vendor/lld/lld-trunk-r257626
Diffstat (limited to 'ELF/SymbolTable.cpp')
-rw-r--r--ELF/SymbolTable.cpp49
1 files changed, 35 insertions, 14 deletions
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 74951bad410f..65f5dff9d7a3 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -18,6 +18,7 @@
#include "Config.h"
#include "Error.h"
#include "Symbols.h"
+#include "llvm/Support/StringSaver.h"
using namespace llvm;
using namespace llvm::object;
@@ -26,8 +27,6 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf2;
-template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
-
// All input object files must be for the same architecture
// (e.g. it does not make sense to link x86 object files with
// MIPS object files.) This function checks for that error.
@@ -64,7 +63,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
// DSOs are uniquified not by filename but by soname.
F->parseSoName();
- if (!IncludedSoNames.insert(F->getSoName()).second)
+ if (!SoNames.insert(F->getSoName()).second)
return;
SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
@@ -100,17 +99,20 @@ SymbolBody *SymbolTable<ELFT>::addUndefinedOpt(StringRef Name) {
}
template <class ELFT>
-void SymbolTable<ELFT>::addAbsolute(StringRef Name,
- typename ELFFile<ELFT>::Elf_Sym &ESym) {
- resolve(new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr));
+SymbolBody *SymbolTable<ELFT>::addAbsolute(StringRef Name, Elf_Sym &ESym) {
+ // Pass nullptr because absolute symbols have no corresponding input sections.
+ auto *Sym = new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr);
+ resolve(Sym);
+ return Sym;
}
template <class ELFT>
-void SymbolTable<ELFT>::addSynthetic(StringRef Name,
- OutputSectionBase<ELFT> &Section,
- typename ELFFile<ELFT>::uintX_t Value) {
+SymbolBody *SymbolTable<ELFT>::addSynthetic(StringRef Name,
+ OutputSectionBase<ELFT> &Section,
+ uintX_t Value) {
auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Value, Section);
resolve(Sym);
+ return Sym;
}
// Add Name as an "ignored" symbol. An ignored symbol is a regular
@@ -118,10 +120,27 @@ void SymbolTable<ELFT>::addSynthetic(StringRef Name,
// file's symbol table. Such symbols are useful for some linker-defined symbols.
template <class ELFT>
SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
- auto *Sym = new (Alloc)
- DefinedRegular<ELFT>(Name, ElfSym<ELFT>::IgnoreUndef, nullptr);
- resolve(Sym);
- return Sym;
+ return addAbsolute(Name, ElfSym<ELFT>::IgnoredWeak);
+}
+
+// The 'strong' variant of the addIgnored. Adds symbol which has a global
+// binding and cannot be substituted.
+template <class ELFT>
+SymbolBody *SymbolTable<ELFT>::addIgnoredStrong(StringRef Name) {
+ return addAbsolute(Name, ElfSym<ELFT>::Ignored);
+}
+
+// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM.
+// Used to implement --wrap.
+template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) {
+ if (Symtab.count(Name) == 0)
+ return;
+ StringSaver Saver(Alloc);
+ Symbol *Sym = addUndefined(Name)->getSymbol();
+ Symbol *Real = addUndefined(Saver.save("__real_" + Name))->getSymbol();
+ Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name))->getSymbol();
+ Real->Body = Sym->Body;
+ Sym->Body = Wrap->Body;
}
// Returns a file from which symbol B was created.
@@ -136,6 +155,8 @@ ELFFileBase<ELFT> *SymbolTable<ELFT>::findFile(SymbolBody *B) {
return nullptr;
}
+// Construct a string in the form of "Sym in File1 and File2".
+// Used to construct an error message.
template <class ELFT>
std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
ELFFileBase<ELFT> *OldFile = findFile(Old);
@@ -184,8 +205,8 @@ template <class ELFT> void SymbolTable<ELFT>::resolve(SymbolBody *New) {
Sym->Body = New;
}
+// Find an existing symbol or create and insert a new one.
template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
- // Find an existing Symbol or create and insert a new one.
StringRef Name = New->getName();
Symbol *&Sym = Symtab[Name];
if (!Sym)