forked from OSchip/llvm-project
[ELF] Add support for reading dynamic libraries.
llvm-svn: 174916
This commit is contained in:
parent
6ae564b4a0
commit
c3c8bc1e5c
|
@ -165,22 +165,26 @@ protected:
|
||||||
class atom_collection_vector : public atom_collection<T> {
|
class atom_collection_vector : public atom_collection<T> {
|
||||||
public:
|
public:
|
||||||
virtual atom_iterator<T> begin() const {
|
virtual atom_iterator<T> begin() const {
|
||||||
return atom_iterator<T>(*this, reinterpret_cast<const void*>
|
return atom_iterator<T>(*this,
|
||||||
(_atoms.data()));
|
_atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual atom_iterator<T> end() const{
|
virtual atom_iterator<T> end() const{
|
||||||
return atom_iterator<T>(*this, reinterpret_cast<const void*>
|
return atom_iterator<T>(*this, _atoms.empty() ? 0 :
|
||||||
(_atoms.data() + _atoms.size()));
|
reinterpret_cast<const void *>(_atoms.data() + _atoms.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const T *deref(const void *it) const {
|
virtual const T *deref(const void *it) const {
|
||||||
return *reinterpret_cast<const T* const*>(it);
|
return *reinterpret_cast<const T* const*>(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void next(const void *&it) const {
|
virtual void next(const void *&it) const {
|
||||||
const T *const *p = reinterpret_cast<const T *const*>(it);
|
const T *const *p = reinterpret_cast<const T *const*>(it);
|
||||||
++p;
|
++p;
|
||||||
it = reinterpret_cast<const void*>(p);
|
it = reinterpret_cast<const void*>(p);
|
||||||
}
|
}
|
||||||
std::vector<const T*> _atoms;
|
|
||||||
|
std::vector<const T *> _atoms;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief This is a convenience class for File subclasses which need to
|
/// \brief This is a convenience class for File subclasses which need to
|
||||||
|
|
|
@ -17,8 +17,11 @@
|
||||||
|
|
||||||
// This should be the only #include, force #includes of all the others on
|
// This should be the only #include, force #includes of all the others on
|
||||||
// clients.
|
// clients.
|
||||||
|
#include "llvm/ADT/Hashing.h"
|
||||||
#include "llvm/Support/Casting.h"
|
#include "llvm/Support/Casting.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
// ADT's.
|
// ADT's.
|
||||||
class StringRef;
|
class StringRef;
|
||||||
|
@ -77,4 +80,13 @@ namespace lld {
|
||||||
using llvm::raw_ostream;
|
using llvm::raw_ostream;
|
||||||
} // end namespace clang.
|
} // end namespace clang.
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <> struct hash<llvm::StringRef> {
|
||||||
|
public:
|
||||||
|
size_t operator()(const llvm::StringRef &s) const {
|
||||||
|
return llvm::hash_value(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -41,15 +41,10 @@ public:
|
||||||
/// If so, return a SharedLibraryAtom which represents that exported
|
/// If so, return a SharedLibraryAtom which represents that exported
|
||||||
/// symbol. Otherwise return nullptr.
|
/// symbol. Otherwise return nullptr.
|
||||||
virtual const SharedLibraryAtom *exports(StringRef name,
|
virtual const SharedLibraryAtom *exports(StringRef name,
|
||||||
bool dataSymbolOnly) const;
|
bool dataSymbolOnly) const = 0;
|
||||||
protected:
|
protected:
|
||||||
/// only subclasses of SharedLibraryFile can be instantiated
|
/// only subclasses of SharedLibraryFile can be instantiated
|
||||||
SharedLibraryFile(const TargetInfo &ti, StringRef path)
|
SharedLibraryFile(StringRef path) : File(path) {}
|
||||||
: File(path), _targetInfo(ti) {
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const TargetInfo &_targetInfo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace lld
|
} // namespace lld
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
namespace elf {
|
namespace elf {
|
||||||
|
template <class ELFT> class DynamicFile;
|
||||||
template <typename ELFT> class ELFFile;
|
template <typename ELFT> class ELFFile;
|
||||||
template <typename ELFT> class TargetAtomHandler;
|
template <typename ELFT> class TargetAtomHandler;
|
||||||
|
|
||||||
|
@ -95,7 +96,7 @@ public:
|
||||||
: _owningFile(file), _name(name), _symbol(symbol), _value(value) {
|
: _owningFile(file), _name(name), _symbol(symbol), _value(value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const class ELFFile<ELFT> &file() const {
|
virtual const ELFFile<ELFT> &file() const {
|
||||||
return _owningFile;
|
return _owningFile;
|
||||||
} virtual Scope scope() const {
|
} virtual Scope scope() const {
|
||||||
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
||||||
|
@ -132,7 +133,7 @@ public:
|
||||||
const Elf_Sym *symbol)
|
const Elf_Sym *symbol)
|
||||||
: _owningFile(file), _name(name), _symbol(symbol) {}
|
: _owningFile(file), _name(name), _symbol(symbol) {}
|
||||||
|
|
||||||
virtual const class ELFFile<ELFT> &file() const {
|
virtual const ELFFile<ELFT> &file() const {
|
||||||
return _owningFile;
|
return _owningFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ public:
|
||||||
_ordinal = ++orderNumber;
|
_ordinal = ++orderNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const class ELFFile<ELFT> &file() const {
|
virtual const ELFFile<ELFT> &file() const {
|
||||||
return _owningFile;
|
return _owningFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,6 +441,49 @@ private:
|
||||||
std::vector<ELFReference<ELFT>*> &
|
std::vector<ELFReference<ELFT>*> &
|
||||||
_referenceList;
|
_referenceList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief An atom from a shared library.
|
||||||
|
template <class ELFT>
|
||||||
|
class ELFDynamicAtom LLVM_FINAL : public SharedLibraryAtom {
|
||||||
|
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ELFDynamicAtom(const DynamicFile<ELFT> &file, StringRef symbolName,
|
||||||
|
StringRef loadName, const Elf_Sym *symbol)
|
||||||
|
: _owningFile(file), _symbolName(symbolName), _loadName(loadName),
|
||||||
|
_symbol(symbol) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const DynamicFile<ELFT> &file() const {
|
||||||
|
return _owningFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual StringRef name() const {
|
||||||
|
return _symbolName;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual Scope scope() const {
|
||||||
|
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
||||||
|
return scopeLinkageUnit;
|
||||||
|
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
|
||||||
|
return scopeGlobal;
|
||||||
|
else
|
||||||
|
return scopeTranslationUnit;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual StringRef loadName() const { return _loadName; }
|
||||||
|
|
||||||
|
virtual bool canBeNullAtRuntime() const {
|
||||||
|
return _symbol->getBinding() == llvm::ELF::STB_WEAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const DynamicFile<ELFT> &_owningFile;
|
||||||
|
StringRef _symbolName;
|
||||||
|
StringRef _loadName;
|
||||||
|
const Elf_Sym *_symbol;
|
||||||
|
};
|
||||||
} // end namespace elf
|
} // end namespace elf
|
||||||
} // end namespace lld
|
} // end namespace lld
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
//===- lib/ReaderWriter/ELF/CreateELF.h -----------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Linker
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
///
|
||||||
|
/// \file
|
||||||
|
/// \brief This file provides a simple way to create an object templated on
|
||||||
|
/// ELFType depending on the runtime type needed.
|
||||||
|
///
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
#ifndef LLD_READER_WRITER_ELF_CREATE_ELF_H
|
||||||
|
#define LLD_READER_WRITER_ELF_CREATE_ELF_H
|
||||||
|
|
||||||
|
#include "llvm/Object/ELF.h"
|
||||||
|
#include "llvm/Support/Compiler.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using llvm::object::ELFType;
|
||||||
|
|
||||||
|
/// \func createELF
|
||||||
|
/// \brief Create an object depending on the runtime attributes and alignment
|
||||||
|
/// of an ELF file.
|
||||||
|
///
|
||||||
|
/// \param Traits
|
||||||
|
/// Traits::result_type must be a type convertable from what create returns.
|
||||||
|
/// Traits::create must be a template function which takes an ELFType and
|
||||||
|
/// returns something convertable to Traits::result_type.
|
||||||
|
///
|
||||||
|
/// \param ident pair of EI_CLASS and EI_DATA.
|
||||||
|
/// \param maxAlignment the maximum alignment of the file.
|
||||||
|
/// \param args arguments forwarded to CreateELFTraits<T>::create.
|
||||||
|
|
||||||
|
#define LLVM_CREATE_ELF_CreateELFTraits(endian, align, is64, ...) \
|
||||||
|
Traits::template create<ELFType<llvm::support::endian, align, is64>>( \
|
||||||
|
__VA_ARGS__);
|
||||||
|
|
||||||
|
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
||||||
|
# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
|
||||||
|
if (maxAlignment >= normal) \
|
||||||
|
return LLVM_CREATE_ELF_CreateELFTraits(endian, normal, is64, __VA_ARGS__) \
|
||||||
|
else if (maxAlignment >= low) \
|
||||||
|
return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
|
||||||
|
else \
|
||||||
|
llvm_unreachable("Invalid alignment for ELF file!");
|
||||||
|
#else
|
||||||
|
# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
|
||||||
|
if (maxAlignment >= low) \
|
||||||
|
return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
|
||||||
|
else \
|
||||||
|
llvm_unreachable("Invalid alignment for ELF file!");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LLVM_CREATE_ELF_IMPL(...) \
|
||||||
|
if (ident.first == llvm::ELF::ELFCLASS32 && \
|
||||||
|
ident.second == llvm::ELF::ELFDATA2LSB) { \
|
||||||
|
LLVM_CREATE_ELF_MaxAlignCheck(4, 2, little, false, __VA_ARGS__) \
|
||||||
|
} else if (ident.first == llvm::ELF::ELFCLASS32 && \
|
||||||
|
ident.second == llvm::ELF::ELFDATA2MSB) { \
|
||||||
|
LLVM_CREATE_ELF_MaxAlignCheck(4, 2, big, false, __VA_ARGS__) \
|
||||||
|
} else if (ident.first == llvm::ELF::ELFCLASS64 && \
|
||||||
|
ident.second == llvm::ELF::ELFDATA2MSB) { \
|
||||||
|
LLVM_CREATE_ELF_MaxAlignCheck(8, 2, big, true, __VA_ARGS__) \
|
||||||
|
} else if (ident.first == llvm::ELF::ELFCLASS64 && \
|
||||||
|
ident.second == llvm::ELF::ELFDATA2LSB) { \
|
||||||
|
LLVM_CREATE_ELF_MaxAlignCheck(8, 2, little, true, __VA_ARGS__) \
|
||||||
|
} \
|
||||||
|
llvm_unreachable("Invalid ELF type!");
|
||||||
|
|
||||||
|
#if LLVM_HAS_VARIADIC_TEMPLATES
|
||||||
|
template <class Traits, class ...Args>
|
||||||
|
typename Traits::result_type createELF(
|
||||||
|
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
|
||||||
|
Args &&...args) {
|
||||||
|
LLVM_CREATE_ELF_IMPL(std::forward<Args>(args)...)
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
template <class Traits, class T1>
|
||||||
|
typename Traits::result_type createELF(
|
||||||
|
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
|
||||||
|
T1 &&t1) {
|
||||||
|
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1))
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Traits, class T1, class T2>
|
||||||
|
typename Traits::result_type createELF(
|
||||||
|
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
|
||||||
|
T1 &&t1, T2 &&t2) {
|
||||||
|
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2))
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Traits, class T1, class T2, class T3>
|
||||||
|
typename Traits::result_type createELF(
|
||||||
|
std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
|
||||||
|
T1 &&t1, T2 &&t2, T3 &&t3) {
|
||||||
|
LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2),
|
||||||
|
std::forward<T3>(t3))
|
||||||
|
}
|
||||||
|
#endif // LLVM_HAS_VARIADIC_TEMPLATES
|
||||||
|
} // end anon namespace
|
||||||
|
|
||||||
|
#undef LLVM_CREATE_ELF_CreateELFTraits
|
||||||
|
#undef LLVM_CREATE_ELF_MaxAlignCheck
|
||||||
|
#undef LLVM_CREATE_ELF_IMPL
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,132 @@
|
||||||
|
//===- 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 "lld/Core/SharedLibraryFile.h"
|
||||||
|
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||||
|
|
||||||
|
#include "llvm/Object/ELF.h"
|
||||||
|
#include "llvm/Support/Path.h"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
namespace lld {
|
||||||
|
namespace elf {
|
||||||
|
template <class ELFT> class DynamicFile LLVM_FINAL : public SharedLibraryFile {
|
||||||
|
public:
|
||||||
|
static ErrorOr<std::unique_ptr<DynamicFile> > create(
|
||||||
|
const ELFTargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||||
|
std::unique_ptr<DynamicFile> file(
|
||||||
|
new DynamicFile(ti, mb->getBufferIdentifier()));
|
||||||
|
|
||||||
|
static uint32_t lastOrdinal = 0;
|
||||||
|
file->_ordinal = lastOrdinal++;
|
||||||
|
|
||||||
|
llvm::OwningPtr<llvm::object::Binary> binaryFile;
|
||||||
|
if (error_code ec = createBinary(mb.release(), binaryFile))
|
||||||
|
return ec;
|
||||||
|
|
||||||
|
// Point Obj to correct class and bitwidth ELF object
|
||||||
|
file->_objFile.reset(
|
||||||
|
dyn_cast<llvm::object::ELFObjectFile<ELFT>>(binaryFile.get()));
|
||||||
|
|
||||||
|
if (!file->_objFile)
|
||||||
|
return make_error_code(llvm::object::object_error::invalid_file_type);
|
||||||
|
|
||||||
|
binaryFile.take();
|
||||||
|
|
||||||
|
llvm::object::ELFObjectFile<ELFT> &obj = *file->_objFile;
|
||||||
|
|
||||||
|
file->_soname = obj.getLoadName();
|
||||||
|
if (file->_soname.empty())
|
||||||
|
file->_soname = llvm::sys::path::filename(file->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_elf_dynamic_symbols(),
|
||||||
|
e = obj.end_elf_dynamic_symbols();
|
||||||
|
i != e; ++i) {
|
||||||
|
// Don't expose undefined or absolute symbols to export.
|
||||||
|
if (i->st_shndx == llvm::ELF::SHN_ABS ||
|
||||||
|
i->st_shndx == llvm::ELF::SHN_UNDEF)
|
||||||
|
continue;
|
||||||
|
StringRef name;
|
||||||
|
if (error_code ec =
|
||||||
|
obj.getSymbolName(obj.getDynamicSymbolTableSectionHeader(), &*i,
|
||||||
|
name))
|
||||||
|
return ec;
|
||||||
|
file->_nameToSym[name]._symbol = &*i;
|
||||||
|
|
||||||
|
// TODO: Read undefined dynamic symbols into _undefinedAtoms.
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||||
|
return _definedAtoms;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const atom_collection<UndefinedAtom> &undefined() const {
|
||||||
|
return _undefinedAtoms;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
|
||||||
|
return _sharedLibraryAtoms;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const atom_collection<AbsoluteAtom> &absolute() const {
|
||||||
|
return _absoluteAtoms;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const SharedLibraryAtom *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);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual const ELFTargetInfo &getTargetInfo() const { return _targetInfo; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
DynamicFile(const ELFTargetInfo &ti, StringRef name)
|
||||||
|
: SharedLibraryFile(name), _targetInfo(ti) {}
|
||||||
|
|
||||||
|
const ELFTargetInfo &_targetInfo;
|
||||||
|
std::unique_ptr<llvm::object::ELFObjectFile<ELFT>> _objFile;
|
||||||
|
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||||
|
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||||
|
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||||
|
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
|
||||||
|
/// \brief DT_SONAME
|
||||||
|
StringRef _soname;
|
||||||
|
|
||||||
|
struct SymAtomPair {
|
||||||
|
const typename llvm::object::ELFObjectFile<ELFT>::Elf_Sym *_symbol;
|
||||||
|
const SharedLibraryAtom *_atom;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
|
||||||
|
mutable llvm::BumpPtrAllocator _alloc;
|
||||||
|
};
|
||||||
|
} // end namespace elf
|
||||||
|
} // end namespace lld
|
||||||
|
|
||||||
|
#endif
|
|
@ -38,16 +38,6 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<llvm::StringRef> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const llvm::StringRef &s) const {
|
|
||||||
using llvm::hash_value;
|
|
||||||
return hash_value(s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
namespace elf {
|
namespace elf {
|
||||||
/// \brief Read a binary, find out based on the symbol table contents what kind
|
/// \brief Read a binary, find out based on the symbol table contents what kind
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "lld/ReaderWriter/Reader.h"
|
#include "lld/ReaderWriter/Reader.h"
|
||||||
|
|
||||||
#include "Atoms.h"
|
#include "Atoms.h"
|
||||||
|
#include "CreateELF.h"
|
||||||
|
#include "DynamicFile.h"
|
||||||
#include "File.h"
|
#include "File.h"
|
||||||
|
|
||||||
#include "lld/Core/Reference.h"
|
#include "lld/Core/Reference.h"
|
||||||
|
@ -46,6 +48,30 @@
|
||||||
using llvm::support::endianness;
|
using llvm::support::endianness;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct DynamicFileCreateELFTraits {
|
||||||
|
typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
static result_type create(const lld::ELFTargetInfo &ti,
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||||
|
return lld::elf::DynamicFile<ELFT>::create(ti, std::move(mb));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ELFFileCreateELFTraits {
|
||||||
|
typedef std::unique_ptr<lld::File> result_type;
|
||||||
|
|
||||||
|
template <class ELFT>
|
||||||
|
static result_type create(const lld::ELFTargetInfo &ti,
|
||||||
|
std::unique_ptr<llvm::MemoryBuffer> mb,
|
||||||
|
lld::error_code &ec) {
|
||||||
|
return std::unique_ptr<lld::File>(
|
||||||
|
new lld::elf::ELFFile<ELFT>(ti, std::move(mb), ec));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
namespace elf {
|
namespace elf {
|
||||||
/// \brief A reader object that will instantiate correct File by examining the
|
/// \brief A reader object that will instantiate correct File by examining the
|
||||||
|
@ -69,66 +95,20 @@ public:
|
||||||
llvm::error_code ec;
|
llvm::error_code ec;
|
||||||
switch (fileType) {
|
switch (fileType) {
|
||||||
case llvm::sys::ELF_Relocatable_FileType: {
|
case llvm::sys::ELF_Relocatable_FileType: {
|
||||||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(&*mb);
|
std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
|
||||||
std::unique_ptr<File> f;
|
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb),
|
||||||
// Instantiate the correct File template instance based on the Ident
|
ec));
|
||||||
// pair. Once the File is created we push the file to the vector of files
|
if (ec)
|
||||||
// already created during parser's life.
|
return ec;
|
||||||
if (Ident.first == llvm::ELF::ELFCLASS32 &&
|
result.push_back(std::move(f));
|
||||||
Ident.second == llvm::ELF::ELFDATA2LSB) {
|
break;
|
||||||
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
}
|
||||||
if (MaxAlignment >= 4)
|
case llvm::sys::ELF_SharedObject_FileType: {
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::little, 4, false> >(
|
auto f = createELF<DynamicFileCreateELFTraits>(
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
|
||||||
else
|
if (!f)
|
||||||
#endif
|
return f;
|
||||||
if (MaxAlignment >= 2)
|
result.push_back(std::move(*f));
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::little, 2, false> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
llvm_unreachable("Invalid alignment for ELF file!");
|
|
||||||
} else if (Ident.first == llvm::ELF::ELFCLASS32 &&
|
|
||||||
Ident.second == llvm::ELF::ELFDATA2MSB) {
|
|
||||||
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
|
||||||
if (MaxAlignment >= 4)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::big, 4, false> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (MaxAlignment >= 2)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::big, 2, false> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
llvm_unreachable("Invalid alignment for ELF file!");
|
|
||||||
} else if (Ident.first == llvm::ELF::ELFCLASS64 &&
|
|
||||||
Ident.second == llvm::ELF::ELFDATA2MSB) {
|
|
||||||
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
|
||||||
if (MaxAlignment >= 8)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::big, 8, true> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (MaxAlignment >= 2)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::big, 2, true> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
llvm_unreachable("Invalid alignment for ELF file!");
|
|
||||||
} else if (Ident.first == llvm::ELF::ELFCLASS64 &&
|
|
||||||
Ident.second == llvm::ELF::ELFDATA2LSB) {
|
|
||||||
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
|
||||||
if (MaxAlignment >= 8)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::little, 8, true> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (MaxAlignment >= 2)
|
|
||||||
f.reset(new ELFFile<ELFType<llvm::support::little, 2, true> >(
|
|
||||||
_elfTargetInfo, std::move(mb), ec));
|
|
||||||
else
|
|
||||||
llvm_unreachable("Invalid alignment for ELF file!");
|
|
||||||
}
|
|
||||||
if (!ec)
|
|
||||||
result.push_back(std::move(f));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case llvm::sys::Archive_FileType:
|
case llvm::sys::Archive_FileType:
|
||||||
|
|
|
@ -17,17 +17,6 @@
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<llvm::StringRef> {
|
|
||||||
public:
|
|
||||||
size_t operator()(const llvm::StringRef &s) const {
|
|
||||||
using llvm::hash_value;
|
|
||||||
return hash_value(s);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace lld {
|
namespace lld {
|
||||||
/// \brief The FileArchive class represents an Archive Library file
|
/// \brief The FileArchive class represents an Archive Library file
|
||||||
class FileArchive : public ArchiveLibraryFile {
|
class FileArchive : public ArchiveLibraryFile {
|
||||||
|
|
|
@ -220,13 +220,15 @@ private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class AtomList : public lld::File::atom_collection<T> {
|
class AtomList : public lld::File::atom_collection<T> {
|
||||||
public:
|
public:
|
||||||
virtual lld::File::atom_iterator<T> begin() const {
|
virtual lld::File::atom_iterator<T> begin() const {
|
||||||
return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*>
|
return lld::File::atom_iterator<
|
||||||
(_atoms.data()));
|
T>(*this,
|
||||||
|
_atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
|
||||||
}
|
}
|
||||||
virtual lld::File::atom_iterator<T> end() const{
|
virtual lld::File::atom_iterator<T> end() const{
|
||||||
return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*>
|
return lld::File::atom_iterator<
|
||||||
(_atoms.data() + _atoms.size()));
|
T>(*this, _atoms.empty() ? 0 :
|
||||||
|
reinterpret_cast<const void *>(_atoms.data() + _atoms.size()));
|
||||||
}
|
}
|
||||||
virtual const T *deref(const void *it) const {
|
virtual const T *deref(const void *it) const {
|
||||||
return *reinterpret_cast<const T *const*>(it);
|
return *reinterpret_cast<const T *const*>(it);
|
||||||
|
|
|
@ -20,7 +20,7 @@ if ( NOT LLD_BUILT_STANDALONE )
|
||||||
set(LLD_TEST_DEPS
|
set(LLD_TEST_DEPS
|
||||||
lld-core lld-test.deps
|
lld-core lld-test.deps
|
||||||
FileCheck not llvm-nm
|
FileCheck not llvm-nm
|
||||||
lld llvm-objdump
|
lld llvm-objdump llvm-readobj
|
||||||
)
|
)
|
||||||
set(LLD_TEST_PARAMS
|
set(LLD_TEST_PARAMS
|
||||||
lld_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
|
lld_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void foo() {
|
||||||
|
puts("Fooo!!");
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,5 @@
|
||||||
|
void foo();
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
foo();
|
||||||
|
}
|
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||||
|
RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=- -noinhibit-exec \
|
||||||
|
RUN: | FileCheck %s
|
||||||
|
|
||||||
|
CHECK: shared-library-atoms:
|
||||||
|
CHECK: name: foo
|
||||||
|
CHECK: load-name: shared.so-x86-64
|
Loading…
Reference in New Issue