1254721Semaste//===-- ModuleSpec.h --------------------------------------------*- C++ -*-===// 2254721Semaste// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6254721Semaste// 7254721Semaste//===----------------------------------------------------------------------===// 8254721Semaste 9254721Semaste#ifndef liblldb_ModuleSpec_h_ 10254721Semaste#define liblldb_ModuleSpec_h_ 11254721Semaste 12344779Sdim#include "lldb/Host/FileSystem.h" 13254721Semaste#include "lldb/Target/PathMappingList.h" 14327952Sdim#include "lldb/Utility/ArchSpec.h" 15321369Sdim#include "lldb/Utility/FileSpec.h" 16321369Sdim#include "lldb/Utility/Stream.h" 17321369Sdim#include "lldb/Utility/UUID.h" 18254721Semaste 19314564Sdim#include "llvm/Support/Chrono.h" 20314564Sdim 21314564Sdim#include <mutex> 22314564Sdim#include <vector> 23314564Sdim 24254721Semastenamespace lldb_private { 25254721Semaste 26314564Sdimclass ModuleSpec { 27254721Semastepublic: 28314564Sdim ModuleSpec() 29314564Sdim : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(), 30314564Sdim m_object_name(), m_object_offset(0), m_object_size(0), 31314564Sdim m_source_mappings() {} 32254721Semaste 33344779Sdim ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID()) 34314564Sdim : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(), 35341825Sdim m_uuid(uuid), m_object_name(), m_object_offset(0), 36344779Sdim m_object_size(FileSystem::Instance().GetByteSize(file_spec)), 37344779Sdim m_source_mappings() {} 38254721Semaste 39314564Sdim ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch) 40314564Sdim : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch), 41314564Sdim m_uuid(), m_object_name(), m_object_offset(0), 42344779Sdim m_object_size(FileSystem::Instance().GetByteSize(file_spec)), 43344779Sdim m_source_mappings() {} 44254721Semaste 45314564Sdim ModuleSpec(const ModuleSpec &rhs) 46314564Sdim : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file), 47314564Sdim m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch), 48314564Sdim m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name), 49314564Sdim m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size), 50314564Sdim m_object_mod_time(rhs.m_object_mod_time), 51314564Sdim m_source_mappings(rhs.m_source_mappings) {} 52254721Semaste 53314564Sdim ModuleSpec &operator=(const ModuleSpec &rhs) { 54314564Sdim if (this != &rhs) { 55314564Sdim m_file = rhs.m_file; 56314564Sdim m_platform_file = rhs.m_platform_file; 57314564Sdim m_symbol_file = rhs.m_symbol_file; 58314564Sdim m_arch = rhs.m_arch; 59314564Sdim m_uuid = rhs.m_uuid; 60314564Sdim m_object_name = rhs.m_object_name; 61314564Sdim m_object_offset = rhs.m_object_offset; 62314564Sdim m_object_size = rhs.m_object_size; 63314564Sdim m_object_mod_time = rhs.m_object_mod_time; 64314564Sdim m_source_mappings = rhs.m_source_mappings; 65254721Semaste } 66314564Sdim return *this; 67314564Sdim } 68254721Semaste 69314564Sdim FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } 70296417Sdim 71314564Sdim const FileSpec *GetFileSpecPtr() const { 72314564Sdim return (m_file ? &m_file : nullptr); 73314564Sdim } 74254721Semaste 75314564Sdim FileSpec &GetFileSpec() { return m_file; } 76254721Semaste 77314564Sdim const FileSpec &GetFileSpec() const { return m_file; } 78254721Semaste 79314564Sdim FileSpec *GetPlatformFileSpecPtr() { 80314564Sdim return (m_platform_file ? &m_platform_file : nullptr); 81314564Sdim } 82254721Semaste 83314564Sdim const FileSpec *GetPlatformFileSpecPtr() const { 84314564Sdim return (m_platform_file ? &m_platform_file : nullptr); 85314564Sdim } 86254721Semaste 87314564Sdim FileSpec &GetPlatformFileSpec() { return m_platform_file; } 88254721Semaste 89314564Sdim const FileSpec &GetPlatformFileSpec() const { return m_platform_file; } 90254721Semaste 91314564Sdim FileSpec *GetSymbolFileSpecPtr() { 92314564Sdim return (m_symbol_file ? &m_symbol_file : nullptr); 93314564Sdim } 94254721Semaste 95314564Sdim const FileSpec *GetSymbolFileSpecPtr() const { 96314564Sdim return (m_symbol_file ? &m_symbol_file : nullptr); 97314564Sdim } 98254721Semaste 99314564Sdim FileSpec &GetSymbolFileSpec() { return m_symbol_file; } 100254721Semaste 101314564Sdim const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; } 102254721Semaste 103314564Sdim ArchSpec *GetArchitecturePtr() { 104314564Sdim return (m_arch.IsValid() ? &m_arch : nullptr); 105314564Sdim } 106288943Sdim 107314564Sdim const ArchSpec *GetArchitecturePtr() const { 108314564Sdim return (m_arch.IsValid() ? &m_arch : nullptr); 109314564Sdim } 110288943Sdim 111314564Sdim ArchSpec &GetArchitecture() { return m_arch; } 112288943Sdim 113314564Sdim const ArchSpec &GetArchitecture() const { return m_arch; } 114314564Sdim 115314564Sdim UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); } 116314564Sdim 117314564Sdim const UUID *GetUUIDPtr() const { 118314564Sdim return (m_uuid.IsValid() ? &m_uuid : nullptr); 119314564Sdim } 120314564Sdim 121314564Sdim UUID &GetUUID() { return m_uuid; } 122314564Sdim 123314564Sdim const UUID &GetUUID() const { return m_uuid; } 124314564Sdim 125314564Sdim ConstString &GetObjectName() { return m_object_name; } 126314564Sdim 127353358Sdim ConstString GetObjectName() const { return m_object_name; } 128314564Sdim 129314564Sdim uint64_t GetObjectOffset() const { return m_object_offset; } 130314564Sdim 131314564Sdim void SetObjectOffset(uint64_t object_offset) { 132314564Sdim m_object_offset = object_offset; 133314564Sdim } 134314564Sdim 135314564Sdim uint64_t GetObjectSize() const { return m_object_size; } 136314564Sdim 137314564Sdim void SetObjectSize(uint64_t object_size) { m_object_size = object_size; } 138314564Sdim 139314564Sdim llvm::sys::TimePoint<> &GetObjectModificationTime() { 140314564Sdim return m_object_mod_time; 141314564Sdim } 142314564Sdim 143314564Sdim const llvm::sys::TimePoint<> &GetObjectModificationTime() const { 144314564Sdim return m_object_mod_time; 145314564Sdim } 146314564Sdim 147314564Sdim PathMappingList &GetSourceMappingList() const { return m_source_mappings; } 148314564Sdim 149314564Sdim void Clear() { 150314564Sdim m_file.Clear(); 151314564Sdim m_platform_file.Clear(); 152314564Sdim m_symbol_file.Clear(); 153314564Sdim m_arch.Clear(); 154314564Sdim m_uuid.Clear(); 155314564Sdim m_object_name.Clear(); 156314564Sdim m_object_offset = 0; 157314564Sdim m_object_size = 0; 158314564Sdim m_source_mappings.Clear(false); 159314564Sdim m_object_mod_time = llvm::sys::TimePoint<>(); 160314564Sdim } 161314564Sdim 162314564Sdim explicit operator bool() const { 163314564Sdim if (m_file) 164314564Sdim return true; 165314564Sdim if (m_platform_file) 166314564Sdim return true; 167314564Sdim if (m_symbol_file) 168314564Sdim return true; 169314564Sdim if (m_arch.IsValid()) 170314564Sdim return true; 171314564Sdim if (m_uuid.IsValid()) 172314564Sdim return true; 173314564Sdim if (m_object_name) 174314564Sdim return true; 175314564Sdim if (m_object_size) 176314564Sdim return true; 177314564Sdim if (m_object_mod_time != llvm::sys::TimePoint<>()) 178314564Sdim return true; 179314564Sdim return false; 180314564Sdim } 181314564Sdim 182314564Sdim void Dump(Stream &strm) const { 183314564Sdim bool dumped_something = false; 184314564Sdim if (m_file) { 185314564Sdim strm.PutCString("file = '"); 186314564Sdim strm << m_file; 187314564Sdim strm.PutCString("'"); 188314564Sdim dumped_something = true; 189254721Semaste } 190314564Sdim if (m_platform_file) { 191314564Sdim if (dumped_something) 192314564Sdim strm.PutCString(", "); 193314564Sdim strm.PutCString("platform_file = '"); 194314564Sdim strm << m_platform_file; 195314564Sdim strm.PutCString("'"); 196314564Sdim dumped_something = true; 197254721Semaste } 198314564Sdim if (m_symbol_file) { 199314564Sdim if (dumped_something) 200314564Sdim strm.PutCString(", "); 201314564Sdim strm.PutCString("symbol_file = '"); 202314564Sdim strm << m_symbol_file; 203314564Sdim strm.PutCString("'"); 204314564Sdim dumped_something = true; 205254721Semaste } 206314564Sdim if (m_arch.IsValid()) { 207314564Sdim if (dumped_something) 208314564Sdim strm.PutCString(", "); 209314564Sdim strm.Printf("arch = "); 210360784Sdim m_arch.DumpTriple(strm.AsRawOstream()); 211314564Sdim dumped_something = true; 212254721Semaste } 213314564Sdim if (m_uuid.IsValid()) { 214314564Sdim if (dumped_something) 215314564Sdim strm.PutCString(", "); 216314564Sdim strm.PutCString("uuid = "); 217314564Sdim m_uuid.Dump(&strm); 218314564Sdim dumped_something = true; 219314564Sdim } 220314564Sdim if (m_object_name) { 221314564Sdim if (dumped_something) 222314564Sdim strm.PutCString(", "); 223314564Sdim strm.Printf("object_name = %s", m_object_name.GetCString()); 224314564Sdim dumped_something = true; 225314564Sdim } 226314564Sdim if (m_object_offset > 0) { 227314564Sdim if (dumped_something) 228314564Sdim strm.PutCString(", "); 229314564Sdim strm.Printf("object_offset = %" PRIu64, m_object_offset); 230314564Sdim dumped_something = true; 231314564Sdim } 232314564Sdim if (m_object_size > 0) { 233314564Sdim if (dumped_something) 234314564Sdim strm.PutCString(", "); 235314564Sdim strm.Printf("object size = %" PRIu64, m_object_size); 236314564Sdim dumped_something = true; 237314564Sdim } 238314564Sdim if (m_object_mod_time != llvm::sys::TimePoint<>()) { 239314564Sdim if (dumped_something) 240314564Sdim strm.PutCString(", "); 241314564Sdim strm.Format("object_mod_time = {0:x+}", 242314564Sdim uint64_t(llvm::sys::toTimeT(m_object_mod_time))); 243314564Sdim } 244314564Sdim } 245254721Semaste 246314564Sdim bool Matches(const ModuleSpec &match_module_spec, 247314564Sdim bool exact_arch_match) const { 248314564Sdim if (match_module_spec.GetUUIDPtr() && 249314564Sdim match_module_spec.GetUUID() != GetUUID()) 250314564Sdim return false; 251314564Sdim if (match_module_spec.GetObjectName() && 252314564Sdim match_module_spec.GetObjectName() != GetObjectName()) 253314564Sdim return false; 254360784Sdim if (!FileSpec::Match(match_module_spec.GetFileSpec(), GetFileSpec())) 255360784Sdim return false; 256360784Sdim if (GetPlatformFileSpec() && 257360784Sdim !FileSpec::Match(match_module_spec.GetPlatformFileSpec(), 258360784Sdim GetPlatformFileSpec())) { 259360784Sdim return false; 260254721Semaste } 261314564Sdim // Only match the symbol file spec if there is one in this ModuleSpec 262360784Sdim if (GetSymbolFileSpec() && 263360784Sdim !FileSpec::Match(match_module_spec.GetSymbolFileSpec(), 264360784Sdim GetSymbolFileSpec())) { 265360784Sdim return false; 266254721Semaste } 267314564Sdim if (match_module_spec.GetArchitecturePtr()) { 268314564Sdim if (exact_arch_match) { 269314564Sdim if (!GetArchitecture().IsExactMatch( 270314564Sdim match_module_spec.GetArchitecture())) 271314564Sdim return false; 272314564Sdim } else { 273314564Sdim if (!GetArchitecture().IsCompatibleMatch( 274314564Sdim match_module_spec.GetArchitecture())) 275314564Sdim return false; 276314564Sdim } 277314564Sdim } 278314564Sdim return true; 279314564Sdim } 280254721Semaste 281254721Semasteprotected: 282314564Sdim FileSpec m_file; 283314564Sdim FileSpec m_platform_file; 284314564Sdim FileSpec m_symbol_file; 285314564Sdim ArchSpec m_arch; 286314564Sdim UUID m_uuid; 287314564Sdim ConstString m_object_name; 288314564Sdim uint64_t m_object_offset; 289314564Sdim uint64_t m_object_size; 290314564Sdim llvm::sys::TimePoint<> m_object_mod_time; 291314564Sdim mutable PathMappingList m_source_mappings; 292254721Semaste}; 293254721Semaste 294314564Sdimclass ModuleSpecList { 295254721Semastepublic: 296314564Sdim ModuleSpecList() : m_specs(), m_mutex() {} 297254721Semaste 298314564Sdim ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() { 299314564Sdim std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex); 300314564Sdim std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex); 301314564Sdim m_specs = rhs.m_specs; 302314564Sdim } 303254721Semaste 304314564Sdim ~ModuleSpecList() = default; 305254721Semaste 306314564Sdim ModuleSpecList &operator=(const ModuleSpecList &rhs) { 307314564Sdim if (this != &rhs) { 308353358Sdim std::lock(m_mutex, rhs.m_mutex); 309353358Sdim std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock); 310353358Sdim std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, 311353358Sdim std::adopt_lock); 312314564Sdim m_specs = rhs.m_specs; 313254721Semaste } 314314564Sdim return *this; 315314564Sdim } 316254721Semaste 317314564Sdim size_t GetSize() const { 318314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 319314564Sdim return m_specs.size(); 320314564Sdim } 321254721Semaste 322314564Sdim void Clear() { 323314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 324314564Sdim m_specs.clear(); 325314564Sdim } 326254721Semaste 327314564Sdim void Append(const ModuleSpec &spec) { 328314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 329314564Sdim m_specs.push_back(spec); 330314564Sdim } 331254721Semaste 332314564Sdim void Append(const ModuleSpecList &rhs) { 333314564Sdim std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex); 334314564Sdim std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex); 335314564Sdim m_specs.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end()); 336314564Sdim } 337314564Sdim 338341825Sdim // The index "i" must be valid and this can't be used in multi-threaded code 339341825Sdim // as no mutex lock is taken. 340314564Sdim ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; } 341314564Sdim 342314564Sdim bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const { 343314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 344314564Sdim if (i < m_specs.size()) { 345314564Sdim module_spec = m_specs[i]; 346314564Sdim return true; 347254721Semaste } 348314564Sdim module_spec.Clear(); 349314564Sdim return false; 350314564Sdim } 351254721Semaste 352314564Sdim bool FindMatchingModuleSpec(const ModuleSpec &module_spec, 353314564Sdim ModuleSpec &match_module_spec) const { 354314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 355314564Sdim bool exact_arch_match = true; 356314564Sdim for (auto spec : m_specs) { 357314564Sdim if (spec.Matches(module_spec, exact_arch_match)) { 358314564Sdim match_module_spec = spec; 359314564Sdim return true; 360314564Sdim } 361254721Semaste } 362296417Sdim 363314564Sdim // If there was an architecture, retry with a compatible arch 364314564Sdim if (module_spec.GetArchitecturePtr()) { 365314564Sdim exact_arch_match = false; 366314564Sdim for (auto spec : m_specs) { 367314564Sdim if (spec.Matches(module_spec, exact_arch_match)) { 368314564Sdim match_module_spec = spec; 369314564Sdim return true; 370254721Semaste } 371314564Sdim } 372254721Semaste } 373314564Sdim match_module_spec.Clear(); 374314564Sdim return false; 375314564Sdim } 376296417Sdim 377360784Sdim void FindMatchingModuleSpecs(const ModuleSpec &module_spec, 378360784Sdim ModuleSpecList &matching_list) const { 379314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 380314564Sdim bool exact_arch_match = true; 381314564Sdim const size_t initial_match_count = matching_list.GetSize(); 382314564Sdim for (auto spec : m_specs) { 383314564Sdim if (spec.Matches(module_spec, exact_arch_match)) 384314564Sdim matching_list.Append(spec); 385254721Semaste } 386309124Sdim 387314564Sdim // If there was an architecture, retry with a compatible arch if no matches 388314564Sdim // were found 389314564Sdim if (module_spec.GetArchitecturePtr() && 390314564Sdim (initial_match_count == matching_list.GetSize())) { 391314564Sdim exact_arch_match = false; 392314564Sdim for (auto spec : m_specs) { 393314564Sdim if (spec.Matches(module_spec, exact_arch_match)) 394314564Sdim matching_list.Append(spec); 395314564Sdim } 396254721Semaste } 397314564Sdim } 398254721Semaste 399314564Sdim void Dump(Stream &strm) { 400314564Sdim std::lock_guard<std::recursive_mutex> guard(m_mutex); 401314564Sdim uint32_t idx = 0; 402314564Sdim for (auto spec : m_specs) { 403314564Sdim strm.Printf("[%u] ", idx); 404314564Sdim spec.Dump(strm); 405314564Sdim strm.EOL(); 406314564Sdim ++idx; 407254721Semaste } 408314564Sdim } 409254721Semaste 410254721Semasteprotected: 411314564Sdim typedef std::vector<ModuleSpec> collection; ///< The module collection type. 412314564Sdim collection m_specs; ///< The collection of modules. 413314564Sdim mutable std::recursive_mutex m_mutex; 414254721Semaste}; 415254721Semaste 416254721Semaste} // namespace lldb_private 417254721Semaste 418296417Sdim#endif // liblldb_ModuleSpec_h_ 419