1 //===-- DWARFIndex.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 "Plugins/SymbolFile/DWARF/DWARFIndex.h" 10 #include "DWARFDebugInfoEntry.h" 11 #include "DWARFDeclContext.h" 12 #include "Plugins/Language/ObjC/ObjCLanguage.h" 13 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" 14 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 15 16 #include "lldb/Core/Mangled.h" 17 #include "lldb/Core/Module.h" 18 #include "lldb/Target/Language.h" 19 20 using namespace lldb_private; 21 using namespace lldb; 22 using namespace lldb_private::plugin::dwarf; 23 24 DWARFIndex::~DWARFIndex() = default; 25 26 bool DWARFIndex::ProcessFunctionDIE( 27 const Module::LookupInfo &lookup_info, DWARFDIE die, 28 const CompilerDeclContext &parent_decl_ctx, 29 llvm::function_ref<bool(DWARFDIE die)> callback) { 30 llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); 31 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 32 33 if (!(name_type_mask & eFunctionNameTypeFull)) { 34 ConstString name_to_match_against; 35 if (const char *mangled_die_name = die.GetMangledName()) { 36 name_to_match_against = ConstString(mangled_die_name); 37 } else { 38 SymbolFileDWARF *symbols = die.GetDWARF(); 39 if (ConstString demangled_die_name = 40 symbols->ConstructFunctionDemangledName(die)) 41 name_to_match_against = demangled_die_name; 42 } 43 44 if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, 45 lookup_info.GetLanguageType())) 46 return true; 47 } 48 49 // Exit early if we're searching exclusively for methods or selectors and 50 // we have a context specified (no methods in namespaces). 51 uint32_t looking_for_nonmethods = 52 name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); 53 if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) 54 return true; 55 56 // Otherwise, we need to also check that the context matches. If it does not 57 // match, we do nothing. 58 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) 59 return true; 60 61 // In case of a full match, we just insert everything we find. 62 if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) 63 return callback(die); 64 65 // If looking for ObjC selectors, we need to also check if the name is a 66 // possible selector. 67 if (name_type_mask & eFunctionNameTypeSelector && 68 ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) 69 return callback(die); 70 71 bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod; 72 bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase; 73 if (looking_for_methods || looking_for_functions) { 74 // If we're looking for either methods or functions, we definitely want this 75 // die. Otherwise, only keep it if the die type matches what we are 76 // searching for. 77 if ((looking_for_methods && looking_for_functions) || 78 looking_for_methods == die.IsMethod()) 79 return callback(die); 80 } 81 82 return true; 83 } 84 85 DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( 86 const DWARFIndex &index, llvm::function_ref<bool(DWARFDIE die)> callback, 87 llvm::StringRef name) 88 : m_index(index), 89 m_dwarf(*llvm::cast<SymbolFileDWARF>( 90 index.m_module.GetSymbolFile()->GetBackingSymbolFile())), 91 m_callback(callback), m_name(name) {} 92 93 bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { 94 if (DWARFDIE die = m_dwarf.GetDIE(ref)) 95 return m_callback(die); 96 m_index.ReportInvalidDIERef(ref, m_name); 97 return true; 98 } 99 100 bool DWARFIndex::DIERefCallbackImpl::operator()( 101 const llvm::AppleAcceleratorTable::Entry &entry) const { 102 return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo, 103 *entry.getDIESectionOffset())); 104 } 105 106 void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { 107 m_module.ReportErrorIfModifyDetected( 108 "the DWARF debug information has been modified (accelerator table had " 109 "bad die {0:x16} for '{1}')\n", 110 ref.die_offset(), name.str().c_str()); 111 } 112 113 void DWARFIndex::GetFullyQualifiedType( 114 const DWARFDeclContext &context, 115 llvm::function_ref<bool(DWARFDIE die)> callback) { 116 GetTypes(context, [&](DWARFDIE die) { 117 return GetFullyQualifiedTypeImpl(context, die, callback); 118 }); 119 } 120 121 bool DWARFIndex::GetFullyQualifiedTypeImpl( 122 const DWARFDeclContext &context, DWARFDIE die, 123 llvm::function_ref<bool(DWARFDIE die)> callback) { 124 DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext(); 125 if (dwarf_decl_ctx == context) 126 return callback(die); 127 return true; 128 } 129 130 void DWARFIndex::GetTypesWithQuery( 131 TypeQuery &query, llvm::function_ref<bool(DWARFDIE die)> callback) { 132 GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) { 133 return ProcessTypeDIEMatchQuery(query, die, callback); 134 }); 135 } 136 137 bool DWARFIndex::ProcessTypeDIEMatchQuery( 138 TypeQuery &query, DWARFDIE die, 139 llvm::function_ref<bool(DWARFDIE die)> callback) { 140 // Check the language, but only if we have a language filter. 141 if (query.HasLanguage() && 142 !query.LanguageMatches(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()))) 143 return true; // Keep iterating over index types, language mismatch. 144 145 // Since mangled names are unique, we only need to check if the names are 146 // the same. 147 if (query.GetSearchByMangledName()) { 148 if (die.GetMangledName(/*substitute_name_allowed=*/false) != 149 query.GetTypeBasename().GetStringRef()) 150 return true; // Keep iterating over index types, mangled name mismatch. 151 return callback(die); 152 } 153 154 std::vector<lldb_private::CompilerContext> die_context; 155 if (query.GetModuleSearch()) 156 die_context = die.GetDeclContext(); 157 else 158 die_context = die.GetTypeLookupContext(); 159 160 if (!query.ContextMatches(die_context)) 161 return true; 162 return callback(die); 163 } 164 165 void DWARFIndex::GetNamespacesWithParents( 166 ConstString name, const CompilerDeclContext &parent_decl_ctx, 167 llvm::function_ref<bool(DWARFDIE die)> callback) { 168 GetNamespaces(name, [&](DWARFDIE die) { 169 return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback); 170 }); 171 } 172 173 bool DWARFIndex::ProcessNamespaceDieMatchParents( 174 const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, 175 llvm::function_ref<bool(DWARFDIE die)> callback) { 176 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) 177 return true; 178 return callback(die); 179 } 180