1 //===-- AppleDWARFIndex.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Symbol/Function.h"
17 using namespace lldb_private;
20 std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
21 Module &module, DWARFDataExtractor apple_names,
22 DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
23 DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
24 auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
25 apple_names, debug_str, ".apple_names");
26 if (!apple_names_table_up->IsValid())
27 apple_names_table_up.reset();
29 auto apple_namespaces_table_up =
30 std::make_unique<DWARFMappedHash::MemoryTable>(
31 apple_namespaces, debug_str, ".apple_namespaces");
32 if (!apple_namespaces_table_up->IsValid())
33 apple_namespaces_table_up.reset();
35 auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
36 apple_types, debug_str, ".apple_types");
37 if (!apple_types_table_up->IsValid())
38 apple_types_table_up.reset();
40 auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
41 apple_objc, debug_str, ".apple_objc");
42 if (!apple_objc_table_up->IsValid())
43 apple_objc_table_up.reset();
45 if (apple_names_table_up || apple_names_table_up || apple_types_table_up ||
47 return std::make_unique<AppleDWARFIndex>(
48 module, std::move(apple_names_table_up),
49 std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
50 std::move(apple_objc_table_up));
55 void AppleDWARFIndex::GetGlobalVariables(
56 ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
57 if (!m_apple_names_up)
59 m_apple_names_up->FindByName(
60 basename.GetStringRef(),
61 DIERefCallback(callback, basename.GetStringRef()));
64 void AppleDWARFIndex::GetGlobalVariables(
65 const RegularExpression ®ex,
66 llvm::function_ref<bool(DWARFDIE die)> callback) {
67 if (!m_apple_names_up)
70 DWARFMappedHash::DIEInfoArray hash_data;
71 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
72 // This is not really the DIE name.
73 DWARFMappedHash::ExtractDIEArray(hash_data,
74 DIERefCallback(callback, regex.GetText()));
77 void AppleDWARFIndex::GetGlobalVariables(
78 const DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
79 if (!m_apple_names_up)
82 DWARFMappedHash::DIEInfoArray hash_data;
83 m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), cu.GetNextUnitOffset(),
85 DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
88 void AppleDWARFIndex::GetObjCMethods(
89 ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
92 m_apple_objc_up->FindByName(
93 class_name.GetStringRef(),
94 DIERefCallback(callback, class_name.GetStringRef()));
97 void AppleDWARFIndex::GetCompleteObjCClass(
98 ConstString class_name, bool must_be_implementation,
99 llvm::function_ref<bool(DWARFDIE die)> callback) {
100 if (!m_apple_types_up)
102 m_apple_types_up->FindCompleteObjCClassByName(
103 class_name.GetStringRef(),
104 DIERefCallback(callback, class_name.GetStringRef()),
105 must_be_implementation);
108 void AppleDWARFIndex::GetTypes(
109 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
110 if (!m_apple_types_up)
112 m_apple_types_up->FindByName(name.GetStringRef(),
113 DIERefCallback(callback, name.GetStringRef()));
116 void AppleDWARFIndex::GetTypes(
117 const DWARFDeclContext &context,
118 llvm::function_ref<bool(DWARFDIE die)> callback) {
119 if (!m_apple_types_up)
122 Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
124 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
125 DWARFMappedHash::eAtomTypeTag);
126 const bool has_qualified_name_hash =
127 m_apple_types_up->GetHeader().header_data.ContainsAtom(
128 DWARFMappedHash::eAtomTypeQualNameHash);
130 const ConstString type_name(context[0].name);
131 const dw_tag_t tag = context[0].tag;
132 if (has_tag && has_qualified_name_hash) {
133 const char *qualified_name = context.GetQualifiedName();
134 const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
136 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
137 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
138 type_name.GetStringRef(), tag, qualified_name_hash,
139 DIERefCallback(callback, type_name.GetStringRef()));
144 // When searching for a scoped type (for example,
145 // "std::vector<int>::const_iterator") searching for the innermost
146 // name alone ("const_iterator") could yield many false
147 // positives. By searching for the parent type ("vector<int>")
148 // first we can avoid extracting type DIEs from object files that
149 // would fail the filter anyway.
150 if (!has_qualified_name_hash && (context.GetSize() > 1) &&
151 (context[1].tag == DW_TAG_class_type ||
152 context[1].tag == DW_TAG_structure_type)) {
153 if (m_apple_types_up->FindByName(context[1].name,
154 [&](DIERef ref) { return false; }))
159 m_module.LogMessage(log, "FindByNameAndTag()");
160 m_apple_types_up->FindByNameAndTag(
161 type_name.GetStringRef(), tag,
162 DIERefCallback(callback, type_name.GetStringRef()));
166 m_apple_types_up->FindByName(
167 type_name.GetStringRef(),
168 DIERefCallback(callback, type_name.GetStringRef()));
171 void AppleDWARFIndex::GetNamespaces(
172 ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
173 if (!m_apple_namespaces_up)
175 m_apple_namespaces_up->FindByName(
176 name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
179 void AppleDWARFIndex::GetFunctions(
180 ConstString name, SymbolFileDWARF &dwarf,
181 const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
182 llvm::function_ref<bool(DWARFDIE die)> callback) {
183 m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
184 return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf,
185 parent_decl_ctx, name_type_mask, callback);
189 void AppleDWARFIndex::GetFunctions(
190 const RegularExpression ®ex,
191 llvm::function_ref<bool(DWARFDIE die)> callback) {
192 if (!m_apple_names_up)
195 DWARFMappedHash::DIEInfoArray hash_data;
196 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
197 DWARFMappedHash::ExtractDIEArray(hash_data,
198 DIERefCallback(callback, regex.GetText()));
201 void AppleDWARFIndex::Dump(Stream &s) {
202 if (m_apple_names_up)
203 s.PutCString(".apple_names index present\n");
204 if (m_apple_namespaces_up)
205 s.PutCString(".apple_namespaces index present\n");
206 if (m_apple_types_up)
207 s.PutCString(".apple_types index present\n");
209 s.PutCString(".apple_objc index present\n");
210 // TODO: Dump index contents