Coverage Report

Created: 2022-01-18 06:27

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