Coverage Report

Created: 2018-08-19 21:11

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/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
  /// 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
  /// Returns file kind.  Need for dyn_cast<> on File objects.
63
6.42k
  Kind kind() const {
64
6.42k
    return _kind;
65
6.42k
  }
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 (_archiveMemberPath.empty())
74
1
      _archiveMemberPath = (_archivePath + "(" + _path + ")").str();
75
6
    return _archiveMemberPath;
76
6
  }
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
487
    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
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
122
    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
122
    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
122
    AtomRange(AtomVector<T> &v) : _v(v) {}
115
3.84k
    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
790
    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
823
    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
    using ConstDerefFn = const T* (*)(const OwningAtomPtr<T>&);
118
    using DerefFn = T* (*)(OwningAtomPtr<T>&);
119
120
    typedef llvm::mapped_iterator<typename AtomVector<T>::const_iterator,
121
                                  ConstDerefFn> ConstItTy;
122
    typedef llvm::mapped_iterator<typename AtomVector<T>::iterator,
123
                                  DerefFn> ItTy;
124
125
6.06k
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
126
6.06k
      return p.get();
127
6.06k
    }
lld::File::AtomRange<lld::DefinedAtom>::DerefConst(lld::OwningAtomPtr<lld::DefinedAtom> const&)
Line
Count
Source
125
5.77k
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
126
5.77k
      return p.get();
127
5.77k
    }
lld::File::AtomRange<lld::UndefinedAtom>::DerefConst(lld::OwningAtomPtr<lld::UndefinedAtom> const&)
Line
Count
Source
125
93
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
126
93
      return p.get();
