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/Module.h" 15 16 using namespace lldb_private; 17 using namespace lldb; 18 19 DWARFIndex::~DWARFIndex() = default; 20 21 bool DWARFIndex::ProcessFunctionDIE( 22 llvm::StringRef name, DIERef ref, SymbolFileDWARF &dwarf, 23 const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, 24 llvm::function_ref<bool(DWARFDIE die)> callback) { 25 DWARFDIE die = dwarf.GetDIE(ref); 26 if (!die) { 27 ReportInvalidDIERef(ref, name); 28 return true; 29 } 30 31 // Exit early if we're searching exclusively for methods or selectors and 32 // we have a context specified (no methods in namespaces). 33 uint32_t looking_for_nonmethods = 34 name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); 35 if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) 36 return true; 37 38 // Otherwise, we need to also check that the context matches. If it does not 39 // match, we do nothing. 40 if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) 41 return true; 42 43 // In case of a full match, we just insert everything we find. 44 if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) 45 return callback(die); 46 47 // If looking for ObjC selectors, we need to also check if the name is a 48 // possible selector. 49 if (name_type_mask & eFunctionNameTypeSelector && 50 ObjCLanguage::IsPossibleObjCMethodName(die.GetName())) 51 return callback(die); 52 53 bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod; 54 bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase; 55 if (looking_for_methods || looking_for_functions) { 56 // If we're looking for either methods or functions, we definitely want this 57 // die. Otherwise, only keep it if the die type matches what we are 58 // searching for. 59 if ((looking_for_methods && looking_for_functions) || 60 looking_for_methods == die.IsMethod()) 61 return callback(die); 62 } 63 64 return true; 65 } 66 67 DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( 68 const DWARFIndex &index, llvm::function_ref<bool(DWARFDIE die)> callback, 69 llvm::StringRef name) 70 : m_index(index), 71 m_dwarf(*llvm::cast<SymbolFileDWARF>(index.m_module.GetSymbolFile())), 72 m_callback(callback), m_name(name) {} 73 74 bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { 75 if (DWARFDIE die = m_dwarf.GetDIE(ref)) 76 return m_callback(die); 77 m_index.ReportInvalidDIERef(ref, m_name); 78 return true; 79 } 80 81 void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { 82 m_module.ReportErrorIfModifyDetected( 83 "the DWARF debug information has been modified (accelerator table had " 84 "bad die 0x%8.8x for '%s')\n", 85 ref.die_offset(), name.str().c_str()); 86 } 87