summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/DynamicFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/DynamicFile.cpp')
-rw-r--r--lld/lib/ReaderWriter/ELF/DynamicFile.cpp109
1 files changed, 109 insertions, 0 deletions
diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.cpp b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp
new file mode 100644
index 00000000000..1858c2476b8
--- /dev/null
+++ b/lld/lib/ReaderWriter/ELF/DynamicFile.cpp
@@ -0,0 +1,109 @@
+//===- lib/ReaderWriter/ELF/DynamicFile.cpp -------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DynamicFile.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Path.h"
+
+using llvm::object::ELFType;
+
+namespace lld {
+namespace elf {
+
+template <class ELFT>
+ErrorOr<std::unique_ptr<DynamicFile<ELFT>>>
+DynamicFile<ELFT>::create(std::unique_ptr<llvm::MemoryBuffer> mb,
+ ELFLinkingContext &ctx) {
+ return llvm::make_unique<DynamicFile<ELFT>>(std::move(mb), ctx);
+}
+
+template <class ELFT>
+DynamicFile<ELFT>::DynamicFile(std::unique_ptr<MemoryBuffer> mb,
+ ELFLinkingContext &ctx)
+ : SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
+ _ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
+
+template <class ELFT>
+const SharedLibraryAtom *DynamicFile<ELFT>::exports(StringRef name,
+ bool dataSymbolOnly) const {
+ assert(!dataSymbolOnly && "Invalid option for ELF exports!");
+ // See if we have the symbol.
+ auto sym = _nameToSym.find(name);
+ if (sym == _nameToSym.end())
+ return nullptr;
+ // Have we already created a SharedLibraryAtom for it?
+ if (sym->second._atom)
+ return sym->second._atom;
+ // Create a SharedLibraryAtom for this symbol.
+ return sym->second._atom = new (_alloc)
+ ELFDynamicAtom<ELFT>(*this, name, _soname, sym->second._symbol);
+}
+
+template <class ELFT> StringRef DynamicFile<ELFT>::getDSOName() const {
+ return _soname;
+}
+
+template <class ELFT> bool DynamicFile<ELFT>::canParse(file_magic magic) {
+ return magic == file_magic::elf_shared_object;
+}
+
+template <class ELFT> std::error_code DynamicFile<ELFT>::doParse() {
+ std::error_code ec;
+ _objFile.reset(new llvm::object::ELFFile<ELFT>(_mb->getBuffer(), ec));
+ if (ec)
+ return ec;
+
+ llvm::object::ELFFile<ELFT> &obj = *_objFile;
+
+ _soname = obj.getLoadName();
+ if (_soname.empty())
+ _soname = llvm::sys::path::filename(path());
+
+ // Create a map from names to dynamic symbol table entries.
+ // TODO: This should use the object file's build in hash table instead if
+ // it exists.
+ for (auto i = obj.begin_dynamic_symbols(), e = obj.end_dynamic_symbols();
+ i != e; ++i) {
+ auto name = obj.getSymbolName(i);
+ if ((ec = name.getError()))
+ return ec;
+
+ // Dont add local symbols to dynamic entries. The first symbol in the
+ // dynamic symbol table is a local symbol.
+ if (i->getBinding() == llvm::ELF::STB_LOCAL)
+ continue;
+
+ // TODO: Add absolute symbols
+ if (i->st_shndx == llvm::ELF::SHN_ABS)
+ continue;
+
+ if (i->st_shndx == llvm::ELF::SHN_UNDEF) {
+ if (!_useShlibUndefines)
+ continue;
+ // Create an undefined atom.
+ if (!name->empty()) {
+ auto *newAtom = new (_alloc) ELFUndefinedAtom<ELFT>(*this, *name, &*i);
+ _undefinedAtoms.push_back(newAtom);
+ }
+ continue;
+ }
+ _nameToSym[*name]._symbol = &*i;
+ }
+ return std::error_code();
+}
+
+template class DynamicFile<ELFType<llvm::support::little, 2, false>>;
+template class DynamicFile<ELFType<llvm::support::big, 2, false>>;
+template class DynamicFile<ELFType<llvm::support::little, 2, true>>;
+template class DynamicFile<ELFType<llvm::support::big, 2, true>>;
+
+} // end namespace elf
+} // end namespace lld
OpenPOWER on IntegriCloud