Files
clang-p2996/lld/lib/ReaderWriter/ELF/DynamicFile.h
Shankar Easwaran eeee23e60a This adds functionality for undefined atoms from dynamic libraries to be added
to the list of undefined atoms. 

The processing of undefined atoms from dynamic libraries is controlled by
use-shlib-undefines command line option. 

This patch also adds additional command line arguments to allow/disallow
unresolved symbols from shared libraries and mimics GNU ld behavior.

llvm-svn: 179257
2013-04-11 02:56:30 +00:00

141 lines
4.4 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/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()));
llvm::OwningPtr<llvm::object::Binary> binaryFile;
bool useShlibUndefines = ti.useShlibUndefines();
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) {
StringRef name;
if (error_code ec = obj.getSymbolName(
obj.getDynamicSymbolTableSectionHeader(), &*i, name))
return ec;
// TODO: Add absolute symbols
if (i->st_shndx == llvm::ELF::SHN_ABS)
continue;
if (useShlibUndefines && (i->st_shndx == llvm::ELF::SHN_UNDEF)) {
// Create an undefined atom.
if (!name.empty()) {
auto *newAtom =
new (file->_alloc) ELFUndefinedAtom<ELFT>(*file.get(), name, &*i);
file->_undefinedAtoms._atoms.push_back(newAtom);
}
continue;
}
file->_nameToSym[name]._symbol = &*i;
}
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) {}
mutable llvm::BumpPtrAllocator _alloc;
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 {
SymAtomPair() : _symbol(nullptr), _atom(nullptr) {}
const typename llvm::object::ELFObjectFile<ELFT>::Elf_Sym *_symbol;
const SharedLibraryAtom *_atom;
};
mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
};
} // end namespace elf
} // end namespace lld
#endif