Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Core/ModuleSpec.h
Line
Count
Source (jump to first uncovered line)
1
//===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
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 LLDB_CORE_MODULESPEC_H
10
#define LLDB_CORE_MODULESPEC_H
11
12
#include "lldb/Host/FileSystem.h"
13
#include "lldb/Target/PathMappingList.h"
14
#include "lldb/Utility/ArchSpec.h"
15
#include "lldb/Utility/FileSpec.h"
16
#include "lldb/Utility/Iterable.h"
17
#include "lldb/Utility/Stream.h"
18
#include "lldb/Utility/UUID.h"
19
20
#include "llvm/Support/Chrono.h"
21
22
#include <mutex>
23
#include <vector>
24
25
namespace lldb_private {
26
27
class ModuleSpec {
28
public:
29
715k
  ModuleSpec() = default;
30
31
  /// If the \c data argument is passed, its contents will be used
32
  /// as the module contents instead of trying to read them from
33
  /// \c file_spec .
34
  ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(),
35
             lldb::DataBufferSP data = lldb::DataBufferSP())
36
445k
      : m_file(file_spec), m_uuid(uuid), m_object_offset(0), m_data(data) {
37
445k
    if (data)
38
210k
      m_object_size = data->GetByteSize();
39
235k
    else if (m_file)
40
235k
      m_object_size = FileSystem::Instance().GetByteSize(file_spec);
41
445k
  }
42
43
  ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
44
342k
      : m_file(file_spec), m_arch(arch), m_object_offset(0),
45
342k
        m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {}
46
47
38
  FileSpec *GetFileSpecPtr() { return (m_file ? 
&m_file24
:
nullptr14
); }
48
49
116k
  const FileSpec *GetFileSpecPtr() const {
50
116k
    return (m_file ? 
&m_file112k
:
nullptr4.15k
);
51
116k
  }
52
53
363k
  FileSpec &GetFileSpec() { return m_file; }
54
55
9.48M
  const FileSpec &GetFileSpec() const { return m_file; }
56
57
0
  FileSpec *GetPlatformFileSpecPtr() {
58
0
    return (m_platform_file ? &m_platform_file : nullptr);
59
0
  }
60
61
0
  const FileSpec *GetPlatformFileSpecPtr() const {
62
0
    return (m_platform_file ? &m_platform_file : nullptr);
63
0
  }
64
65
224k
  FileSpec &GetPlatformFileSpec() { return m_platform_file; }
66
67
228k
  const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
68
69
0
  FileSpec *GetSymbolFileSpecPtr() {
70
0
    return (m_symbol_file ? &m_symbol_file : nullptr);
71
0
  }
72
73
0
  const FileSpec *GetSymbolFileSpecPtr() const {
74
0
    return (m_symbol_file ? &m_symbol_file : nullptr);
75
0
  }
76
77
235k
  FileSpec &GetSymbolFileSpec() { return m_symbol_file; }
78
79
341k
  const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
80
81
1.42k
  ArchSpec *GetArchitecturePtr() {
82
1.42k
    return (m_arch.IsValid() ? &m_arch : 
nullptr0
);
83
1.42k
  }
84
85
232k
  const ArchSpec *GetArchitecturePtr() const {
86
232k
    return (m_arch.IsValid() ? 
&m_arch124k
:
nullptr107k
);
87
232k
  }
88
89
2.81M
  ArchSpec &GetArchitecture() { return m_arch; }
90
91
368k
  const ArchSpec &GetArchitecture() const { return m_arch; }
92
93
1.46k
  UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : 
nullptr0
); }
94
95
462k
  const UUID *GetUUIDPtr() const {
96
462k
    return (m_uuid.IsValid() ? 
&m_uuid435k
:
nullptr26.4k
);
97
462k
  }
98
99
1.42M
  UUID &GetUUID() { return m_uuid; }
100
101
27.6M
  const UUID &GetUUID() const { return m_uuid; }
102
103
112k
  ConstString &GetObjectName() { return m_object_name; }
104
105
228k
  ConstString GetObjectName() const { return m_object_name; }
106
107
112k
  uint64_t GetObjectOffset() const { return m_object_offset; }
108
109
118k
  void SetObjectOffset(uint64_t object_offset) {
110
118k
    m_object_offset = object_offset;
111
118k
  }
112
113
33
  uint64_t GetObjectSize() const { return m_object_size; }
114
115
118k
  void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
116
117
112k
  llvm::sys::TimePoint<> &GetObjectModificationTime() {
118
112k
    return m_object_mod_time;
119
112k
  }
120
121
0
  const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
122
0
    return m_object_mod_time;
123
0
  }
124
125
112k
  PathMappingList &GetSourceMappingList() const { return m_source_mappings; }
126
127
226k
  lldb::DataBufferSP GetData() const { return m_data; }
128
129
352
  void Clear() {
130
352
    m_file.Clear();
131
352
    m_platform_file.Clear();
132
352
    m_symbol_file.Clear();
133
352
    m_arch.Clear();
134
352
    m_uuid.Clear();
135
352
    m_object_name.Clear();
136
352
    m_object_offset = 0;
137
352
    m_object_size = 0;
138
352
    m_source_mappings.Clear(false);
139
352
    m_object_mod_time = llvm::sys::TimePoint<>();
140
352
  }
