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