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> {
|
||||
public:
|
||||
virtual atom_iterator<T> begin() const {
|
||||
return atom_iterator<T>(*this, reinterpret_cast<const void*>
|
||||
(_atoms.data()));
|
||||
return atom_iterator<T>(*this,
|
||||
_atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
|
||||
}
|
||||
|
||||
virtual atom_iterator<T> end() const{
|
||||
return atom_iterator<T>(*this, reinterpret_cast<const void*>
|
||||
(_atoms.data() + _atoms.size()));
|
||||
return atom_iterator<T>(*this, _atoms.empty() ? 0 :
|
||||
reinterpret_cast<const void *>(_atoms.data() + _atoms.size()));
|
||||
}
|
||||
|
||||
virtual const T *deref(const void *it) const {
|
||||
return *reinterpret_cast<const T* const*>(it);
|
||||
}
|
||||
|
||||
virtual void next(const void *&it) const {
|
||||
const T *const *p = reinterpret_cast<const T *const*>(it);
|
||||
++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
|
||||
|
|
|
@ -17,8 +17,11 @@
|
|||
|
||||
// This should be the only #include, force #includes of all the others on
|
||||
// clients.
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
// ADT's.
|
||||
class StringRef;
|
||||
|
@ -77,4 +80,13 @@ namespace lld {
|
|||
using llvm::raw_ostream;
|
||||
} // 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
|
||||
|
|
|
@ -41,15 +41,10 @@ public:
|
|||
/// If so, return a SharedLibraryAtom which represents that exported
|
||||
/// symbol. Otherwise return nullptr.
|
||||
virtual const SharedLibraryAtom *exports(StringRef name,
|
||||
bool dataSymbolOnly) const;
|
||||
bool dataSymbolOnly) const = 0;
|
||||
protected:
|
||||
/// only subclasses of SharedLibraryFile can be instantiated
|
||||
SharedLibraryFile(const TargetInfo &ti, StringRef path)
|
||||
: File(path), _targetInfo(ti) {
|
||||
}
|
||||
|
||||
private:
|
||||
const TargetInfo &_targetInfo;
|
||||
SharedLibraryFile(StringRef path) : File(path) {}
|
||||
};
|
||||
|
||||
} // namespace lld
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
template <class ELFT> class DynamicFile;
|
||||
template <typename ELFT> class ELFFile;
|
||||
template <typename ELFT> class TargetAtomHandler;
|
||||
|
||||
|
@ -95,7 +96,7 @@ public:
|
|||
: _owningFile(file), _name(name), _symbol(symbol), _value(value) {
|
||||
}
|
||||
|
||||
virtual const class ELFFile<ELFT> &file() const {
|
||||
virtual const ELFFile<ELFT> &file() const {
|
||||
return _owningFile;
|
||||
} virtual Scope scope() const {
|
||||
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
||||
|
@ -132,7 +133,7 @@ public:
|
|||
const Elf_Sym *symbol)
|
||||
: _owningFile(file), _name(name), _symbol(symbol) {}
|
||||
|
||||
virtual const class ELFFile<ELFT> &file() const {
|
||||
virtual const ELFFile<ELFT> &file() const {
|
||||
return _owningFile;
|
||||
}
|
||||
|
||||
|
@ -187,7 +188,7 @@ public:
|
|||
_ordinal = ++orderNumber;
|
||||
}
|
||||
|
||||
virtual const class ELFFile<ELFT> &file() const {
|
||||
virtual const ELFFile<ELFT> &file() const {
|
||||
return _owningFile;
|
||||
}
|
||||
|
||||
|
@ -440,6 +441,49 @@ private:
|
|||
std::vector<ELFReference<ELFT>*> &
|
||||
_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 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 <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 elf {
|
||||
/// \brief Read a binary, find out based on the symbol table contents what kind
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "lld/ReaderWriter/Reader.h"
|
||||
|
||||
#include "Atoms.h"
|
||||
#include "CreateELF.h"
|
||||
#include "DynamicFile.h"
|
||||
#include "File.h"
|
||||
|
||||
#include "lld/Core/Reference.h"
|
||||
|
@ -46,6 +48,30 @@
|
|||
using llvm::support::endianness;
|
||||
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 elf {
|
||||
/// \brief A reader object that will instantiate correct File by examining the
|
||||
|
@ -69,66 +95,20 @@ public:
|
|||
llvm::error_code ec;
|
||||
switch (fileType) {
|
||||
case llvm::sys::ELF_Relocatable_FileType: {
|
||||
std::pair<unsigned char, unsigned char> Ident = getElfArchType(&*mb);
|
||||
std::unique_ptr<File> f;
|
||||
// Instantiate the correct File template instance based on the Ident
|
||||
// pair. Once the File is created we push the file to the vector of files
|
||||
// already created during parser's life.
|
||||
if (Ident.first == llvm::ELF::ELFCLASS32 &&
|
||||
Ident.second == llvm::ELF::ELFDATA2LSB) {
|
||||
#if !LLVM_IS_UNALIGNED_ACCESS_FAST
|
||||
if (MaxAlignment >= 4)
|
||||
f.reset(new ELFFile<ELFType<llvm::support::little, 4, false> >(
|
||||
_elfTargetInfo, std::move(mb), ec));
|
||||
else
|
||||
#endif
|
||||
if (MaxAlignment >= 2)
|
||||
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));
|
||||
std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
|
||||
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb),
|
||||
ec));
|
||||
if (ec)
|
||||
return ec;
|
||||
result.push_back(std::move(f));
|
||||
break;
|
||||
}
|
||||
case llvm::sys::ELF_SharedObject_FileType: {
|
||||
auto f = createELF<DynamicFileCreateELFTraits>(
|
||||
getElfArchType(&*mb), MaxAlignment, _elfTargetInfo, std::move(mb));
|
||||
if (!f)
|
||||
return f;
|
||||
result.push_back(std::move(*f));
|
||||
break;
|
||||
}
|
||||
case llvm::sys::Archive_FileType:
|
||||
|
|
|
@ -17,17 +17,6 @@
|
|||
|
||||
#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 {
|
||||
/// \brief The FileArchive class represents an Archive Library file
|
||||
class FileArchive : public ArchiveLibraryFile {
|
||||
|
|
|
@ -220,13 +220,15 @@ private:
|
|||
template <typename T>
|
||||
class AtomList : public lld::File::atom_collection<T> {
|
||||
public:
|
||||
virtual lld::File::atom_iterator<T> begin() const {
|
||||
return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*>
|
||||
(_atoms.data()));
|
||||
virtual lld::File::atom_iterator<T> begin() const {
|
||||
return lld::File::atom_iterator<
|
||||
T>(*this,
|
||||
_atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
|
||||
}
|
||||
virtual lld::File::atom_iterator<T> end() const{
|
||||
return lld::File::atom_iterator<T>(*this, reinterpret_cast<const void*>
|
||||
(_atoms.data() + _atoms.size()));
|
||||
virtual lld::File::atom_iterator<T> end() const{
|
||||
return lld::File::atom_iterator<
|
||||
T>(*this, _atoms.empty() ? 0 :
|
||||
reinterpret_cast<const void *>(_atoms.data() + _atoms.size()));
|
||||
}
|
||||
virtual const T *deref(const void *it) const {
|
||||
return *reinterpret_cast<const T *const*>(it);
|
||||
|
|
|
@ -20,7 +20,7 @@ if ( NOT LLD_BUILT_STANDALONE )
|
|||
set(LLD_TEST_DEPS
|
||||
lld-core lld-test.deps
|
||||
FileCheck not llvm-nm
|
||||
lld llvm-objdump
|
||||
lld llvm-objdump llvm-readobj
|
||||
)
|
||||
set(LLD_TEST_PARAMS
|
||||
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