Rui Ueyama 72553767d5 ELF: Pass file types instead of type traits to ELFObjectReader.
All <Arch>ELFFileCreateFileTraits structs are the same except its file type.
That means that we don't need to pass the type traits. Instead, we can only
pass file types. By doing this, we can remove copy-pasted boilerplates.

llvm-svn: 234047
2015-04-03 20:29:37 +00:00

123 lines
3.8 KiB
C++

//===- lib/ReaderWriter/ELF/DynamicFile.h ---------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
#define LLD_READER_WRITER_ELF_DYNAMIC_FILE_H
#include "Atoms.h"
#include "lld/Core/SharedLibraryFile.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Path.h"
#include <unordered_map>
namespace lld {
namespace elf {
template <class ELFT> class DynamicFile : public SharedLibraryFile {
public:
static ErrorOr<std::unique_ptr<DynamicFile>>
create(std::unique_ptr<llvm::MemoryBuffer> mb, ELFLinkingContext &ctx);
DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
_ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
const SharedLibraryAtom *exports(StringRef name,
bool dataSymbolOnly) const override {
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);
}
StringRef getDSOName() const override { return _soname; }
protected:
std::error_code doParse() override {
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._atoms.push_back(newAtom);
}
continue;
}
_nameToSym[*name]._symbol = &*i;
}
return std::error_code();
}
private:
mutable llvm::BumpPtrAllocator _alloc;
std::unique_ptr<llvm::object::ELFFile<ELFT>> _objFile;
/// \brief DT_SONAME
StringRef _soname;
struct SymAtomPair {
const typename llvm::object::ELFFile<ELFT>::Elf_Sym *_symbol = nullptr;
const SharedLibraryAtom *_atom = nullptr;
};
std::unique_ptr<MemoryBuffer> _mb;
ELFLinkingContext &_ctx;
bool _useShlibUndefines;
mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
};
template <class ELFT>
ErrorOr<std::unique_ptr<DynamicFile<ELFT>>>
DynamicFile<ELFT>::create(std::unique_ptr<llvm::MemoryBuffer> mb,
ELFLinkingContext &ctx) {
return std::unique_ptr<DynamicFile>(new DynamicFile(std::move(mb), ctx));
}
} // end namespace elf
} // end namespace lld
#endif