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