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