ModuleSpec.h revision 360784
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 liblldb_ModuleSpec_h_ 10#define liblldb_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 24namespace lldb_private { 25 26class ModuleSpec { 27public: 28 ModuleSpec() 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() {} 32 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() {} 38 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() {} 44 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) {} 52 53 ModuleSpec &operator=(const ModuleSpec &rhs) { 54 if (this != &rhs) { 55 m_file = rhs.m_file; 56 m_platform_file = rhs.m_platform_file; 57 m_symbol_file = rhs.m_symbol_file; 58 m_arch = rhs.m_arch; 59 m_uuid = rhs.m_uuid; 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; 65 } 66 return *this; 67 } 68 69 FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } 70 71 const FileSpec *GetFileSpecPtr() const { 72 return (m_file ? &m_file : nullptr); 73 } 74 75 FileSpec &GetFileSpec() { return m_file; } 76 77 const FileSpec &GetFileSpec() const { return m_file; } 78 79 FileSpec *GetPlatformFileSpecPtr() { 80 return (m_platform_file ? &m_platform_file : nullptr); 81 } 82 83 const FileSpec *GetPlatformFileSpecPtr() const { 84 return (m_platform_file ? &m_platform_file : nullptr); 85 } 86 87 FileSpec &GetPlatformFileSpec() { return m_platform_file; } 88 89 const FileSpec &GetPlatformFileSpec() const { return m_platform_file; } 90 91 FileSpec *GetSymbolFileSpecPtr() { 92 return (m_symbol_file ? &m_symbol_file : nullptr); 93 } 94 95 const FileSpec *GetSymbolFileSpecPtr() const { 96 return (m_symbol_file ? &m_symbol_file : nullptr); 97 } 98 99 FileSpec &GetSymbolFileSpec() { return m_symbol_file; } 100 101 const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; } 102 103 ArchSpec *GetArchitecturePtr() { 104 return (m_arch.IsValid() ? &m_arch : nullptr); 105 } 106 107 const ArchSpec *GetArchitecturePtr() const { 108 return (m_arch.IsValid() ? &m_arch : nullptr); 109 } 110 111 ArchSpec &GetArchitecture() { return m_arch; } 112 113 const ArchSpec &GetArchitecture() const { return m_arch; } 114 115 UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); } 116 117 const UUID *GetUUIDPtr() const { 118 return (m_uuid.IsValid() ? &m_uuid : nullptr); 119 } 120 121 UUID &GetUUID() { return m_uuid; } 122 123 const UUID &GetUUID() const { return m_uuid; } 124 125 ConstString &GetObjectName() { return m_object_name; } 126 127 ConstString GetObjectName() const { return m_object_name; } 128 129 uint64_t GetObjectOffset() const { return m_object_offset; } 130 131 void SetObjectOffset(uint64_t object_offset) { 132 m_object_offset = object_offset; 133 } 134 135 uint64_t GetObjectSize() const { return m_object_size; } 136 137 void SetObjectSize(uint64_t object_size) { m_object_size = object_size; } 138 139 llvm::sys::TimePoint<> &GetObjectModificationTime() { 140 return m_object_mod_time; 141 } 142 143 const llvm::sys::TimePoint<> &GetObjectModificationTime() const { 144 return m_object_mod_time; 145 } 146 147 PathMappingList &GetSourceMappingList() const { return m_source_mappings; } 148 149 void Clear() { 150 m_file.Clear(); 151 m_platform_file.Clear(); 152 m_symbol_file.Clear(); 153 m_arch.Clear(); 154 m_uuid.Clear(); 155 m_object_name.Clear(); 156 m_object_offset = 0; 157 m_object_size = 0; 158 m_source_mappings.Clear(false); 159 m_object_mod_time = llvm::sys::TimePoint<>(); 160 } 161 162 explicit operator bool() const { 163 if (m_file) 164 return true; 165 if (m_platform_file) 166 return true; 167 if (m_symbol_file) 168 return true; 169 if (m_arch.IsValid()) 170 return true; 171 if (m_uuid.IsValid()) 172 return true; 173 if (m_object_name) 174 return true; 175 if (m_object_size) 176 return true; 177 if (m_object_mod_time != llvm::sys::TimePoint<>()) 178 return true; 179 return false; 180 } 181 182 void Dump(Stream &strm) const { 183 bool dumped_something = false; 184 if (m_file) { 185 strm.PutCString("file = '"); 186 strm << m_file; 187 strm.PutCString("'"); 188 dumped_something = true; 189 } 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; 197 } 198 if (m_symbol_file) { 199 if (dumped_something) 200 strm.PutCString(", "); 201 strm.PutCString("symbol_file = '"); 202 strm << m_symbol_file; 203 strm.PutCString("'"); 204 dumped_something = true; 205 } 206 if (m_arch.IsValid()) { 207 if (dumped_something) 208 strm.PutCString(", "); 209 strm.Printf("arch = "); 210 m_arch.DumpTriple(strm.AsRawOstream()); 211 dumped_something = true; 212 } 213 if (m_uuid.IsValid()) { 214 if (dumped_something) 215 strm.PutCString(", "); 216 strm.PutCString("uuid = "); 217 m_uuid.Dump(&strm); 218 dumped_something = true; 219 } 220 if (m_object_name) { 221 if (dumped_something) 222 strm.PutCString(", "); 223 strm.Printf("object_name = %s", m_object_name.GetCString()); 224 dumped_something = true; 225 } 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; 231 } 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; 237 } 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))); 243 } 244 } 245 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()) 250 return false; 251 if (match_module_spec.GetObjectName() && 252 match_module_spec.GetObjectName() != GetObjectName()) 253 return false; 254 if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec())) 255 return false; 256 if (GetPlatformFileSpec() && 257 !FileSpec::Match(match_module_spec.GetPlatformFileSpec(), 258 GetPlatformFileSpec())) { 259 return false; 260 } 261 // Only match the symbol file spec if there is one in this ModuleSpec 262 if (GetSymbolFileSpec() && 263 !FileSpec::Match(match_module_spec.GetSymbolFileSpec(), 264 GetSymbolFileSpec())) { 265 return false; 266 } 267 if (match_module_spec.GetArchitecturePtr()) { 268 if (exact_arch_match) { 269 if (!GetArchitecture().IsExactMatch( 270 match_module_spec.GetArchitecture())) 271 return false; 272 } else { 273 if (!GetArchitecture().IsCompatibleMatch( 274 match_module_spec.GetArchitecture())) 275 return false; 276 } 277 } 278 return true; 279 } 280 281protected: 282 FileSpec m_file; 283 FileSpec m_platform_file; 284 FileSpec m_symbol_file; 285 ArchSpec m_arch; 286 UUID m_uuid; 287 ConstString m_object_name; 288 uint64_t m_object_offset; 289 uint64_t m_object_size; 290 llvm::sys::TimePoint<> m_object_mod_time; 291 mutable PathMappingList m_source_mappings; 292}; 293 294class ModuleSpecList { 295public: 296 ModuleSpecList() : m_specs(), m_mutex() {} 297 298 ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() { 299 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex); 300 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex); 301 m_specs = rhs.m_specs; 302 } 303 304 ~ModuleSpecList() = default; 305 306 ModuleSpecList &operator=(const ModuleSpecList &rhs) { 307 if (this != &rhs) { 308 std::lock(m_mutex, rhs.m_mutex); 309 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock); 310 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, 311 std::adopt_lock); 312 m_specs = rhs.m_specs; 313 } 314 return *this; 315 } 316 317 size_t GetSize() const { 318 std::lock_guard<std::recursive_mutex> guard(m_mutex); 319 return m_specs.size(); 320 } 321 322 void Clear() { 323 std::lock_guard<std::recursive_mutex> guard(m_mutex); 324 m_specs.clear(); 325 } 326 327 void Append(const ModuleSpec &spec) { 328 std::lock_guard<std::recursive_mutex> guard(m_mutex); 329 m_specs.push_back(spec); 330 } 331 332 void Append(const ModuleSpecList &rhs) { 333 std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex); 334 std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex); 335 m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end()); 336 } 337 338 // The index "i" must be valid and this can't be used in multi-threaded code 339 // as no mutex lock is taken. 340 ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; } 341 342 bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const { 343 std::lock_guard<std::recursive_mutex> guard(m_mutex); 344 if (i < m_specs.size()) { 345 module_spec = m_specs[i]; 346 return true; 347 } 348 module_spec.Clear(); 349 return false; 350 } 351 352 bool FindMatchingModuleSpec(const ModuleSpec &module_spec, 353 ModuleSpec &match_module_spec) const { 354 std::lock_guard<std::recursive_mutex> guard(m_mutex); 355 bool exact_arch_match = true; 356 for (auto spec : m_specs) { 357 if (spec.Matches(module_spec, exact_arch_match)) { 358 match_module_spec = spec; 359 return true; 360 } 361 } 362 363 // If there was an architecture, retry with a compatible arch 364 if (module_spec.GetArchitecturePtr()) { 365 exact_arch_match = false; 366 for (auto spec : m_specs) { 367 if (spec.Matches(module_spec, exact_arch_match)) { 368 match_module_spec = spec; 369 return true; 370 } 371 } 372 } 373 match_module_spec.Clear(); 374 return false; 375 } 376 377 void FindMatchingModuleSpecs(const ModuleSpec &module_spec, 378 ModuleSpecList &matching_list) const { 379 std::lock_guard<std::recursive_mutex> guard(m_mutex); 380 bool exact_arch_match = true; 381 const size_t initial_match_count = matching_list.GetSize(); 382 for (auto spec : m_specs) { 383 if (spec.Matches(module_spec, exact_arch_match)) 384 matching_list.Append(spec); 385 } 386 387 // If there was an architecture, retry with a compatible arch if no matches 388 // were found 389 if (module_spec.GetArchitecturePtr() && 390 (initial_match_count == matching_list.GetSize())) { 391 exact_arch_match = false; 392 for (auto spec : m_specs) { 393 if (spec.Matches(module_spec, exact_arch_match)) 394 matching_list.Append(spec); 395 } 396 } 397 } 398 399 void Dump(Stream &strm) { 400 std::lock_guard<std::recursive_mutex> guard(m_mutex); 401 uint32_t idx = 0; 402 for (auto spec : m_specs) { 403 strm.Printf("[%u] ", idx); 404 spec.Dump(strm); 405 strm.EOL(); 406 ++idx; 407 } 408 } 409 410protected: 411 typedef std::vector<ModuleSpec> collection; ///< The module collection type. 412 collection m_specs; ///< The collection of modules. 413 mutable std::recursive_mutex m_mutex; 414}; 415 416} // namespace lldb_private 417 418#endif // liblldb_ModuleSpec_h_ 419