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 "Plugins/Language/ObjC/ObjCLanguage.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h" 12 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" 13 14 #include "lldb/Core/Mangled.h" 15 #include "lldb/Core/Module.h" 16 #include "lldb/Target/Language.h" 17 18 using namespace lldb_private; 19 using namespace lldb; 20 using namespace lldb_private::plugin::dwarf; 21 22 DWARFIndex::~DWARFIndex() = default; 23 24 bool DWARFIndex::ProcessFunctionDIE( 25 const Module::LookupInfo &lookup_info, DIERef ref, SymbolFileDWARF &dwarf, 26 const CompilerDeclContext &parent_decl_ctx, 27 llvm::function_ref<bool(DWARFDIE die)> callback) { 28 llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); 29 FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 30 DWARFDIE die = dwarf.GetDIE(ref); 31 if (!die) { 32 ReportInvalidDIERef(ref, name); 33 return true; 34 } 35 36 if (!(name_type_mask & eFunctionNameTypeFull)) { 37 ConstString name_to_match_against; 38 if (const char *mangled_die_name = die.GetMangledName()) { 39 name_to_match_against = ConstString(mangled_die_name); 40 } else { 41 SymbolFileDWARF *symbols = die.GetDWARF(); 42 if (ConstString demangled_die_name = 43 symbols->ConstructFunctionDemangledName(die)) 44 name_to_match_against = demangled_die_name; 45 } 46 47 if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, 48 lookup_info.GetLanguageType())) 49 return true; 50 } 51 52 // Exit early if we're searching exclusively for methods or selectors and 53 // we have a context specified (no methods in namespaces). 54 uint32_t looking_for_nonmethods = 55 name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); 56 if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) 57 return true; 58 59 // Otherwise, we need to also check that the context matches. If it does not 60 // match, we do nothing. 61 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) 62 return true; 63 64 // In case of a full match, we just insert everything we find. 65 if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) 66 return callback(die); 67 68 // If looking for ObjC selectors, we need to also check if the name is a 69 // possible selector. 70 if (name_type_mask & eFunctionNameTypeSelector && 71 ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) 72 return callback(die); 73 74 bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod; 75 bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase; 76 if (looking_for_methods || looking_for_functions) { 77 // If we're looking for either methods or functions, we definitely want this 78 // die. Otherwise, only keep it if the die type matches what we are 79 // searching for. 80 if ((looking_for_methods && looking_for_functions) || 81 looking_for_methods == die.IsMethod()) 82 return callback(die); 83 } 84 85 return true; 86 } 87 88 DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( 89 const DWARFIndex &index, llvm::function_ref<bool(DWARFDIE die)> callback, 90 llvm::StringRef name) 91 : m_index(index), 92 m_dwarf(*llvm::cast<SymbolFileDWARF>( 93 index.m_module.GetSymbolFile()->GetBackingSymbolFile())), 94 m_callback(callback), m_name(name) {} 95 96 bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { 97 if (DWARFDIE die = m_dwarf.GetDIE(ref)) 98 return m_callback(die); 99 m_index.ReportInvalidDIERef(ref, m_name); 100 return true; 101 } 102 103 bool DWARFIndex::DIERefCallbackImpl::operator()( 104 const llvm::AppleAcceleratorTable::Entry &entry) const { 105 return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo, 106 *entry.getDIESectionOffset())); 107 } 108 109 void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { 110 m_module.ReportErrorIfModifyDetected( 111 "the DWARF debug information has been modified (accelerator table had " 112 "bad die {0:x16} for '{1}')\n", 113 ref.die_offset(), name.str().c_str()); 114 } 115