diff options
-rw-r--r-- | lld/include/lld/Core/File.h | 14 | ||||
-rw-r--r-- | lld/include/lld/Core/LLVM.h | 12 | ||||
-rw-r--r-- | lld/include/lld/Core/SharedLibraryFile.h | 9 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Atoms.h | 50 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/CreateELF.h | 109 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/DynamicFile.h | 132 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/File.h | 10 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ELF/Reader.cpp | 100 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/ReaderArchive.cpp | 11 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 14 | ||||
-rw-r--r-- | lld/test/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lld/test/elf/Inputs/shared.c | 5 | ||||
-rw-r--r-- | lld/test/elf/Inputs/shared.so-x86-64 | bin | 0 -> 8125 bytes | |||
-rw-r--r-- | lld/test/elf/Inputs/use-shared.c | 5 | ||||
-rw-r--r-- | lld/test/elf/Inputs/use-shared.x86-64 | bin | 0 -> 1264 bytes | |||
-rw-r--r-- | lld/test/elf/dynamic-library.test | 7 |
16 files changed, 377 insertions, 103 deletions
diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h index 4242c20ef2a..109a824abd8 100644 --- a/lld/include/lld/Core/File.h +++ b/lld/include/lld/Core/File.h @@ -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 diff --git a/lld/include/lld/Core/LLVM.h b/lld/include/lld/Core/LLVM.h index eb809146ddb..7f7a6529fa5 100644 --- a/lld/include/lld/Core/LLVM.h +++ b/lld/include/lld/Core/LLVM.h @@ -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 diff --git a/lld/include/lld/Core/SharedLibraryFile.h b/lld/include/lld/Core/SharedLibraryFile.h index 0303363f6c0..730fbeab0be 100644 --- a/lld/include/lld/Core/SharedLibraryFile.h +++ b/lld/include/lld/Core/SharedLibraryFile.h @@ -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 diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h index fd85806464e..9cff16b194c 100644 --- a/lld/lib/ReaderWriter/ELF/Atoms.h +++ b/lld/lib/ReaderWriter/ELF/Atoms.h @@ -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 diff --git a/lld/lib/ReaderWriter/ELF/CreateELF.h b/lld/lib/ReaderWriter/ELF/CreateELF.h new file mode 100644 index 00000000000..8a29976438a --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/CreateELF.h @@ -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 diff --git a/lld/lib/ReaderWriter/ELF/DynamicFile.h b/lld/lib/ReaderWriter/ELF/DynamicFile.h new file mode 100644 index 00000000000..2e80745bdb1 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/DynamicFile.h @@ -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 diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h index 91b03ecb087..f1123ef539f 100644 --- a/lld/lib/ReaderWriter/ELF/File.h +++ b/lld/lib/ReaderWriter/ELF/File.h @@ -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 diff --git a/lld/lib/ReaderWriter/ELF/Reader.cpp b/lld/lib/ReaderWriter/ELF/Reader.cpp index 8a95cede9b6..be2fedb239b 100644 --- a/lld/lib/ReaderWriter/ELF/Reader.cpp +++ b/lld/lib/ReaderWriter/ELF/Reader.cpp @@ -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: diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp index e3736d73fd8..ba92087225c 100644 --- a/lld/lib/ReaderWriter/ReaderArchive.cpp +++ b/lld/lib/ReaderWriter/ReaderArchive.cpp @@ -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 { diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index e351cc1104b..5320b6e2f43 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -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); diff --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt index 4bf808d548f..f1ae51fcdf2 100644 --- a/lld/test/CMakeLists.txt +++ b/lld/test/CMakeLists.txt @@ -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 diff --git a/lld/test/elf/Inputs/shared.c b/lld/test/elf/Inputs/shared.c new file mode 100644 index 00000000000..9bf69f83f6e --- /dev/null +++ b/lld/test/elf/Inputs/shared.c @@ -0,0 +1,5 @@ +#include <stdio.h> + +void foo() { + puts("Fooo!!"); +} diff --git a/lld/test/elf/Inputs/shared.so-x86-64 b/lld/test/elf/Inputs/shared.so-x86-64 Binary files differnew file mode 100644 index 00000000000..cc2fe5610ba --- /dev/null +++ b/lld/test/elf/Inputs/shared.so-x86-64 diff --git a/lld/test/elf/Inputs/use-shared.c b/lld/test/elf/Inputs/use-shared.c new file mode 100644 index 00000000000..54332356b0b --- /dev/null +++ b/lld/test/elf/Inputs/use-shared.c @@ -0,0 +1,5 @@ +void foo(); + +int main() { + foo(); +} diff --git a/lld/test/elf/Inputs/use-shared.x86-64 b/lld/test/elf/Inputs/use-shared.x86-64 Binary files differnew file mode 100644 index 00000000000..f7236ff6973 --- /dev/null +++ b/lld/test/elf/Inputs/use-shared.x86-64 diff --git a/lld/test/elf/dynamic-library.test b/lld/test/elf/dynamic-library.test new file mode 100644 index 00000000000..d559bccad36 --- /dev/null +++ b/lld/test/elf/dynamic-library.test @@ -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 |