File indexing completed on 2026-05-10 08:42:45
0001
0002
0003
0004
0005
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
0032
0033
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
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
0320
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
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
0369
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;
0402 mutable std::recursive_mutex m_mutex;
0403 };
0404
0405 }
0406
0407 #endif