Coverage Report

Created: 2017-09-19 22:28

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/lld/include/lld/Core/File.h
Line
Count
Source (jump to first uncovered line)
1
//===- Core/File.h - A Container of Atoms ---------------------------------===//
2
//
3
//                             The LLVM Linker
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
#ifndef LLD_CORE_FILE_H
11
#define LLD_CORE_FILE_H
12
13
#include "lld/Core/AbsoluteAtom.h"
14
#include "lld/Core/DefinedAtom.h"
15
#include "lld/Core/SharedLibraryAtom.h"
16
#include "lld/Core/UndefinedAtom.h"
17
#include "llvm/ADT/Optional.h"
18
#include "llvm/ADT/STLExtras.h"
19
#include "llvm/ADT/Twine.h"
20
#include "llvm/Support/ErrorHandling.h"
21
#include <functional>
22
#include <memory>
23
#include <mutex>
24
#include <vector>
25
26
namespace lld {
27
28
class LinkingContext;
29
30
/// Every Atom is owned by some File. A common scenario is for a single
31
/// object file (.o) to be parsed by some reader and produce a single
32
/// File object that represents the content of that object file.
33
///
34
/// To iterate through the Atoms in a File there are four methods that
35
/// return collections.  For instance to iterate through all the DefinedAtoms
36
/// in a File object use:
37
///      for (const DefinedAtoms *atom : file->defined()) {
38
///      }
39
///
40
/// The Atom objects in a File are owned by the File object.  The Atom objects
41
/// are destroyed when the File object is destroyed.
42
class File {
43
public:
44
  virtual ~File();
45
46
  /// \brief Kinds of files that are supported.
47
  enum Kind {
48
    kindErrorObject,          ///< a error object file (.o)
49
    kindNormalizedObject,     ///< a normalized file (.o)
50
    kindMachObject,           ///< a MachO object file (.o)
51
    kindCEntryObject,         ///< a file for CEntries
52
    kindHeaderObject,         ///< a file for file headers
53
    kindEntryObject,          ///< a file for the entry
54
    kindUndefinedSymsObject,  ///< a file for undefined symbols
55
    kindStubHelperObject,     ///< a file for stub helpers
56
    kindResolverMergedObject, ///< the resolver merged file.
57
    kindSectCreateObject,     ///< a sect create object file (.o)
58
    kindSharedLibrary,        ///< shared library (.so)
59
    kindArchiveLibrary        ///< archive (.a)
60
  };
61
62
  /// \brief Returns file kind.  Need for dyn_cast<> on File objects.
63
6.41k
  Kind kind() const {
64
6.41k
    return _kind;
65
6.41k
  }
66
67
  /// This returns the path to the file which was used to create this object
68
  /// (e.g. "/tmp/foo.o"). If the file is a member of an archive file, the
69
  /// returned string includes the archive file name.
70
611
  StringRef path() const {
71
611
    if (_archivePath.empty())
72
605
      return _path;
73
6
    
if (6
_archiveMemberPath.empty()6
)
74
1
      _archiveMemberPath = (_archivePath + "(" + _path + ")").str();
75
6
    return _archiveMemberPath;
76
611
  }
77
78
  /// Returns the path of the archive file name if this file is instantiated
79
  /// from an archive file. Otherwise returns the empty string.
80
0
  StringRef archivePath() const { return _archivePath; }
81
7
  void setArchivePath(StringRef path) { _archivePath = path; }
82
83
  /// Returns the path name of this file. It doesn't include archive file name.
84
0
  StringRef memberPath() const { return _path; }
85
86
  /// Returns the command line order of the file.
87
48
  uint64_t ordinal() const {
88
48
    assert(_ordinal != UINT64_MAX);
89
48
    return _ordinal;
90
48
  }
91
92
  /// Returns true/false depending on whether an ordinal has been set.
93
128
  bool hasOrdinal() const { return (_ordinal != UINT64_MAX); }
94
95
  /// Sets the command line order of the file.
96
1.00k
  void setOrdinal(uint64_t ordinal) const { _ordinal = ordinal; }
97
98
  /// Returns the ordinal for the next atom to be defined in this file.
99
855
  uint64_t getNextAtomOrdinalAndIncrement() const {
100
855
    return _nextAtomOrdinal++;
101
855
  }
102
103
  /// For allocating any objects owned by this File.
104
3.89k
  llvm::BumpPtrAllocator &allocator() const {
105
3.89k
    return _allocator;
106
3.89k
  }
107
108
  /// The type of atom mutable container.
109
  template <typename T> using AtomVector = std::vector<OwningAtomPtr<T>>;
110
111
  /// The range type for the atoms.
112
  template <typename T> class AtomRange {
113
  public:
114
483
    AtomRange(AtomVector<T> &v) : _v(v) {}
lld::File::AtomRange<lld::AbsoluteAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::AbsoluteAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::AbsoluteAtom> > >&)
Line
Count
Source
114
121
    AtomRange(AtomVector<T> &v) : _v(v) {}
lld::File::AtomRange<lld::SharedLibraryAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::SharedLibraryAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::SharedLibraryAtom> > >&)
Line
Count
Source
114
121
    AtomRange(AtomVector<T> &v) : _v(v) {}
lld::File::AtomRange<lld::UndefinedAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::UndefinedAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::UndefinedAtom> > >&)
Line
Count
Source
114
121
    AtomRange(AtomVector<T> &v) : _v(v) {}