141
142
0
  explicit operator bool() const {
143
0
    if (m_file)
144
0
      return true;
145
0
    if (m_platform_file)
146
0
      return true;
147
0
    if (m_symbol_file)
148
0
      return true;
149
0
    if (m_arch.IsValid())
150
0
      return true;
151
0
    if (m_uuid.IsValid())
152
0
      return true;
153
0
    if (m_object_name)
154
0
      return true;
155
0
    if (m_object_size)
156
0
      return true;
157
0
    if (m_object_mod_time != llvm::sys::TimePoint<>())
158
0
      return true;
159
0
    return false;
160
0
  }
161
162
46
  void Dump(Stream &strm) const {
163
46
    bool dumped_something = false;
164
46
    if (m_file) {
165
0
      strm.PutCString("file = '");
166
0
      strm << m_file;
167
0
      strm.PutCString("'");
168
0
      dumped_something = true;
169
0
    }
170
46
    if (m_platform_file) {
171
0
      if (dumped_something)
172
0
        strm.PutCString(", ");
173
0
      strm.PutCString("platform_file = '");
174
0
      strm << m_platform_file;
175
0
      strm.PutCString("'");
176
0
      dumped_something = true;
177
0
    }
178
46
    if (m_symbol_file) {
179
0
      if (dumped_something)
180
0
        strm.PutCString(", ");
181
0
      strm.PutCString("symbol_file = '");
182
0
      strm << m_symbol_file;
183
0
      strm.PutCString("'");
184
0
      dumped_something = true;
185
0
    }
186
46
    if (m_arch.IsValid()) {
187
46
      if (dumped_something)
188
0
        strm.PutCString(", ");
189
46
      strm.Printf("arch = ");
190
46
      m_arch.DumpTriple(strm.AsRawOstream());
191
46
      dumped_something = true;
192
46
    }
193
46
    if (m_uuid.IsValid()) {
194
0
      if (dumped_something)
195
0
        strm.PutCString(", ");
196
0
      strm.PutCString("uuid = ");
197
0
      m_uuid.Dump(strm);
198
0
      dumped_something = true;
199
0
    }
200
46
    if (m_object_name) {
201
0
      if (dumped_something)
202
0
        strm.PutCString(", ");
203
0
      strm.Printf("object_name = %s", m_object_name.GetCString());
204
0
      dumped_something = true;
205
0
    }
206
46
    if (m_object_offset > 0) {
207
0
      if (dumped_something)
208
0
        strm.PutCString(", ");
209
0
      strm.Printf("object_offset = %" PRIu64, m_object_offset);
210
0
      dumped_something = true;
211
0
    }
212
46
    if (m_object_size > 0) {
213
0
      if (dumped_something)
214
0
        strm.PutCString(", ");
215
0
      strm.Printf("object size = %" PRIu64, m_object_size);
216
0
      dumped_something = true;
217
0
    }
218
46
    if (m_object_mod_time != llvm::sys::TimePoint<>()) {
219
0
      if (dumped_something)
220
0
        strm.PutCString(", ");
221
0
      strm.Format("object_mod_time = {0:x+}",
222
0
                  uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
223
0
    }
224
46
  }
225
226
  bool Matches(const ModuleSpec &match_module_spec,
227
112k
               bool exact_arch_match) const {
228
112k
    if (match_module_spec.GetUUIDPtr() &&
229
112k
        
match_module_spec.GetUUID() != GetUUID()103k
)
230
60
      return false;
231
112k
    if (match_module_spec.GetObjectName() &&
232
112k
        
match_module_spec.GetObjectName() != GetObjectName()0
)
233
0
      return false;
234
112k
    if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec()))
235
0
      return false;
236
112k
    if (GetPlatformFileSpec() &&
237
112k
        !FileSpec::Match(match_module_spec.GetPlatformFileSpec(),
238
0
                         GetPlatformFileSpec())) {
239
0
      return false;
240
0
    }
241
    // Only match the symbol file spec if there is one in this ModuleSpec
242
112k
    if (GetSymbolFileSpec() &&
243
112k
        !FileSpec::Match(match_module_spec.GetSymbolFileSpec(),
244
0
                         GetSymbolFileSpec())) {
245
0
      return false;
246
0
    }
247
112k
    if (match_module_spec.GetArchitecturePtr()) {
248
9.41k
      if (exact_arch_match) {
249
9.36k
        if (!GetArchitecture().IsExactMatch(
250
9.36k
                match_module_spec.GetArchitecture()))
251
114
          return false;
252
9.36k
      } else {
253
45
        if (!GetArchitecture().IsCompatibleMatch(
254
45
                match_module_spec.GetArchitecture()))
255
42
          return false;
256
45
      }
257
9.41k
    }
258
112k
    return true;
259
112k
  }
260
261
protected:
262
  FileSpec m_file;
