diff options
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/DynamicFile.cpp')
| -rw-r--r-- | lld/lib/ReaderWriter/ELF/DynamicFile.cpp | 109 |
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 |