lld::File::AtomRange<lld::DefinedAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::DefinedAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::DefinedAtom> > >&)
Line
Count
Source
114
120
    AtomRange(AtomVector<T> &v) : _v(v) {}
115
3.83k
    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
lld::File::AtomRange<lld::DefinedAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::DefinedAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::DefinedAtom> > > const&)
Line
Count
Source
115
1.60k
    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
lld::File::AtomRange<lld::UndefinedAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::UndefinedAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::UndefinedAtom> > > const&)
Line
Count
Source
115
789
    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
lld::File::AtomRange<lld::SharedLibraryAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::SharedLibraryAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::SharedLibraryAtom> > > const&)
Line
Count
Source
115
822
    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
lld::File::AtomRange<lld::AbsoluteAtom>::AtomRange(std::__1::vector<lld::OwningAtomPtr<lld::AbsoluteAtom>, std::__1::allocator<lld::OwningAtomPtr<lld::AbsoluteAtom> > > const&)
Line
Count
Source
115
622
    AtomRange(const AtomVector<T> &v) : _v(const_cast<AtomVector<T> &>(v)) {}
116
117
    typedef std::pointer_to_unary_function<const OwningAtomPtr<T>&,
118
                                           const T*> ConstDerefFn;
119
120
    typedef std::pointer_to_unary_function<OwningAtomPtr<T>&, T*> DerefFn;
121
122
    typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
123
                                  ConstDerefFn> ConstItTy;
124
    typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
125
                                  DerefFn> ItTy;
126
127
6.06k
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
128
6.06k
      return p.get();
129
6.06k
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::DerefConst(lld::OwningAtomPtr<lld::AbsoluteAtom> const&)
lld::File::AtomRange<lld::SharedLibraryAtom>::DerefConst(lld::OwningAtomPtr<lld::SharedLibraryAtom> const&)
Line
Count
Source
127
204
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
128
204
      return p.get();
129
204
    }
lld::File::AtomRange<lld::DefinedAtom>::DerefConst(lld::OwningAtomPtr<lld::DefinedAtom> const&)
Line
Count
Source
127
5.76k
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
128
5.76k
      return p.get();
129
5.76k
    }
lld::File::AtomRange<lld::UndefinedAtom>::DerefConst(lld::OwningAtomPtr<lld::UndefinedAtom> const&)
Line
Count
Source
127
93
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
128
93
      return p.get();
129
93
    }
130
131
0
    static T* Deref(OwningAtomPtr<T> &p) {
132
0
      return p.get();
133
0
    }
Unexecuted instantiation: lld::File::AtomRange<lld::DefinedAtom>::Deref(lld::OwningAtomPtr<lld::DefinedAtom>&)
Unexecuted instantiation: lld::File::AtomRange<lld::UndefinedAtom>::Deref(lld::OwningAtomPtr<lld::UndefinedAtom>&)
Unexecuted instantiation: lld::File::AtomRange<lld::SharedLibraryAtom>::Deref(lld::OwningAtomPtr<lld::SharedLibraryAtom>&)
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::Deref(lld::OwningAtomPtr<lld::AbsoluteAtom>&)
134
135
1.82k
    ConstItTy begin() const {
136
1.82k
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
137
1.82k
    }
lld::File::AtomRange<lld::AbsoluteAtom>::begin() const
Line
Count
Source
135
77
    ConstItTy begin() const {
136
77
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
137
77
    }
lld::File::AtomRange<lld::UndefinedAtom>::begin() const
Line
Count
Source
135
244
    ConstItTy begin() const {
136
244
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
137
244
    }
