1 //===-- AppleDWARFIndex.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/AppleDWARFIndex.h"
10 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
12 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
13
14 #include "lldb/Core/Module.h"
15 #include "lldb/Symbol/Function.h"
16
17 using namespace lldb_private;
18 using namespace lldb;
19 using namespace lldb_private::dwarf;
20
Create(Module & module,DWARFDataExtractor apple_names,DWARFDataExtractor apple_namespaces,DWARFDataExtractor apple_types,DWARFDataExtractor apple_objc,DWARFDataExtractor debug_str)21 std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
22 Module &module, DWARFDataExtractor apple_names,
23 DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
24 DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
25 auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
26 apple_names, debug_str, ".apple_names");
27 if (!apple_names_table_up->IsValid())
28 apple_names_table_up.reset();
29
30 auto apple_namespaces_table_up =
31 std::make_unique<DWARFMappedHash::MemoryTable>(
32 apple_namespaces, debug_str, ".apple_namespaces");
33 if (!apple_namespaces_table_up->IsValid())
34 apple_namespaces_table_up.reset();
35
36 auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
37 apple_types, debug_str, ".apple_types");
38 if (!apple_types_table_up->IsValid())
39 apple_types_table_up.reset();
40
41 auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
42 apple_objc, debug_str, ".apple_objc");
43 if (!apple_objc_table_up->IsValid())
44 apple_objc_table_up.reset();
45
46 if (apple_names_table_up || apple_namespaces_table_up ||
47 apple_types_table_up || apple_objc_table_up)
48 return std::make_unique<AppleDWARFIndex>(
49 module, std::move(apple_names_table_up),
50 std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
51 std::move(apple_objc_table_up));
52
53 return nullptr;
54 }
55
GetGlobalVariables(ConstString basename,llvm::function_ref<bool (DWARFDIE die)> callback)56 void AppleDWARFIndex::GetGlobalVariables(
57 ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
58 if (!m_apple_names_up)
59 return;
60 m_apple_names_up->FindByName(
61 basename.GetStringRef(),
62 DIERefCallback(callback, basename.GetStringRef()));
63 }
64
GetGlobalVariables(const RegularExpression & regex,llvm::function_ref<bool (DWARFDIE die)> callback)65 void AppleDWARFIndex::GetGlobalVariables(
66 const RegularExpression ®ex,
67 llvm::function_ref<bool(DWARFDIE die)> callback) {
68 if (!m_apple_names_up)
69 return;
70
71 DWARFMappedHash::DIEInfoArray hash_data;
72 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
73 // This is not really the DIE name.
74 DWARFMappedHash::ExtractDIEArray(hash_data,
75 DIERefCallback(callback, regex.GetText()));
76 }
77
GetGlobalVariables(DWARFUnit & cu,llvm::function_ref<bool (DWARFDIE die)> callback)78 void AppleDWARFIndex::GetGlobalVariables(
79 DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
80 if (!m_apple_names_up)
81 return;
82
83 lldbassert(!cu.GetSymbolFileDWARF().GetDwoNum());
84 const DWARFUnit &non_skeleton_cu = cu.GetNonSkeletonUnit();
85 DWARFMappedHash::DIEInfoArray hash_data;
86 m_apple_names_up->AppendAllDIEsInRange(non_skeleton_cu.GetOffset(),
87 non_skeleton_cu.GetNextUnitOffset(),
88 hash_data);
89 DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
90 }
91
GetObjCMethods(ConstString class_name,llvm::function_ref<bool (DWARFDIE die)> callback)92 void AppleDWARFIndex::GetObjCMethods(
93 ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
94 if (!m_apple_objc_up)
95 return;
96 m_apple_objc_up->FindByName(
97 class_name.GetStringRef(),
98 DIERefCallback(callback, class_name.GetStringRef()));
99 }
100
GetCompleteObjCClass(ConstString class_name,bool must_be_implementation,llvm::function_ref<bool (DWARFDIE die)> callback)101 void AppleDWARFIndex::GetCompleteObjCClass(
102 ConstString class_name, bool must_be_implementation,
103 llvm::function_ref<bool(DWARFDIE die)> callback) {
104 if (!m_apple_types_up)
105 return;
106 m_apple_types_up->FindCompleteObjCClassByName(
107 class_name.GetStringRef(),
108 DIERefCallback(callback, class_name.GetStringRef()),
109 must_be_implementation);
110 }
111
GetTypes(ConstString name,llvm::function_ref<bool (DWARFDIE die)> callback)112 void AppleDWARFIndex::GetTypes(
113 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
114 if (!m_apple_types_up)
115 return;
116 m_apple_types_up->FindByName(name.GetStringRef(),
117 DIERefCallback(callback, name.GetStringRef()));
118 }
119
GetTypes(const DWARFDeclContext & context,llvm::function_ref<bool (DWARFDIE die)> callback)120 void AppleDWARFIndex::GetTypes(
121 const DWARFDeclContext &context,
122 llvm::function_ref<bool(DWARFDIE die)> callback) {
123 if (!m_apple_types_up)
124 return;
125
126 Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
127 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
128 DWARFMappedHash::eAtomTypeTag);
129 const bool has_qualified_name_hash =
130 m_apple_types_up->GetHeader().header_data.ContainsAtom(
131 DWARFMappedHash::eAtomTypeQualNameHash);
132
133 const ConstString type_name(context[0].name);
134 const dw_tag_t tag = context[0].tag;
135 if (has_tag && has_qualified_name_hash) {
136 const char *qualified_name = context.GetQualifiedName();
137 const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
138 if (log)
139 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
140 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
141 type_name.GetStringRef(), tag, qualified_name_hash,
142 DIERefCallback(callback, type_name.GetStringRef()));
143 return;
144 }
145
146 if (has_tag) {
147 // When searching for a scoped type (for example,
148 // "std::vector<int>::const_iterator") searching for the innermost
149 // name alone ("const_iterator") could yield many false
150 // positives. By searching for the parent type ("vector<int>")
151 // first we can avoid extracting type DIEs from object files that
152 // would fail the filter anyway.
153 if (!has_qualified_name_hash && (context.GetSize() > 1) &&
154 (context[1].tag == DW_TAG_class_type ||
155 context[1].tag == DW_TAG_structure_type)) {
156 if (m_apple_types_up->FindByName(context[1].name,
157 [&](DIERef ref) { return false; }))
158 return;
159 }
160
161 if (log)
162 m_module.LogMessage(log, "FindByNameAndTag()");
163 m_apple_types_up->FindByNameAndTag(
164 type_name.GetStringRef(), tag,
165 DIERefCallback(callback, type_name.GetStringRef()));
166 return;
167 }
168
169 m_apple_types_up->FindByName(
170 type_name.GetStringRef(),
171 DIERefCallback(callback, type_name.GetStringRef()));
172 }
173
GetNamespaces(ConstString name,llvm::function_ref<bool (DWARFDIE die)> callback)174 void AppleDWARFIndex::GetNamespaces(
175 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
176 if (!m_apple_namespaces_up)
177 return;
178 m_apple_namespaces_up->FindByName(
179 name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
180 }
181
GetFunctions(const Module::LookupInfo & lookup_info,SymbolFileDWARF & dwarf,const CompilerDeclContext & parent_decl_ctx,llvm::function_ref<bool (DWARFDIE die)> callback)182 void AppleDWARFIndex::GetFunctions(
183 const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
184 const CompilerDeclContext &parent_decl_ctx,
185 llvm::function_ref<bool(DWARFDIE die)> callback) {
186 ConstString name = lookup_info.GetLookupName();
187 m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
188 return ProcessFunctionDIE(lookup_info, die_ref, dwarf, parent_decl_ctx,
189 callback);
190 });
191 }
192
GetFunctions(const RegularExpression & regex,llvm::function_ref<bool (DWARFDIE die)> callback)193 void AppleDWARFIndex::GetFunctions(
194 const RegularExpression ®ex,
195 llvm::function_ref<bool(DWARFDIE die)> callback) {
196 if (!m_apple_names_up)
197 return;
198
199 DWARFMappedHash::DIEInfoArray hash_data;
200 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
201 DWARFMappedHash::ExtractDIEArray(hash_data,
202 DIERefCallback(callback, regex.GetText()));
203 }
204
Dump(Stream & s)205 void AppleDWARFIndex::Dump(Stream &s) {
206 if (m_apple_names_up)
207 s.PutCString(".apple_names index present\n");
208 if (m_apple_namespaces_up)
209 s.PutCString(".apple_namespaces index present\n");
210 if (m_apple_types_up)
211 s.PutCString(".apple_types index present\n");
212 if (m_apple_objc_up)
213 s.PutCString(".apple_objc index present\n");
214 // TODO: Dump index contents
215 }
216