1 //===-- SymbolFile.cpp ----------------------------------------------------===// 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 char SymbolFile::ID; 28 char SymbolFileCommon::ID; 29 30 void SymbolFile::PreloadSymbols() { 31 // No-op for most implementations. 32 } 33 34 std::recursive_mutex &SymbolFile::GetModuleMutex() const { 35 return GetObjectFile()->GetModule()->GetMutex(); 36 } 37 38 SymbolFile *SymbolFile::FindPlugin(ObjectFileSP objfile_sp) { 39 std::unique_ptr<SymbolFile> best_symfile_up; 40 if (objfile_sp != nullptr) { 41 42 // We need to test the abilities of this section list. So create what it 43 // would be with this new objfile_sp. 44 lldb::ModuleSP module_sp(objfile_sp->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 != objfile_sp.get()) { 49 // Make sure the main object file's sections are created 50 module_obj_file->GetSectionList(); 51 objfile_sp->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(objfile_sp)); 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 uint32_t 89 SymbolFile::ResolveSymbolContext(const SourceLocationSpec &src_location_spec, 90 lldb::SymbolContextItem resolve_scope, 91 SymbolContextList &sc_list) { 92 return 0; 93 } 94 95 void SymbolFile::FindGlobalVariables(ConstString name, 96 const CompilerDeclContext &parent_decl_ctx, 97 uint32_t max_matches, 98 VariableList &variables) {} 99 100 void SymbolFile::FindGlobalVariables(const RegularExpression ®ex, 101 uint32_t max_matches, 102 VariableList &variables) {} 103 104 void SymbolFile::FindFunctions(ConstString name, 105 const CompilerDeclContext &parent_decl_ctx, 106 lldb::FunctionNameType name_type_mask, 107 bool include_inlines, 108 SymbolContextList &sc_list) {} 109 110 void SymbolFile::FindFunctions(const RegularExpression ®ex, 111 bool include_inlines, 112 SymbolContextList &sc_list) {} 113 114 void SymbolFile::GetMangledNamesForFunction( 115 const std::string &scope_qualified_name, 116 std::vector<ConstString> &mangled_names) {} 117 118 void SymbolFile::FindTypes( 119 ConstString name, const CompilerDeclContext &parent_decl_ctx, 120 uint32_t max_matches, 121 llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, 122 TypeMap &types) {} 123 124 void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern, 125 LanguageSet languages, 126 llvm::DenseSet<SymbolFile *> &searched_symbol_files, 127 TypeMap &types) {} 128 129 void SymbolFile::AssertModuleLock() { 130 // The code below is too expensive to leave enabled in release builds. It's 131 // enabled in debug builds or when the correct macro is set. 132 #if defined(LLDB_CONFIGURATION_DEBUG) 133 // We assert that we have to module lock by trying to acquire the lock from a 134 // different thread. Note that we must abort if the result is true to 135 // guarantee correctness. 136 assert(std::async( 137 std::launch::async, 138 [this] { 139 return this->GetModuleMutex().try_lock(); 140 }).get() == false && 141 "Module is not locked"); 142 #endif 143 } 144 145 SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default; 146 147 Symtab *SymbolFileCommon::GetSymtab() { 148 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 149 if (m_symtab) 150 return m_symtab; 151 152 // Fetch the symtab from the main object file. 153 m_symtab = GetMainObjectFile()->GetSymtab(); 154 155 // Then add our symbols to it. 156 if (m_symtab) 157 AddSymbols(*m_symtab); 158 159 return m_symtab; 160 } 161 162 ObjectFile *SymbolFileCommon::GetMainObjectFile() { 163 return m_objfile_sp->GetModule()->GetObjectFile(); 164 } 165 166 void SymbolFileCommon::SectionFileAddressesChanged() { 167 ObjectFile *module_objfile = GetMainObjectFile(); 168 ObjectFile *symfile_objfile = GetObjectFile(); 169 if (symfile_objfile != module_objfile) 170 symfile_objfile->SectionFileAddressesChanged(); 171 if (m_symtab) 172 m_symtab->SectionFileAddressesChanged(); 173 } 174 175 uint32_t SymbolFileCommon::GetNumCompileUnits() { 176 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 177 if (!m_compile_units) { 178 // Create an array of compile unit shared pointers -- which will each 179 // remain NULL until someone asks for the actual compile unit information. 180 m_compile_units.emplace(CalculateNumCompileUnits()); 181 } 182 return m_compile_units->size(); 183 } 184 185 CompUnitSP SymbolFileCommon::GetCompileUnitAtIndex(uint32_t idx) { 186 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 187 uint32_t num = GetNumCompileUnits(); 188 if (idx >= num) 189 return nullptr; 190 lldb::CompUnitSP &cu_sp = (*m_compile_units)[idx]; 191 if (!cu_sp) 192 cu_sp = ParseCompileUnitAtIndex(idx); 193 return cu_sp; 194 } 195 196 void SymbolFileCommon::SetCompileUnitAtIndex(uint32_t idx, 197 const CompUnitSP &cu_sp) { 198 std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 199 const size_t num_compile_units = GetNumCompileUnits(); 200 assert(idx < num_compile_units); 201 (void)num_compile_units; 202 203 // Fire off an assertion if this compile unit already exists for now. The 204 // partial parsing should take care of only setting the compile unit 205 // once, so if this assertion fails, we need to make sure that we don't 206 // have a race condition, or have a second parse of the same compile 207 // unit. 208 assert((*m_compile_units)[idx] == nullptr); 209 (*m_compile_units)[idx] = cu_sp; 210 } 211 212 llvm::Expected<TypeSystem &> 213 SymbolFileCommon::GetTypeSystemForLanguage(lldb::LanguageType language) { 214 auto type_system_or_err = 215 m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); 216 if (type_system_or_err) { 217 type_system_or_err->SetSymbolFile(this); 218 } 219 return type_system_or_err; 220 } 221 222 uint64_t SymbolFileCommon::GetDebugInfoSize() { 223 if (!m_objfile_sp) 224 return 0; 225 ModuleSP module_sp(m_objfile_sp->GetModule()); 226 if (!module_sp) 227 return 0; 228 const SectionList *section_list = module_sp->GetSectionList(); 229 if (section_list) 230 return section_list->GetDebugInfoSize(); 231 return 0; 232 } 233 234 void SymbolFileCommon::Dump(Stream &s) { 235 s.Format("SymbolFile {0} ({1})\n", GetPluginName(), 236 GetMainObjectFile()->GetFileSpec()); 237 s.PutCString("Types:\n"); 238 m_type_list.Dump(&s, /*show_context*/ false); 239 s.PutChar('\n'); 240 241 s.PutCString("Compile units:\n"); 242 if (m_compile_units) { 243 for (const CompUnitSP &cu_sp : *m_compile_units) { 244 // We currently only dump the compile units that have been parsed 245 if (cu_sp) 246 cu_sp->Dump(&s, /*show_context*/ false); 247 } 248 } 249 s.PutChar('\n'); 250 251 if (Symtab *symtab = GetSymtab()) 252 symtab->Dump(&s, nullptr, eSortOrderNone); 253 } 254