summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/DynamicFile.h
blob: 8255c81f8ba1d54c89002aee85c969b2f5f698db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//===- 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) {}

  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
OpenPOWER on IntegriCloud