1 //===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef liblldb_ModuleSpec_h_
10 #define liblldb_ModuleSpec_h_
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"
19 #include "llvm/Support/Chrono.h"
24 namespace lldb_private {
29 : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(),
30 m_object_name(), m_object_offset(0), m_object_size(0),
31 m_source_mappings() {}
33 ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID())
34 : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
35 m_uuid(uuid), m_object_name(), m_object_offset(0),
36 m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
37 m_source_mappings() {}
39 ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
40 : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch),
41 m_uuid(), m_object_name(), m_object_offset(0),
42 m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
43 m_source_mappings() {}
45 ModuleSpec(const ModuleSpec &rhs)
46 : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file),
47 m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch),
48 m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name),
49 m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size),
50 m_object_mod_time(rhs.m_object_mod_time),
51 m_source_mappings(rhs.m_source_mappings) {}
53 ModuleSpec &operator=(const ModuleSpec &rhs) {
56 m_platform_file = rhs.m_platform_file;
57 m_symbol_file = rhs.m_symbol_file;
60 m_object_name = rhs.m_object_name;
61 m_object_offset = rhs.m_object_offset;
62 m_object_size = rhs.m_object_size;
63 m_object_mod_time = rhs.m_object_mod_time;
64 m_source_mappings = rhs.m_source_mappings;
69 FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }
71 const FileSpec *GetFileSpecPtr() const {
72 return (m_file ? &m_file : nullptr);
75 FileSpec &GetFileSpec() { return m_file; }
77 const FileSpec &GetFileSpec() const { return m_file; }
79 FileSpec *GetPlatformFileSpecPtr() {
80 return (m_platform_file ? &m_platform_file : nullptr);
83 const FileSpec *GetPlatformFileSpecPtr() const {
84 return (m_platform_file ? &m_platform_file : nullptr);
87 FileSpec &GetPlatformFileSpec() { return m_platform_file; }
89 const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
91 FileSpec *GetSymbolFileSpecPtr() {
92 return (m_symbol_file ? &m_symbol_file : nullptr);
95 const FileSpec *GetSymbolFileSpecPtr() const {
96 return (m_symbol_file ? &m_symbol_file : nullptr);
99 FileSpec &GetSymbolFileSpec() { return m_symbol_file; }
101 const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
103 ArchSpec *GetArchitecturePtr() {
104 return (m_arch.IsValid() ? &m_arch : nullptr);
107 const ArchSpec *GetArchitecturePtr() const {
108 return (m_arch.IsValid() ? &m_arch : nullptr);
111 ArchSpec &GetArchitecture() { return m_arch; }
113 const ArchSpec &GetArchitecture() const { return m_arch; }
115 UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); }
117 const UUID *GetUUIDPtr() const {
118 return (m_uuid.IsValid() ? &m_uuid : nullptr);
121 UUID &GetUUID() { return m_uuid; }
123 const UUID &GetUUID() const { return m_uuid; }
125 ConstString &GetObjectName() { return m_object_name; }
127 ConstString GetObjectName() const { return m_object_name; }
129 uint64_t GetObjectOffset() const { return m_object_offset; }
131 void SetObjectOffset(uint64_t object_offset) {
132 m_object_offset = object_offset;
135 uint64_t GetObjectSize() const { return m_object_size; }
137 void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
139 llvm::sys::TimePoint<> &GetObjectModificationTime() {
140 return m_object_mod_time;
143 const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
144 return m_object_mod_time;
147 PathMappingList &GetSourceMappingList() const { return m_source_mappings; }
151 m_platform_file.Clear();
152 m_symbol_file.Clear();
155 m_object_name.Clear();
158 m_source_mappings.Clear(false);
159 m_object_mod_time = llvm::sys::TimePoint<>();
162 explicit operator bool() const {
169 if (m_arch.IsValid())
171 if (m_uuid.IsValid())
177 if (m_object_mod_time != llvm::sys::TimePoint<>())
182 void Dump(Stream &strm) const {
183 bool dumped_something = false;
185 strm.PutCString("file = '");
187 strm.PutCString("'");
188 dumped_something = true;
190 if (m_platform_file) {
191 if (dumped_something)
192 strm.PutCString(", ");
193 strm.PutCString("platform_file = '");
194 strm << m_platform_file;
195 strm.PutCString("'");
196 dumped_something = true;
199 if (dumped_something)
200 strm.PutCString(", ");
201 strm.PutCString("symbol_file = '");
202 strm << m_symbol_file;
203 strm.PutCString("'");
204 dumped_something = true;
206 if (m_arch.IsValid()) {
207 if (dumped_something)
208 strm.PutCString(", ");
209 strm.Printf("arch = ");
210 m_arch.DumpTriple(strm);
211 dumped_something = true;
213 if (m_uuid.IsValid()) {
214 if (dumped_something)
215 strm.PutCString(", ");
216 strm.PutCString("uuid = ");
218 dumped_something = true;
221 if (dumped_something)
222 strm.PutCString(", ");
223 strm.Printf("object_name = %s", m_object_name.GetCString());
224 dumped_something = true;
226 if (m_object_offset > 0) {
227 if (dumped_something)
228 strm.PutCString(", ");
229 strm.Printf("object_offset = %" PRIu64, m_object_offset);
230 dumped_something = true;
232 if (m_object_size > 0) {
233 if (dumped_something)
234 strm.PutCString(", ");
235 strm.Printf("object size = %" PRIu64, m_object_size);
236 dumped_something = true;
238 if (m_object_mod_time != llvm::sys::TimePoint<>()) {
239 if (dumped_something)
240 strm.PutCString(", ");
241 strm.Format("object_mod_time = {0:x+}",
242 uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
246 bool Matches(const ModuleSpec &match_module_spec,
247 bool exact_arch_match) const {
248 if (match_module_spec.GetUUIDPtr() &&
249 match_module_spec.GetUUID() != GetUUID())
251 if (match_module_spec.GetObjectName() &&
252 match_module_spec.GetObjectName() != GetObjectName())
254 if (match_module_spec.GetFileSpecPtr()) {
255 const FileSpec &fspec = match_module_spec.GetFileSpec();
256 if (!FileSpec::Equal(fspec, GetFileSpec(),
257 !fspec.GetDirectory().IsEmpty()))
260 if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) {
261 const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
262 if (!FileSpec::Equal(fspec, GetPlatformFileSpec(),
263 !fspec.GetDirectory().IsEmpty()))
266 // Only match the symbol file spec if there is one in this ModuleSpec
267 if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) {
268 const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
269 if (!FileSpec::Equal(fspec, GetSymbolFileSpec(),
270 !fspec.GetDirectory().IsEmpty()))
273 if (match_module_spec.GetArchitecturePtr()) {
274 if (exact_arch_match) {
275 if (!GetArchitecture().IsExactMatch(
276 match_module_spec.GetArchitecture()))
279 if (!GetArchitecture().IsCompatibleMatch(
280 match_module_spec.GetArchitecture()))
289 FileSpec m_platform_file;
290 FileSpec m_symbol_file;
293 ConstString m_object_name;
294 uint64_t m_object_offset;
295 uint64_t m_object_size;
296 llvm::sys::TimePoint<> m_object_mod_time;
297 mutable PathMappingList m_source_mappings;
300 class ModuleSpecList {
302 ModuleSpecList() : m_specs(), m_mutex() {}
304 ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() {
305 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
306 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
307 m_specs = rhs.m_specs;
310 ~ModuleSpecList() = default;
312 ModuleSpecList &operator=(const ModuleSpecList &rhs) {
314 std::lock(m_mutex, rhs.m_mutex);
315 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
316 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex,
318 m_specs = rhs.m_specs;
323 size_t GetSize() const {
324 std::lock_guard<std::recursive_mutex> guard(m_mutex);
325 return m_specs.size();
329 std::lock_guard<std::recursive_mutex> guard(m_mutex);
333 void Append(const ModuleSpec &spec) {
334 std::lock_guard<std::recursive_mutex> guard(m_mutex);
335 m_specs.push_back(spec);
338 void Append(const ModuleSpecList &rhs) {
339 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
340 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
341 m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
344 // The index "i" must be valid and this can't be used in multi-threaded code
345 // as no mutex lock is taken.
346 ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
348 bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
349 std::lock_guard<std::recursive_mutex> guard(m_mutex);
350 if (i < m_specs.size()) {
351 module_spec = m_specs[i];
358 bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
359 ModuleSpec &match_module_spec) const {
360 std::lock_guard<std::recursive_mutex> guard(m_mutex);
361 bool exact_arch_match = true;
362 for (auto spec : m_specs) {
363 if (spec.Matches(module_spec, exact_arch_match)) {
364 match_module_spec = spec;
369 // If there was an architecture, retry with a compatible arch
370 if (module_spec.GetArchitecturePtr()) {
371 exact_arch_match = false;
372 for (auto spec : m_specs) {
373 if (spec.Matches(module_spec, exact_arch_match)) {
374 match_module_spec = spec;
379 match_module_spec.Clear();
383 size_t FindMatchingModuleSpecs(const ModuleSpec &module_spec,
384 ModuleSpecList &matching_list) const {
385 std::lock_guard<std::recursive_mutex> guard(m_mutex);
386 bool exact_arch_match = true;
387 const size_t initial_match_count = matching_list.GetSize();
388 for (auto spec : m_specs) {
389 if (spec.Matches(module_spec, exact_arch_match))
390 matching_list.Append(spec);
393 // If there was an architecture, retry with a compatible arch if no matches
395 if (module_spec.GetArchitecturePtr() &&
396 (initial_match_count == matching_list.GetSize())) {
397 exact_arch_match = false;
398 for (auto spec : m_specs) {
399 if (spec.Matches(module_spec, exact_arch_match))
400 matching_list.Append(spec);
403 return matching_list.GetSize() - initial_match_count;
406 void Dump(Stream &strm) {
407 std::lock_guard<std::recursive_mutex> guard(m_mutex);
409 for (auto spec : m_specs) {
410 strm.Printf("[%u] ", idx);
418 typedef std::vector<ModuleSpec> collection; ///< The module collection type.
419 collection m_specs; ///< The collection of modules.
420 mutable std::recursive_mutex m_mutex;
423 } // namespace lldb_private
425 #endif // liblldb_ModuleSpec_h_