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