Coverage Report

Created: 2019-07-24 05:18

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