263
  FileSpec m_platform_file;
264
  FileSpec m_symbol_file;
265
  ArchSpec m_arch;
266
  UUID m_uuid;
267
  ConstString m_object_name;
268
  uint64_t m_object_offset = 0;
269
  uint64_t m_object_size = 0;
270
  llvm::sys::TimePoint<> m_object_mod_time;
271
  mutable PathMappingList m_source_mappings;
272
  lldb::DataBufferSP m_data = {};
273
};
274
275
class ModuleSpecList {
276
public:
277
474k
  ModuleSpecList() = default;
278
279
3
  ModuleSpecList(const ModuleSpecList &rhs) {
280
3
    std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
281
3
    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
282
3
    m_specs = rhs.m_specs;
283
3
  }
284
285
474k
  ~ModuleSpecList() = default;
286
287
3
  ModuleSpecList &operator=(const ModuleSpecList &rhs) {
288
3
    if (this != &rhs) {
289
3
      std::lock(m_mutex, rhs.m_mutex);
290
3
      std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
291
3
      std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex,
292
3
                                                      std::adopt_lock);
293
3
      m_specs = rhs.m_specs;
294
3
    }
295
3
    return *this;
296
3
  }
297
298
1.09M
  size_t GetSize() const {
299
1.09M
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
300
1.09M
    return m_specs.size();
301
1.09M
  }
302
303
2.33k
  void Clear() {
304
2.33k
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
305
2.33k
    m_specs.clear();
306
2.33k
  }
307
308
875k
  void Append(const ModuleSpec &spec) {
309
875k
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
310
875k
    m_specs.push_back(spec);
311
875k
  }
312
313
0
  void Append(const ModuleSpecList &rhs) {
314
0
    std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
315
0
    std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
316
0
    m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
317
0
  }
318
319
  // The index "i" must be valid and this can't be used in multi-threaded code
320
  // as no mutex lock is taken.
321
355k
  ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
322
323
3.97k
  bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
324
3.97k
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
325
3.97k
    if (i < m_specs.size()) {
326
3.97k
      module_spec = m_specs[i];
327
3.97k
      return true;
328
3.97k
    }
329
0
    module_spec.Clear();
330
0
    return false;
331
3.97k
  }
332
333
  bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
334
112k
                              ModuleSpec &match_module_spec) const {
335
112k
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
336
112k
    bool exact_arch_match = true;
337
112k
    for (auto spec : m_specs) {
338
112k
      if (spec.Matches(module_spec, exact_arch_match)) {
339
112k
        match_module_spec = spec;
340
112k
        return true;
341
112k
      }
342
112k
    }
343
344
    // If there was an architecture, retry with a compatible arch
345
49
    if (module_spec.GetArchitecturePtr()) {
346
41
      exact_arch_match = false;
347
65
      for (auto spec : m_specs) {
348
65
        if (spec.Matches(module_spec, exact_arch_match)) {
349
3
          match_module_spec = spec;
350
3
          return true;
351
3
        }
352
65
      }
353
41
    }
354
46
    match_module_spec.Clear();
355
46
    return false;
356
49
  }
357
358
  void FindMatchingModuleSpecs(const ModuleSpec &module_spec,
359
0
                               ModuleSpecList &matching_list) const {
360
0
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
361
0
    bool exact_arch_match = true;
362
0
    const size_t initial_match_count = matching_list.GetSize();
363
0
    for (auto spec : m_specs) {
364
0
      if (spec.Matches(module_spec, exact_arch_match))
365
0
        matching_list.Append(spec);
366
0
    }
367
0
368
0
    // If there was an architecture, retry with a compatible arch if no matches
369
0
    // were found
370
0
    if (module_spec.GetArchitecturePtr() &&
371
0
        (initial_match_count == matching_list.GetSize())) {
372
0
      exact_arch_match = false;
373
0
      for (auto spec : m_specs) {
374
0
        if (spec.Matches(module_spec, exact_arch_match))
375
0
          matching_list.Append(spec);
376
0
      }
377
0
    }
378
0
  }
379
380
0
  void Dump(Stream &strm) {
381
0
    std::lock_guard<std::recursive_mutex> guard(m_mutex);
382
0
    uint32_t idx = 0;
383
0
    for (auto spec : m_specs) {
384
0
      strm.Printf("[%u] ", idx);
385
0
      spec.Dump(strm);
386
0
      strm.EOL();
387
0
      ++idx;
388
0
    }
389
0
  }
390
391
  typedef std::vector<ModuleSpec> collection;
392
  typedef LockingAdaptedIterable<collection, ModuleSpec, vector_adapter,
393
                                 std::recursive_mutex>
394
      ModuleSpecIterable;
395
396
3
  ModuleSpecIterable ModuleSpecs() {
397
3
    return ModuleSpecIterable(m_specs, m_mutex);
398
3
  }
399
400
protected:
401
  collection m_specs;                         ///< The collection of modules.
402
  mutable std::recursive_mutex m_mutex;
403
};
404
405
} // namespace lldb_private
406
407
#endif // LLDB_CORE_MODULESPEC_H