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