lld::File::AtomRange<lld::DefinedAtom>::begin() const
Line
Count
Source
135
1.24k
    ConstItTy begin() const {
136
1.24k
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
137
1.24k
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::begin() const
Line
Count
Source
135
260
    ConstItTy begin() const {
136
260
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
137
260
    }
138
1.82k
    ConstItTy end() const {
139
1.82k
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
140
1.82k
    }
lld::File::AtomRange<lld::DefinedAtom>::end() const
Line
Count
Source
138
1.24k
    ConstItTy end() const {
139
1.24k
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
140
1.24k
    }
lld::File::AtomRange<lld::UndefinedAtom>::end() const
Line
Count
Source
138
243
    ConstItTy end() const {
139
243
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
140
243
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::end() const
Line
Count
Source
138
260
    ConstItTy end() const {
139
260
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
140
260
    }
lld::File::AtomRange<lld::AbsoluteAtom>::end() const
Line
Count
Source
138
77
    ConstItTy end() const {
139
77
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
140
77
    }
141
142
240
    ItTy begin() {
143
240
      return ItTy(_v.begin(), DerefFn(Deref));
144
240
    }
lld::File::AtomRange<lld::AbsoluteAtom>::begin()
Line
Count
Source
142
60
    ItTy begin() {
143
60
      return ItTy(_v.begin(), DerefFn(Deref));
144
60
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::begin()
Line
Count
Source
142
60
    ItTy begin() {
143
60
      return ItTy(_v.begin(), DerefFn(Deref));
144
60
    }
lld::File::AtomRange<lld::UndefinedAtom>::begin()
Line
Count
Source
142
60
    ItTy begin() {
143
60
      return ItTy(_v.begin(), DerefFn(Deref));
144
60
    }
lld::File::AtomRange<lld::DefinedAtom>::begin()
Line
Count
Source
142
60
    ItTy begin() {
143
60
      return ItTy(_v.begin(), DerefFn(Deref));
144
60
    }
145
240
    ItTy end() {
146
240
      return ItTy(_v.end(), DerefFn(Deref));
147
240
    }
lld::File::AtomRange<lld::DefinedAtom>::end()
Line
Count
Source
145
60
    ItTy end() {
146
60
      return ItTy(_v.end(), DerefFn(Deref));
147
60
    }
lld::File::AtomRange<lld::AbsoluteAtom>::end()
Line
Count
Source
145
60
    ItTy end() {
146
60
      return ItTy(_v.end(), DerefFn(Deref));
147
60
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::end()
Line
Count
Source
145
60
    ItTy end() {
146
60
      return ItTy(_v.end(), DerefFn(Deref));
147
60
    }
lld::File::AtomRange<lld::UndefinedAtom>::end()
Line
Count
Source
145
60
    ItTy end() {
146
60
      return ItTy(_v.end(), DerefFn(Deref));
147
60
    }
148
149
168
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
150
168
      return llvm::make_range(_v.begin(), _v.end());
151
168
    }
152
153
2.49k
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
154
2.49k
      return llvm::make_range(_v.begin(), _v.end());
155
2.49k
    }
lld::File::AtomRange<lld::DefinedAtom>::owning_ptrs() const
Line
Count
Source
153
623
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
154
623
      return llvm::make_range(_v.begin(), _v.end());
155
623
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::owning_ptrs() const
Line
Count
Source
153
623
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
154
623
      return llvm::make_range(_v.begin(), _v.end());
155
623
    }
lld::File::AtomRange<lld::UndefinedAtom>::owning_ptrs() const
Line
Count
Source
153
623
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
154
623
      return llvm::make_range(_v.begin(), _v.end());
155
623
    }
lld::File::AtomRange<lld::AbsoluteAtom>::owning_ptrs() const
Line
Count
Source
153
623
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
154
623
      return llvm::make_range(_v.begin(), _v.end());
155
623
    }
156
157
    bool empty() const {
158
      return _v.empty();
159
    }
160
161
428
    size_t size() const {
162
428
      return _v.size();
163
428
    }
lld::File::AtomRange<lld::DefinedAtom>::size() const
Line
Count
Source
161
398
    size_t size() const {
162
398
      return _v.size();
163
398
    }
