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
ProcessFunctionDIE(llvm::StringRef name,DIERef ref,SymbolFileDWARF & dwarf,const CompilerDeclContext & parent_decl_ctx,uint32_t name_type_mask,llvm::function_ref<bool (DWARFDIE die)> callback)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)
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
DIERefCallbackImpl(const DWARFIndex & index,llvm::function_ref<bool (DWARFDIE die)> callback,llvm::StringRef name)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
operator ()(DIERef ref) const74 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
ReportInvalidDIERef(DIERef ref,llvm::StringRef name) const81 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