Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:45

0001 //===-- ModuleSpec.h --------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_CORE_MODULESPEC_H
0010 #define LLDB_CORE_MODULESPEC_H
0011 
0012 #include "lldb/Host/FileSystem.h"
0013 #include "lldb/Target/PathMappingList.h"
0014 #include "lldb/Utility/ArchSpec.h"
0015 #include "lldb/Utility/FileSpec.h"
0016 #include "lldb/Utility/Iterable.h"
0017 #include "lldb/Utility/Stream.h"
0018 #include "lldb/Utility/UUID.h"
0019 
0020 #include "llvm/Support/Chrono.h"
0021 
0022 #include <mutex>
0023 #include <vector>
0024 
0025 namespace lldb_private {
0026 
0027 class ModuleSpec {
0028 public:
0029   ModuleSpec() = default;
0030 
0031   /// If the \c data argument is passed, its contents will be used
0032   /// as the module contents instead of trying to read them from
0033   /// \c file_spec .
0034   ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(),
0035              lldb::DataBufferSP data = lldb::DataBufferSP())
0036       : m_file(file_spec), m_uuid(uuid), m_object_offset(0), m_data(data) {
0037     if (data)
0038       m_object_size = data->GetByteSize();
0039     else if (m_file)
0040       m_object_size = FileSystem::Instance().GetByteSize(file_spec);
0041   }
0042 
0043   ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
0044       : m_file(file_spec), m_arch(arch), m_object_offset(0),
0045         m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {}
0046 
0047   FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); }
0048 
0049   const FileSpec *GetFileSpecPtr() const {
0050     return (m_file ? &m_file : nullptr);
0051   }
0052 
0053   FileSpec &GetFileSpec() { return m_file; }
0054 
0055   const FileSpec &GetFileSpec() const { return m_file; }
0056 
0057   FileSpec *GetPlatformFileSpecPtr() {
0058     return (m_platform_file ? &m_platform_file : nullptr);
0059   }
0060 
0061   const FileSpec *GetPlatformFileSpecPtr() const {
0062     return (m_platform_file ? &m_platform_file : nullptr);
0063   }
0064 
0065   FileSpec &GetPlatformFileSpec() { return m_platform_file; }
0066 
0067   const FileSpec &GetPlatformFileSpec() const { return m_platform_file; }
0068 
0069   FileSpec *GetSymbolFileSpecPtr() {
0070     return (m_symbol_file ? &m_symbol_file : nullptr);
0071   }
0072 
0073   const FileSpec *GetSymbolFileSpecPtr() const {
0074     return (m_symbol_file ? &m_symbol_file : nullptr);
0075   }
0076 
0077   FileSpec &GetSymbolFileSpec() { return m_symbol_file; }
0078 
0079   const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; }
0080 
0081   ArchSpec *GetArchitecturePtr() {
0082     return (m_arch.IsValid() ? &m_arch : nullptr);
0083   }
0084 
0085   const ArchSpec *GetArchitecturePtr() const {
0086     return (m_arch.IsValid() ? &m_arch : nullptr);
0087   }
0088 
0089   ArchSpec &GetArchitecture() { return m_arch; }
0090 
0091   const ArchSpec &GetArchitecture() const { return m_arch; }
0092 
0093   UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); }
0094 
0095   const UUID *GetUUIDPtr() const {
0096     return (m_uuid.IsValid() ? &m_uuid : nullptr);
0097   }
0098 
0099   UUID &GetUUID() { return m_uuid; }
0100 
0101   const UUID &GetUUID() const { return m_uuid; }
0102 
0103   ConstString &GetObjectName() { return m_object_name; }
0104 
0105   ConstString GetObjectName() const { return m_object_name; }
0106 
0107   uint64_t GetObjectOffset() const { return m_object_offset; }
0108 
0109   void SetObjectOffset(uint64_t object_offset) {
0110     m_object_offset = object_offset;
0111   }
0112 
0113   uint64_t GetObjectSize() const { return m_object_size; }
0114 
0115   void SetObjectSize(uint64_t object_size) { m_object_size = object_size; }
0116 
0117   llvm::sys::TimePoint<> &GetObjectModificationTime() {
0118     return m_object_mod_time;
0119   }
0120 
0121   const llvm::sys::TimePoint<> &GetObjectModificationTime() const {
0122     return m_object_mod_time;
0123   }
0124 
0125   PathMappingList &GetSourceMappingList() const { return m_source_mappings; }
0126 
0127   lldb::DataBufferSP GetData() const { return m_data; }
0128 
0129   void Clear() {
0130     m_file.Clear();
0131     m_platform_file.Clear();
0132     m_symbol_file.Clear();
0133     m_arch.Clear();
0134     m_uuid.Clear();
0135     m_object_name.Clear();
0136     m_object_offset = 0;
0137     m_object_size = 0;
0138     m_source_mappings.Clear(false);
0139     m_object_mod_time = llvm::sys::TimePoint<>();
0140   }
0141 
0142   explicit operator bool() const {
0143     if (m_file)
0144       return true;
0145     if (m_platform_file)
0146       return true;
0147     if (m_symbol_file)
0148       return true;
0149     if (m_arch.IsValid())
0150       return true;
0151     if (m_uuid.IsValid())
0152       return true;
0153     if (m_object_name)
0154       return true;
0155     if (m_object_size)
0156       return true;
0157     if (m_object_mod_time != llvm::sys::TimePoint<>())
0158       return true;
0159     return false;
0160   }
0161 
0162   void Dump(Stream &strm) const {
0163     bool dumped_something = false;
0164     if (m_file) {
0165       strm.PutCString("file = '");
0166       strm << m_file;
0167       strm.PutCString("'");
0168       dumped_something = true;
0169     }
0170     if (m_platform_file) {
0171       if (dumped_something)
0172         strm.PutCString(", ");
0173       strm.PutCString("platform_file = '");
0174       strm << m_platform_file;
0175       strm.PutCString("'");
0176       dumped_something = true;
0177     }
0178     if (m_symbol_file) {
0179       if (dumped_something)
0180         strm.PutCString(", ");
0181       strm.PutCString("symbol_file = '");
0182       strm << m_symbol_file;
0183       strm.PutCString("'");
0184       dumped_something = true;
0185     }
0186     if (m_arch.IsValid()) {
0187       if (dumped_something)
0188         strm.PutCString(", ");
0189       strm.Printf("arch = ");
0190       m_arch.DumpTriple(strm.AsRawOstream());
0191       dumped_something = true;
0192     }
0193     if (m_uuid.IsValid()) {
0194       if (dumped_something)
0195         strm.PutCString(", ");
0196       strm.PutCString("uuid = ");
0197       m_uuid.Dump(strm);
0198       dumped_something = true;
0199     }
0200     if (m_object_name) {
0201       if (dumped_something)
0202         strm.PutCString(", ");
0203       strm.Printf("object_name = %s", m_object_name.GetCString());
0204       dumped_something = true;
0205     }
0206     if (m_object_offset > 0) {
0207       if (dumped_something)
0208         strm.PutCString(", ");
0209       strm.Printf("object_offset = %" PRIu64, m_object_offset);
0210       dumped_something = true;
0211     }
0212     if (m_object_size > 0) {
0213       if (dumped_something)
0214         strm.PutCString(", ");
0215       strm.Printf("object size = %" PRIu64, m_object_size);
0216       dumped_something = true;
0217     }
0218     if (m_object_mod_time != llvm::sys::TimePoint<>()) {
0219       if (dumped_something)
0220         strm.PutCString(", ");
0221       strm.Format("object_mod_time = {0:x+}",
0222                   uint64_t(llvm::sys::toTimeT(m_object_mod_time)));
0223     }
0224   }
0225 
0226   bool Matches(const ModuleSpec &match_module_spec,
0227                bool exact_arch_match) const {
0228     if (match_module_spec.GetUUIDPtr() &&
0229         match_module_spec.GetUUID() != GetUUID())
0230       return false;
0231     if (match_module_spec.GetObjectName() &&
0232         match_module_spec.GetObjectName() != GetObjectName())
0233       return false;
0234     if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec()))
0235       return false;
0236     if (GetPlatformFileSpec() &&
0237         !FileSpec::Match(match_module_spec.GetPlatformFileSpec(),
0238                          GetPlatformFileSpec())) {
0239       return false;
0240     }
0241     // Only match the symbol file spec if there is one in this ModuleSpec
0242     if (GetSymbolFileSpec() &&
0243         !FileSpec::Match(match_module_spec.GetSymbolFileSpec(),
0244                          GetSymbolFileSpec())) {
0245       return false;
0246     }
0247     if (match_module_spec.GetArchitecturePtr()) {
0248       if (exact_arch_match) {
0249         if (!GetArchitecture().IsExactMatch(
0250                 match_module_spec.GetArchitecture()))
0251           return false;
0252       } else {
0253         if (!GetArchitecture().IsCompatibleMatch(
0254                 match_module_spec.GetArchitecture()))
0255           return false;
0256       }
0257     }
0258     return true;
0259   }
0260 
0261 protected:
0262   FileSpec m_file;
0263   FileSpec m_platform_file;
0264   FileSpec m_symbol_file;
0265   ArchSpec m_arch;
0266   UUID m_uuid;
0267   ConstString m_object_name;
0268   uint64_t m_object_offset = 0;
0269   uint64_t m_object_size = 0;
0270   llvm::sys::TimePoint<> m_object_mod_time;
0271   mutable PathMappingList m_source_mappings;
0272   lldb::DataBufferSP m_data = {};
0273 };
0274 
0275 class ModuleSpecList {
0276 public:
0277   ModuleSpecList() = default;
0278 
0279   ModuleSpecList(const ModuleSpecList &rhs) {
0280     std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
0281     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
0282     m_specs = rhs.m_specs;
0283   }
0284 
0285   ~ModuleSpecList() = default;
0286 
0287   ModuleSpecList &operator=(const ModuleSpecList &rhs) {
0288     if (this != &rhs) {
0289       std::lock(m_mutex, rhs.m_mutex);
0290       std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock);
0291       std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex,
0292                                                       std::adopt_lock);
0293       m_specs = rhs.m_specs;
0294     }
0295     return *this;
0296   }
0297 
0298   size_t GetSize() const {
0299     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0300     return m_specs.size();
0301   }
0302 
0303   void Clear() {
0304     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0305     m_specs.clear();
0306   }
0307 
0308   void Append(const ModuleSpec &spec) {
0309     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0310     m_specs.push_back(spec);
0311   }
0312 
0313   void Append(const ModuleSpecList &rhs) {
0314     std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex);
0315     std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex);
0316     m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end());
0317   }
0318 
0319   // The index "i" must be valid and this can't be used in multi-threaded code
0320   // as no mutex lock is taken.
0321   ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; }
0322 
0323   bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const {
0324     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0325     if (i < m_specs.size()) {
0326       module_spec = m_specs[i];
0327       return true;
0328     }
0329     module_spec.Clear();
0330     return false;
0331   }
0332 
0333   bool FindMatchingModuleSpec(const ModuleSpec &module_spec,
0334                               ModuleSpec &match_module_spec) const {
0335     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0336     bool exact_arch_match = true;
0337     for (auto spec : m_specs) {
0338       if (spec.Matches(module_spec, exact_arch_match)) {
0339         match_module_spec = spec;
0340         return true;
0341       }
0342     }
0343 
0344     // If there was an architecture, retry with a compatible arch
0345     if (module_spec.GetArchitecturePtr()) {
0346       exact_arch_match = false;
0347       for (auto spec : m_specs) {
0348         if (spec.Matches(module_spec, exact_arch_match)) {
0349           match_module_spec = spec;
0350           return true;
0351         }
0352       }
0353     }
0354     match_module_spec.Clear();
0355     return false;
0356   }
0357 
0358   void FindMatchingModuleSpecs(const ModuleSpec &module_spec,
0359                                ModuleSpecList &matching_list) const {
0360     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0361     bool exact_arch_match = true;
0362     const size_t initial_match_count = matching_list.GetSize();
0363     for (auto spec : m_specs) {
0364       if (spec.Matches(module_spec, exact_arch_match))
0365         matching_list.Append(spec);
0366     }
0367 
0368     // If there was an architecture, retry with a compatible arch if no matches
0369     // were found
0370     if (module_spec.GetArchitecturePtr() &&
0371         (initial_match_count == matching_list.GetSize())) {
0372       exact_arch_match = false;
0373       for (auto spec : m_specs) {
0374         if (spec.Matches(module_spec, exact_arch_match))
0375           matching_list.Append(spec);
0376       }
0377     }
0378   }
0379 
0380   void Dump(Stream &strm) {
0381     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0382     uint32_t idx = 0;
0383     for (auto spec : m_specs) {
0384       strm.Printf("[%u] ", idx);
0385       spec.Dump(strm);
0386       strm.EOL();
0387       ++idx;
0388     }
0389   }
0390 
0391   typedef std::vector<ModuleSpec> collection;
0392   typedef LockingAdaptedIterable<collection, ModuleSpec, vector_adapter,
0393                                  std::recursive_mutex>
0394       ModuleSpecIterable;
0395 
0396   ModuleSpecIterable ModuleSpecs() {
0397     return ModuleSpecIterable(m_specs, m_mutex);
0398   }
0399 
0400 protected:
0401   collection m_specs;                         ///< The collection of modules.
0402   mutable std::recursive_mutex m_mutex;
0403 };
0404 
0405 } // namespace lldb_private
0406 
0407 #endif // LLDB_CORE_MODULESPEC_H