15ffd83dbSDimitry Andric //===-- DWARFIndex.cpp ----------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" 101db9f3b2SDimitry Andric #include "DWARFDebugInfoEntry.h" 111db9f3b2SDimitry Andric #include "DWARFDeclContext.h" 120b57cec5SDimitry Andric #include "Plugins/Language/ObjC/ObjCLanguage.h" 130b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" 140b57cec5SDimitry Andric #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 150b57cec5SDimitry Andric 16bdd1243dSDimitry Andric #include "lldb/Core/Mangled.h" 175ffd83dbSDimitry Andric #include "lldb/Core/Module.h" 18bdd1243dSDimitry Andric #include "lldb/Target/Language.h" 195ffd83dbSDimitry Andric 200b57cec5SDimitry Andric using namespace lldb_private; 210b57cec5SDimitry Andric using namespace lldb; 225f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric DWARFIndex::~DWARFIndex() = default; 250b57cec5SDimitry Andric 265ffd83dbSDimitry Andric bool DWARFIndex::ProcessFunctionDIE( 27*0fca6ea1SDimitry Andric const Module::LookupInfo &lookup_info, DWARFDIE die, 28bdd1243dSDimitry Andric const CompilerDeclContext &parent_decl_ctx, 295ffd83dbSDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 30bdd1243dSDimitry Andric llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); 31bdd1243dSDimitry Andric FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 320b57cec5SDimitry Andric 33bdd1243dSDimitry Andric if (!(name_type_mask & eFunctionNameTypeFull)) { 34bdd1243dSDimitry Andric ConstString name_to_match_against; 35bdd1243dSDimitry Andric if (const char *mangled_die_name = die.GetMangledName()) { 36bdd1243dSDimitry Andric name_to_match_against = ConstString(mangled_die_name); 37bdd1243dSDimitry Andric } else { 38bdd1243dSDimitry Andric SymbolFileDWARF *symbols = die.GetDWARF(); 39bdd1243dSDimitry Andric if (ConstString demangled_die_name = 40bdd1243dSDimitry Andric symbols->ConstructFunctionDemangledName(die)) 41bdd1243dSDimitry Andric name_to_match_against = demangled_die_name; 42bdd1243dSDimitry Andric } 43bdd1243dSDimitry Andric 44bdd1243dSDimitry Andric if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, 45bdd1243dSDimitry Andric lookup_info.GetLanguageType())) 46bdd1243dSDimitry Andric return true; 47bdd1243dSDimitry Andric } 48bdd1243dSDimitry Andric 490b57cec5SDimitry Andric // Exit early if we're searching exclusively for methods or selectors and 500b57cec5SDimitry Andric // we have a context specified (no methods in namespaces). 510b57cec5SDimitry Andric uint32_t looking_for_nonmethods = 520b57cec5SDimitry Andric name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); 530b57cec5SDimitry Andric if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) 545ffd83dbSDimitry Andric return true; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric // Otherwise, we need to also check that the context matches. If it does not 570b57cec5SDimitry Andric // match, we do nothing. 585ffd83dbSDimitry Andric if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) 595ffd83dbSDimitry Andric return true; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // In case of a full match, we just insert everything we find. 62349cc55cSDimitry Andric if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) 635ffd83dbSDimitry Andric return callback(die); 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // If looking for ObjC selectors, we need to also check if the name is a 660b57cec5SDimitry Andric // possible selector. 670b57cec5SDimitry Andric if (name_type_mask & eFunctionNameTypeSelector && 685ffd83dbSDimitry Andric ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) 695ffd83dbSDimitry Andric return callback(die); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod; 720b57cec5SDimitry Andric bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase; 730b57cec5SDimitry Andric if (looking_for_methods || looking_for_functions) { 740b57cec5SDimitry Andric // If we're looking for either methods or functions, we definitely want this 750b57cec5SDimitry Andric // die. Otherwise, only keep it if the die type matches what we are 760b57cec5SDimitry Andric // searching for. 770b57cec5SDimitry Andric if ((looking_for_methods && looking_for_functions) || 780b57cec5SDimitry Andric looking_for_methods == die.IsMethod()) 795ffd83dbSDimitry Andric return callback(die); 800b57cec5SDimitry Andric } 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric return true; 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( 865ffd83dbSDimitry Andric const DWARFIndex &index, llvm::function_ref<bool(DWARFDIE die)> callback, 875ffd83dbSDimitry Andric llvm::StringRef name) 885ffd83dbSDimitry Andric : m_index(index), 8981ad6265SDimitry Andric m_dwarf(*llvm::cast<SymbolFileDWARF>( 9081ad6265SDimitry Andric index.m_module.GetSymbolFile()->GetBackingSymbolFile())), 915ffd83dbSDimitry Andric m_callback(callback), m_name(name) {} 925ffd83dbSDimitry Andric 935ffd83dbSDimitry Andric bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { 945ffd83dbSDimitry Andric if (DWARFDIE die = m_dwarf.GetDIE(ref)) 955ffd83dbSDimitry Andric return m_callback(die); 965ffd83dbSDimitry Andric m_index.ReportInvalidDIERef(ref, m_name); 975ffd83dbSDimitry Andric return true; 985ffd83dbSDimitry Andric } 995ffd83dbSDimitry Andric 10006c3fb27SDimitry Andric bool DWARFIndex::DIERefCallbackImpl::operator()( 10106c3fb27SDimitry Andric const llvm::AppleAcceleratorTable::Entry &entry) const { 10206c3fb27SDimitry Andric return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo, 10306c3fb27SDimitry Andric *entry.getDIESectionOffset())); 10406c3fb27SDimitry Andric } 10506c3fb27SDimitry Andric 1065ffd83dbSDimitry Andric void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { 1075ffd83dbSDimitry Andric m_module.ReportErrorIfModifyDetected( 1085ffd83dbSDimitry Andric "the DWARF debug information has been modified (accelerator table had " 109bdd1243dSDimitry Andric "bad die {0:x16} for '{1}')\n", 1105ffd83dbSDimitry Andric ref.die_offset(), name.str().c_str()); 1110b57cec5SDimitry Andric } 1121db9f3b2SDimitry Andric 1131db9f3b2SDimitry Andric void DWARFIndex::GetFullyQualifiedType( 1141db9f3b2SDimitry Andric const DWARFDeclContext &context, 1151db9f3b2SDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 1161db9f3b2SDimitry Andric GetTypes(context, [&](DWARFDIE die) { 1171db9f3b2SDimitry Andric return GetFullyQualifiedTypeImpl(context, die, callback); 1181db9f3b2SDimitry Andric }); 1191db9f3b2SDimitry Andric } 1201db9f3b2SDimitry Andric 1211db9f3b2SDimitry Andric bool DWARFIndex::GetFullyQualifiedTypeImpl( 1221db9f3b2SDimitry Andric const DWARFDeclContext &context, DWARFDIE die, 1231db9f3b2SDimitry Andric llvm::function_ref<bool(DWARFDIE die)> callback) { 124*0fca6ea1SDimitry Andric DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext(); 1251db9f3b2SDimitry Andric if (dwarf_decl_ctx == context) 1261db9f3b2SDimitry Andric return callback(die); 1271db9f3b2SDimitry Andric return true; 1281db9f3b2SDimitry Andric } 129