lld::File::AtomRange<lld::UndefinedAtom>::size() const
Line
Count
Source
161
23
    size_t size() const {
162
23
      return _v.size();
163
23
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::size() const
Line
Count
Source
161
7
    size_t size() const {
162
7
      return _v.size();
163
7
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::size() const
164
165
    const OwningAtomPtr<T> &operator[](size_t idx) const {
166
      return _v[idx];
167
    }
168
169
1.05k
    OwningAtomPtr<T> &operator[](size_t idx) {
170
1.05k
      return _v[idx];
171
1.05k
    }
lld::File::AtomRange<lld::DefinedAtom>::operator[](unsigned long)
Line
Count
Source
169
1.00k
    OwningAtomPtr<T> &operator[](size_t idx) {
170
1.00k
      return _v[idx];
171
1.00k
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::operator[](unsigned long)
lld::File::AtomRange<lld::SharedLibraryAtom>::operator[](unsigned long)
Line
Count
Source
169
11
    OwningAtomPtr<T> &operator[](size_t idx) {
170
11
      return _v[idx];
171
11
    }
lld::File::AtomRange<lld::UndefinedAtom>::operator[](unsigned long)
Line
Count
Source
169
41
    OwningAtomPtr<T> &operator[](size_t idx) {
170
41
      return _v[idx];
171
41
    }
172
173
  private:
174
    AtomVector<T> &_v;
175
  };
176
177
  /// \brief Must be implemented to return the AtomVector object for
178
  /// all DefinedAtoms in this File.
179
  virtual const AtomRange<DefinedAtom> defined() const = 0;
180
181
  /// \brief Must be implemented to return the AtomVector object for
182
  /// all UndefinedAtomw in this File.
183
  virtual const AtomRange<UndefinedAtom> undefined() const = 0;
184
185
  /// \brief Must be implemented to return the AtomVector object for
186
  /// all SharedLibraryAtoms in this File.
187
  virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
188
189
  /// \brief Must be implemented to return the AtomVector object for
190
  /// all AbsoluteAtoms in this File.
191
  virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
192
193
  /// Drop all of the atoms owned by this file.  This will result in all of
194
  /// the atoms running their destructors.
195
  /// This is required because atoms may be allocated on a BumpPtrAllocator
196
  /// of a different file.  We need to destruct all atoms before any files.
197
  virtual void clearAtoms() = 0;
198
199
  /// \brief If a file is parsed using a different method than doParse(),
200
  /// one must use this method to set the last error status, so that
201
  /// doParse will not be called twice. Only YAML reader uses this
202
  /// (because YAML reader does not read blobs but structured data).
203
275
  void setLastError(std::error_code err) { _lastError = err; }
204
205
  std::error_code parse();
206
207
  // Usually each file owns a std::unique_ptr<MemoryBuffer>.
208
  // However, there's one special case. If a file is an archive file,
209
  // the archive file and its children all shares the same memory buffer.
210
  // This method is used by the ArchiveFile to give its children
211
  // co-ownership of the buffer.
212
282
  void setSharedMemoryBuffer(std::shared_ptr<MemoryBuffer> mb) {
213
282
    _sharedMemoryBuffer = mb;
214
282
  }
215
216
protected:
217
  /// \brief only subclasses of File can be instantiated
218
  File(StringRef p, Kind kind)
219
    : _path(p), _kind(kind), _ordinal(UINT64_MAX),
220
1.32k
      _nextAtomOrdinal(0) {}
221
222
  /// \brief Subclasses should override this method to parse the
223
  /// memory buffer passed to this file's constructor.
224
321
  virtual std::error_code doParse() { return std::error_code(); }
225
226
  static AtomVector<DefinedAtom> _noDefinedAtoms;
227
  static AtomVector<UndefinedAtom> _noUndefinedAtoms;
228
  static AtomVector<SharedLibraryAtom> _noSharedLibraryAtoms;
229
  static AtomVector<AbsoluteAtom> _noAbsoluteAtoms;
230
  mutable llvm::BumpPtrAllocator _allocator;
231
232
private:
233
  StringRef _path;
234
  std::string _archivePath;
235
  mutable std::string _archiveMemberPath;
236
  Kind              _kind;
237
  mutable uint64_t  _ordinal;
238
  mutable uint64_t _nextAtomOrdinal;
239
  std::shared_ptr<MemoryBuffer> _sharedMemoryBuffer;
240
  llvm::Optional<std::error_code> _lastError;
241
  std::mutex _parseMutex;
242
};
243
244
/// An ErrorFile represents a file that doesn't exist.
245
/// If you try to parse a file which doesn't exist, an instance of this
246
/// class will be returned. That's parse method always returns an error.
247
/// This is useful to delay erroring on non-existent files, so that we
248
/// can do unit testing a driver using non-existing file paths.
249
class ErrorFile : public File {
250
public:
251
  ErrorFile(StringRef path, std::error_code ec)
252
64
      : File(path, kindErrorObject), _ec(ec) {}
253
254
6
  std::error_code doParse() override { return _ec; }
255
256
0
  const AtomRange<DefinedAtom> defined() const override {
257
0
    llvm_unreachable("internal error");
258
0
  }
259
0
  const AtomRange<UndefinedAtom> undefined() const override {
260
0
    llvm_unreachable("internal error");
261
0
  }
262
0
  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
263
0
    llvm_unreachable("internal error");
264
0
  }
265
0
  const AtomRange<AbsoluteAtom> absolute() const override {
266
0
    llvm_unreachable("internal error");
267
0
  }
268
269
64
  void clearAtoms() override {
270
64
  }
271
272
private:
273
  std::error_code _ec;
274
};
275
276
} // end namespace lld
277
278
#endif