1 //===-- SymbolFile.cpp ------------------------------------------*- 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 #include "lldb/Symbol/SymbolFile.h" 10 11 #include "lldb/Core/Module.h" 12 #include "lldb/Core/PluginManager.h" 13 #include "lldb/Symbol/CompileUnit.h" 14 #include "lldb/Symbol/ObjectFile.h" 15 #include "lldb/Symbol/TypeMap.h" 16 #include "lldb/Symbol/TypeSystem.h" 17 #include "lldb/Symbol/VariableList.h" 18 #include "lldb/Utility/Log.h" 19 #include "lldb/Utility/StreamString.h" 20 #include "lldb/lldb-private.h" 21 22 #include <future> 23 24 using namespace lldb_private; 25 using namespace lldb; 26 27 void SymbolFile::PreloadSymbols() { 28 // No-op for most implementations. 29 } 30 31 std::recursive_mutex &SymbolFile::GetModuleMutex() const { 32 return GetObjectFile()->GetModule()->GetMutex(); 33 } 34 35 SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) { 36 std::unique_ptr<SymbolFile> best_symfile_up; 37 if (obj_file != nullptr) { 38 39 // We need to test the abilities of this section list. So create what it 40 // would be with this new obj_file. 41 lldb::ModuleSP module_sp(obj_file->GetModule()); 42 if (module_sp) { 43 // Default to the main module section list. 44 ObjectFile *module_obj_file = module_sp->GetObjectFile(); 45 if (module_obj_file != obj_file) { 46 // Make sure the main object file's sections are created 47 module_obj_file->GetSectionList(); 48 obj_file->CreateSections(*module_sp->GetUnifiedSectionList()); 49 } 50 } 51 52 // TODO: Load any plug-ins in the appropriate plug-in search paths and 53 // iterate over all of them to find the best one for the job. 54 55 uint32_t best_symfile_abilities = 0; 56 57 SymbolFileCreateInstance create_callback; 58 for (uint32_t idx = 0; 59 (create_callback = PluginManager::GetSymbolFileCreateCallbackAtIndex( 60 idx)) != nullptr; 61 ++idx) { 62 std::unique_ptr<SymbolFile> curr_symfile_up(create_callback(obj_file)); 63 64 if (curr_symfile_up) { 65 const uint32_t sym_file_abilities = curr_symfile_up->GetAbilities(); 66 if (sym_file_abilities > best_symfile_abilities) { 67 best_symfile_abilities = sym_file_abilities; 68 best_symfile_up.reset(curr_symfile_up.release()); 69 // If any symbol file parser has all of the abilities, then we should 70 // just stop looking. 71 if ((kAllAbilities & sym_file_abilities) == kAllAbilities) 72 break; 73 } 74 } 75 } 76 if (best_symfile_up) { 77 // Let the winning symbol file parser initialize itself more completely 78 // now that it has been chosen 79 best_symfile_up->InitializeObject(); 80 } 81 } 82 return best_symfile_up.release(); 83 } 84 85 TypeSystem *SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) { 86 TypeSystem *type_system = 87 m_obj_file->GetModule()->GetTypeSystemForLanguage(language); 88 if (type_system) 89 type_system->SetSymbolFile(this); 90 return type_system; 91 } 92 93 uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec, 94 uint32_t line, bool check_inlines, 95 lldb::SymbolContextItem resolve_scope, 96 SymbolContextList &sc_list) { 97 return 0; 98 } 99 100 uint32_t 101 SymbolFile::FindGlobalVariables(ConstString name, 102 const CompilerDeclContext *parent_decl_ctx, 103 uint32_t max_matches, VariableList &variables) { 104 return 0; 105 } 106 107 uint32_t SymbolFile::FindGlobalVariables(const RegularExpression ®ex, 108 uint32_t max_matches, 109 VariableList &variables) { 110 return 0; 111 } 112 113 uint32_t SymbolFile::FindFunctions(ConstString name, 114 const CompilerDeclContext *parent_decl_ctx, 115 lldb::FunctionNameType name_type_mask, 116 bool include_inlines, bool append, 117 SymbolContextList &sc_list) { 118 if (!append) 119 sc_list.Clear(); 120 return 0; 121 } 122 123 uint32_t SymbolFile::FindFunctions(const RegularExpression ®ex, 124 bool include_inlines, bool append, 125 SymbolContextList &sc_list) { 126 if (!append) 127 sc_list.Clear(); 128 return 0; 129 } 130 131 void SymbolFile::GetMangledNamesForFunction( 132 const std::string &scope_qualified_name, 133 std::vector<ConstString> &mangled_names) { 134 return; 135 } 136 137 uint32_t SymbolFile::FindTypes( 138 ConstString name, const CompilerDeclContext *parent_decl_ctx, 139 bool append, uint32_t max_matches, 140 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, 141 TypeMap &types) { 142 if (!append) 143 types.Clear(); 144 return 0; 145 } 146 147 size_t SymbolFile::FindTypes(const std::vector<CompilerContext> &context, 148 bool append, TypeMap &types) { 149 if (!append) 150 types.Clear(); 151 return 0; 152 } 153 154 void SymbolFile::AssertModuleLock() { 155 // The code below is too expensive to leave enabled in release builds. It's 156 // enabled in debug builds or when the correct macro is set. 157 #if defined(LLDB_CONFIGURATION_DEBUG) 158 // We assert that we have to module lock by trying to acquire the lock from a 159 // different thread. Note that we must abort if the result is true to 160 // guarantee correctness. 161 assert(std::async(std::launch::async, 162 [this] { return this->GetModuleMutex().try_lock(); }) 163 .get() == false && 164 "Module is not locked"); 165 #endif 166 } 167 168 uint32_t SymbolFile::GetNumCompileUnits() { 169 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 170 if (!m_compile_units) { 171 // Create an array of compile unit shared pointers -- which will each 172 // remain NULL until someone asks for the actual compile unit information. 173 m_compile_units.emplace(CalculateNumCompileUnits()); 174 } 175 return m_compile_units->size(); 176 } 177 178 CompUnitSP SymbolFile::GetCompileUnitAtIndex(uint32_t idx) { 179 uint32_t num = GetNumCompileUnits(); 180 if (idx >= num) 181 return nullptr; 182 lldb::CompUnitSP &cu_sp = (*m_compile_units)[idx]; 183 if (!cu_sp) 184 cu_sp = ParseCompileUnitAtIndex(idx); 185 return cu_sp; 186 } 187 188 void SymbolFile::SetCompileUnitAtIndex(uint32_t idx, const CompUnitSP &cu_sp) { 189 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 190 const size_t num_compile_units = GetNumCompileUnits(); 191 assert(idx < num_compile_units); 192 (void)num_compile_units; 193 194 // Fire off an assertion if this compile unit already exists for now. The 195 // partial parsing should take care of only setting the compile unit 196 // once, so if this assertion fails, we need to make sure that we don't 197 // have a race condition, or have a second parse of the same compile 198 // unit. 199 assert((*m_compile_units)[idx] == nullptr); 200 (*m_compile_units)[idx] = cu_sp; 201 } 202 203 void SymbolFile::Dump(Stream &s) { 204 s.PutCString("Types:\n"); 205 m_type_list.Dump(&s, /*show_context*/ false); 206 s.PutChar('\n'); 207 208 s.PutCString("Compile units:\n"); 209 if (m_compile_units) { 210 for (const CompUnitSP &cu_sp : *m_compile_units) { 211 // We currently only dump the compile units that have been parsed 212 if (cu_sp) 213 cu_sp->Dump(&s, /*show_context*/ false); 214 } 215 } 216 s.PutChar('\n'); 217 } 218 219 SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default; 220