127
93
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::DerefConst(lld::OwningAtomPtr<lld::SharedLibraryAtom> const&)
Line
Count
Source
125
204
    static const T* DerefConst(const OwningAtomPtr<T> &p) {
126
204
      return p.get();
127
204
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::DerefConst(lld::OwningAtomPtr<lld::AbsoluteAtom> const&)
128
129
0
    static T* Deref(OwningAtomPtr<T> &p) {
130
0
      return p.get();
131
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>&)
132
133
1.83k
    ConstItTy begin() const {
134
1.83k
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
135
1.83k
    }
lld::File::AtomRange<lld::DefinedAtom>::begin() const
Line
Count
Source
133
1.24k
    ConstItTy begin() const {
134
1.24k
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
135
1.24k
    }
lld::File::AtomRange<lld::UndefinedAtom>::begin() const
Line
Count
Source
133
246
    ConstItTy begin() const {
134
246
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
135
246
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::begin() const
Line
Count
Source
133
262
    ConstItTy begin() const {
134
262
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
135
262
    }
lld::File::AtomRange<lld::AbsoluteAtom>::begin() const
Line
Count
Source
133
78
    ConstItTy begin() const {
134
78
      return ConstItTy(_v.begin(), ConstDerefFn(DerefConst));
135
78
    }
136
1.83k
    ConstItTy end() const {
137
1.83k
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
138
1.83k
    }
lld::File::AtomRange<lld::DefinedAtom>::end() const
Line
Count
Source
136
1.24k
    ConstItTy end() const {
137
1.24k
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
138
1.24k
    }
lld::File::AtomRange<lld::UndefinedAtom>::end() const
Line
Count
Source
136
245
    ConstItTy end() const {
137
245
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
138
245
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::end() const
Line
Count
Source
136
262
    ConstItTy end() const {
137
262
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
138
262
    }
lld::File::AtomRange<lld::AbsoluteAtom>::end() const
Line
Count
Source
136
78
    ConstItTy end() const {
137
78
      return ConstItTy(_v.end(), ConstDerefFn(DerefConst));
138
78
    }
139
140
240
    ItTy begin() {
141
240
      return ItTy(_v.begin(), DerefFn(Deref));
142
240
    }
lld::File::AtomRange<lld::DefinedAtom>::begin()
Line
Count
Source
140
60
    ItTy begin() {
141
60
      return ItTy(_v.begin(), DerefFn(Deref));
142
60
    }
lld::File::AtomRange<lld::UndefinedAtom>::begin()
Line
Count
Source
140
60
    ItTy begin() {
141
60
      return ItTy(_v.begin(), DerefFn(Deref));
142
60
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::begin()
Line
Count
Source
140
60
    ItTy begin() {
141
60
      return ItTy(_v.begin(), DerefFn(Deref));
142
60
    }
lld::File::AtomRange<lld::AbsoluteAtom>::begin()
Line
Count
Source
140
60
    ItTy begin() {
141
60
      return ItTy(_v.begin(), DerefFn(Deref));
142
60
    }
143
240
    ItTy end() {
144
240
      return ItTy(_v.end(), DerefFn(Deref));
145
240
    }
lld::File::AtomRange<lld::DefinedAtom>::end()
Line
Count
Source
143
60
    ItTy end() {
144
60
      return ItTy(_v.end(), DerefFn(Deref));
145
60
    }
lld::File::AtomRange<lld::UndefinedAtom>::end()
Line
Count
Source
143
60
    ItTy end() {
144
60
      return ItTy(_v.end(), DerefFn(Deref));
145
60
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::end()
Line
Count
Source
143
60
    ItTy end() {
144
60
      return ItTy(_v.end(), DerefFn(Deref));
145
60
    }
lld::File::AtomRange<lld::AbsoluteAtom>::end()
Line
Count
Source
143
60
    ItTy end() {
144
60
      return ItTy(_v.end(), DerefFn(Deref));
145
60
    }
146
147
169
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() {
148
169
      return llvm::make_range(_v.begin(), _v.end());
149
169
    }
150
151
2.49k
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
152
2.49k
      return llvm::make_range(_v.begin(), _v.end());
153
2.49k
    }
lld::File::AtomRange<lld::DefinedAtom>::owning_ptrs() const
Line
Count
Source
151
624
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
152
624
      return llvm::make_range(_v.begin(), _v.end());
153
624
    }
lld::File::AtomRange<lld::UndefinedAtom>::owning_ptrs() const
Line
Count
Source
151
624
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
152
624
      return llvm::make_range(_v.begin(), _v.end());
153
624
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::owning_ptrs() const
Line
Count
Source
151
624
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
152
624
      return llvm::make_range(_v.begin(), _v.end());
153
624
    }
lld::File::AtomRange<lld::AbsoluteAtom>::owning_ptrs() const
Line
Count
Source
151
624
    llvm::iterator_range<typename AtomVector<T>::iterator> owning_ptrs() const {
152
624
      return llvm::make_range(_v.begin(), _v.end());
153
624
    }
154
155
    bool empty() const {
156
      return _v.empty();
157
    }
158
159
430
    size_t size() const {
160
430
      return _v.size();
161
430
    }
lld::File::AtomRange<lld::DefinedAtom>::size() const
Line
Count
Source
159
400
    size_t size() const {
160
400
      return _v.size();
161
400
    }
lld::File::AtomRange<lld::UndefinedAtom>::size() const
Line
Count
Source
159
23
    size_t size() const {
160
23
      return _v.size();
161
23
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::size() const
Line
Count
Source
159
7
    size_t size() const {
160
7
      return _v.size();
161
7
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::size() const
162
163
    const OwningAtomPtr<T> &operator[](size_t idx) const {
164
      return _v[idx];
165
    }
166
167
1.05k
    OwningAtomPtr<T> &operator[](size_t idx) {
168
1.05k
      return _v[idx];
169
1.05k
    }
lld::File::AtomRange<lld::DefinedAtom>::operator[](unsigned long)
Line
Count
Source
167
1.00k
    OwningAtomPtr<T> &operator[](size_t idx) {
168
1.00k
      return _v[idx];
169
1.00k
    }
lld::File::AtomRange<lld::UndefinedAtom>::operator[](unsigned long)
Line
Count
Source
167
41
    OwningAtomPtr<T> &operator[](size_t idx) {
168
41
      return _v[idx];
169
41
    }
lld::File::AtomRange<lld::SharedLibraryAtom>::operator[](unsigned long)
Line
Count
Source
167
11
    OwningAtomPtr<T> &operator[](size_t idx) {
168
11
      return _v[idx];
169
11
    }
Unexecuted instantiation: lld::File::AtomRange<lld::AbsoluteAtom>::operator[](unsigned long)
170
171
  private:
172
    AtomVector<T> &_v;
173
  };
174
175
  /// Must be implemented to return the AtomVector object for
176
  /// all DefinedAtoms in this File.
177
  virtual const AtomRange<DefinedAtom> defined() const = 0;
178
179
  /// Must be implemented to return the AtomVector object for
180
  /// all UndefinedAtomw in this File.
181
  virtual const AtomRange<UndefinedAtom> undefined() const = 0;
182
183
  /// Must be implemented to return the AtomVector object for
184
  /// all SharedLibraryAtoms in this File.
185
  virtual const AtomRange<SharedLibraryAtom> sharedLibrary() const = 0;
186
187
  /// Must be implemented to return the AtomVector object for
188
  /// all AbsoluteAtoms in this File.
189
  virtual const AtomRange<AbsoluteAtom> absolute() const = 0;
190
191
  /// Drop all of the atoms owned by this file.  This will result in all of
192
  /// the atoms running their destructors.
193
  /// This is required because atoms may be allocated on a BumpPtrAllocator
194
  /// of a different file.  We need to destruct all atoms before any files.
195
  virtual void clearAtoms() = 0;
196
197
  /// If a file is parsed using a different method than doParse(),
198
  /// one must use this method to set the last error status, so that
199
  /// doParse will not be called twice. Only YAML reader uses this
200
  /// (because YAML reader does not read blobs but structured data).
201
276
  void setLastError(std::error_code err) { _lastError = err; }
202
203
  std::error_code parse();
204
205
  // Usually each file owns a std::unique_ptr<MemoryBuffer>.
206
  // However, there's one special case. If a file is an archive file,
207
  // the archive file and its children all shares the same memory buffer.
208
  // This method is used by the ArchiveFile to give its children
209
  // co-ownership of the buffer.
210
283
  void setSharedMemoryBuffer(std::shared_ptr<MemoryBuffer> mb) {
211
283
    _sharedMemoryBuffer = mb;
212
283
  }
213
214
protected:
215
  /// only subclasses of File can be instantiated
216
  File(StringRef p, Kind kind)
217
    : _path(p), _kind(kind), _ordinal(UINT64_MAX),
218
1.32k
      _nextAtomOrdinal(0) {}
219
220
  /// Subclasses should override this method to parse the
221
  /// memory buffer passed to this file's constructor.
222
321
  virtual std::error_code doParse() { return std::error_code(); }
223
224
  static AtomVector<DefinedAtom> _noDefinedAtoms;
225
  static AtomVector<UndefinedAtom> _noUndefinedAtoms;
226
  static AtomVector<SharedLibraryAtom> _noSharedLibraryAtoms;
227
  static AtomVector<AbsoluteAtom> _noAbsoluteAtoms;
228
  mutable llvm::BumpPtrAllocator _allocator;
229
230
private:
231
  StringRef _path;
232
  std::string _archivePath;
233
  mutable std::string _archiveMemberPath;
234
  Kind              _kind;
235
  mutable uint64_t  _ordinal;
236
  mutable uint64_t _nextAtomOrdinal;
237
  std::shared_ptr<MemoryBuffer> _sharedMemoryBuffer;
238
  llvm::Optional<std::error_code> _lastError;
239
  std::mutex _parseMutex;
240
};
241
242
/// An ErrorFile represents a file that doesn't exist.
243
/// If you try to parse a file which doesn't exist, an instance of this
244
/// class will be returned. That's parse method always returns an error.
245
/// This is useful to delay erroring on non-existent files, so that we
246
/// can do unit testing a driver using non-existing file paths.
247
class ErrorFile : public File {
248
public:
249
  ErrorFile(StringRef path, std::error_code ec)
250
64
      : File(path, kindErrorObject), _ec(ec) {}
251
252
6
  std::error_code doParse() override { return _ec; }
253
254
0
  const AtomRange<DefinedAtom> defined() const override {
255
0
    llvm_unreachable("internal error");
256
0
  }
257
0
  const AtomRange<UndefinedAtom> undefined() const override {
258
0
    llvm_unreachable("internal error");
259
0
  }
260
0
  const AtomRange<SharedLibraryAtom> sharedLibrary() const override {
261
0
    llvm_unreachable("internal error");
262
0
  }
263
0
  const AtomRange<AbsoluteAtom> absolute() const override {
264
0
    llvm_unreachable("internal error");
265
0
  }
266
267
64
  void clearAtoms() override {
268
64
  }
269
270
private:
271
  std::error_code _ec;
272
};
273
274
} // end namespace lld
275
276
#endif