1dda28197Spatrick //===-- AppleDWARFIndex.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h"
10061da546Spatrick #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
11061da546Spatrick #include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
12061da546Spatrick #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
13061da546Spatrick
14061da546Spatrick #include "lldb/Core/Module.h"
15061da546Spatrick #include "lldb/Symbol/Function.h"
16061da546Spatrick
17061da546Spatrick using namespace lldb_private;
18061da546Spatrick using namespace lldb;
19*f6aab3d8Srobert using namespace lldb_private::dwarf;
20061da546Spatrick
Create(Module & module,DWARFDataExtractor apple_names,DWARFDataExtractor apple_namespaces,DWARFDataExtractor apple_types,DWARFDataExtractor apple_objc,DWARFDataExtractor debug_str)21061da546Spatrick std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
22061da546Spatrick Module &module, DWARFDataExtractor apple_names,
23061da546Spatrick DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
24061da546Spatrick DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
25061da546Spatrick auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
26061da546Spatrick apple_names, debug_str, ".apple_names");
27061da546Spatrick if (!apple_names_table_up->IsValid())
28061da546Spatrick apple_names_table_up.reset();
29061da546Spatrick
30061da546Spatrick auto apple_namespaces_table_up =
31061da546Spatrick std::make_unique<DWARFMappedHash::MemoryTable>(
32061da546Spatrick apple_namespaces, debug_str, ".apple_namespaces");
33061da546Spatrick if (!apple_namespaces_table_up->IsValid())
34061da546Spatrick apple_namespaces_table_up.reset();
35061da546Spatrick
36061da546Spatrick auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
37061da546Spatrick apple_types, debug_str, ".apple_types");
38061da546Spatrick if (!apple_types_table_up->IsValid())
39061da546Spatrick apple_types_table_up.reset();
40061da546Spatrick
41061da546Spatrick auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
42061da546Spatrick apple_objc, debug_str, ".apple_objc");
43061da546Spatrick if (!apple_objc_table_up->IsValid())
44061da546Spatrick apple_objc_table_up.reset();
45061da546Spatrick
46be691f3bSpatrick if (apple_names_table_up || apple_namespaces_table_up ||
47be691f3bSpatrick apple_types_table_up || apple_objc_table_up)
48061da546Spatrick return std::make_unique<AppleDWARFIndex>(
49061da546Spatrick module, std::move(apple_names_table_up),
50061da546Spatrick std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
51061da546Spatrick std::move(apple_objc_table_up));
52061da546Spatrick
53061da546Spatrick return nullptr;
54061da546Spatrick }
55061da546Spatrick
GetGlobalVariables(ConstString basename,llvm::function_ref<bool (DWARFDIE die)> callback)56dda28197Spatrick void AppleDWARFIndex::GetGlobalVariables(
57dda28197Spatrick ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
58dda28197Spatrick if (!m_apple_names_up)
59dda28197Spatrick return;
60dda28197Spatrick m_apple_names_up->FindByName(
61dda28197Spatrick basename.GetStringRef(),
62dda28197Spatrick DIERefCallback(callback, basename.GetStringRef()));
63061da546Spatrick }
64061da546Spatrick
GetGlobalVariables(const RegularExpression & regex,llvm::function_ref<bool (DWARFDIE die)> callback)65dda28197Spatrick void AppleDWARFIndex::GetGlobalVariables(
66dda28197Spatrick const RegularExpression ®ex,
67dda28197Spatrick llvm::function_ref<bool(DWARFDIE die)> callback) {
68061da546Spatrick if (!m_apple_names_up)
69061da546Spatrick return;
70061da546Spatrick
71061da546Spatrick DWARFMappedHash::DIEInfoArray hash_data;
72dda28197Spatrick m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
73dda28197Spatrick // This is not really the DIE name.
74dda28197Spatrick DWARFMappedHash::ExtractDIEArray(hash_data,
75dda28197Spatrick DIERefCallback(callback, regex.GetText()));
76061da546Spatrick }
77061da546Spatrick
GetGlobalVariables(DWARFUnit & cu,llvm::function_ref<bool (DWARFDIE die)> callback)78dda28197Spatrick void AppleDWARFIndex::GetGlobalVariables(
79*f6aab3d8Srobert DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
80061da546Spatrick if (!m_apple_names_up)
81061da546Spatrick return;
82061da546Spatrick
83*f6aab3d8Srobert lldbassert(!cu.GetSymbolFileDWARF().GetDwoNum());
84*f6aab3d8Srobert const DWARFUnit &non_skeleton_cu = cu.GetNonSkeletonUnit();
85061da546Spatrick DWARFMappedHash::DIEInfoArray hash_data;
86*f6aab3d8Srobert m_apple_names_up->AppendAllDIEsInRange(non_skeleton_cu.GetOffset(),
87*f6aab3d8Srobert non_skeleton_cu.GetNextUnitOffset(),
88dda28197Spatrick hash_data);
89dda28197Spatrick DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
90061da546Spatrick }
91061da546Spatrick
GetObjCMethods(ConstString class_name,llvm::function_ref<bool (DWARFDIE die)> callback)92dda28197Spatrick void AppleDWARFIndex::GetObjCMethods(
93dda28197Spatrick ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
94dda28197Spatrick if (!m_apple_objc_up)
95dda28197Spatrick return;
96dda28197Spatrick m_apple_objc_up->FindByName(
97dda28197Spatrick class_name.GetStringRef(),
98dda28197Spatrick DIERefCallback(callback, class_name.GetStringRef()));
99061da546Spatrick }
100061da546Spatrick
GetCompleteObjCClass(ConstString class_name,bool must_be_implementation,llvm::function_ref<bool (DWARFDIE die)> callback)101dda28197Spatrick void AppleDWARFIndex::GetCompleteObjCClass(
102dda28197Spatrick ConstString class_name, bool must_be_implementation,
103dda28197Spatrick llvm::function_ref<bool(DWARFDIE die)> callback) {
104dda28197Spatrick if (!m_apple_types_up)
105dda28197Spatrick return;
106061da546Spatrick m_apple_types_up->FindCompleteObjCClassByName(
107dda28197Spatrick class_name.GetStringRef(),
108dda28197Spatrick DIERefCallback(callback, class_name.GetStringRef()),
109dda28197Spatrick must_be_implementation);
110061da546Spatrick }
111061da546Spatrick
GetTypes(ConstString name,llvm::function_ref<bool (DWARFDIE die)> callback)112dda28197Spatrick void AppleDWARFIndex::GetTypes(
113dda28197Spatrick ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
114dda28197Spatrick if (!m_apple_types_up)
115dda28197Spatrick return;
116dda28197Spatrick m_apple_types_up->FindByName(name.GetStringRef(),
117dda28197Spatrick DIERefCallback(callback, name.GetStringRef()));
118061da546Spatrick }
119061da546Spatrick
GetTypes(const DWARFDeclContext & context,llvm::function_ref<bool (DWARFDIE die)> callback)120dda28197Spatrick void AppleDWARFIndex::GetTypes(
121dda28197Spatrick const DWARFDeclContext &context,
122dda28197Spatrick llvm::function_ref<bool(DWARFDIE die)> callback) {
123061da546Spatrick if (!m_apple_types_up)
124061da546Spatrick return;
125061da546Spatrick
126*f6aab3d8Srobert Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
127061da546Spatrick const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
128061da546Spatrick DWARFMappedHash::eAtomTypeTag);
129061da546Spatrick const bool has_qualified_name_hash =
130061da546Spatrick m_apple_types_up->GetHeader().header_data.ContainsAtom(
131061da546Spatrick DWARFMappedHash::eAtomTypeQualNameHash);
132061da546Spatrick
133061da546Spatrick const ConstString type_name(context[0].name);
134061da546Spatrick const dw_tag_t tag = context[0].tag;
135061da546Spatrick if (has_tag && has_qualified_name_hash) {
136061da546Spatrick const char *qualified_name = context.GetQualifiedName();
137061da546Spatrick const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
138061da546Spatrick if (log)
139061da546Spatrick m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
140061da546Spatrick m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
141dda28197Spatrick type_name.GetStringRef(), tag, qualified_name_hash,
142dda28197Spatrick DIERefCallback(callback, type_name.GetStringRef()));
143061da546Spatrick return;
144061da546Spatrick }
145061da546Spatrick
146061da546Spatrick if (has_tag) {
147061da546Spatrick // When searching for a scoped type (for example,
148061da546Spatrick // "std::vector<int>::const_iterator") searching for the innermost
149061da546Spatrick // name alone ("const_iterator") could yield many false
150061da546Spatrick // positives. By searching for the parent type ("vector<int>")
151061da546Spatrick // first we can avoid extracting type DIEs from object files that
152061da546Spatrick // would fail the filter anyway.
153061da546Spatrick if (!has_qualified_name_hash && (context.GetSize() > 1) &&
154061da546Spatrick (context[1].tag == DW_TAG_class_type ||
155061da546Spatrick context[1].tag == DW_TAG_structure_type)) {
156dda28197Spatrick if (m_apple_types_up->FindByName(context[1].name,
157dda28197Spatrick [&](DIERef ref) { return false; }))
158061da546Spatrick return;
159061da546Spatrick }
160061da546Spatrick
161061da546Spatrick if (log)
162061da546Spatrick m_module.LogMessage(log, "FindByNameAndTag()");
163dda28197Spatrick m_apple_types_up->FindByNameAndTag(
164dda28197Spatrick type_name.GetStringRef(), tag,
165dda28197Spatrick DIERefCallback(callback, type_name.GetStringRef()));
166061da546Spatrick return;
167061da546Spatrick }
168061da546Spatrick
169dda28197Spatrick m_apple_types_up->FindByName(
170dda28197Spatrick type_name.GetStringRef(),
171dda28197Spatrick DIERefCallback(callback, type_name.GetStringRef()));
172061da546Spatrick }
173061da546Spatrick
GetNamespaces(ConstString name,llvm::function_ref<bool (DWARFDIE die)> callback)174dda28197Spatrick void AppleDWARFIndex::GetNamespaces(
175dda28197Spatrick ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
176dda28197Spatrick if (!m_apple_namespaces_up)
177dda28197Spatrick return;
178dda28197Spatrick m_apple_namespaces_up->FindByName(
179dda28197Spatrick name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
180061da546Spatrick }
181061da546Spatrick
GetFunctions(const Module::LookupInfo & lookup_info,SymbolFileDWARF & dwarf,const CompilerDeclContext & parent_decl_ctx,llvm::function_ref<bool (DWARFDIE die)> callback)182dda28197Spatrick void AppleDWARFIndex::GetFunctions(
183*f6aab3d8Srobert const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
184*f6aab3d8Srobert const CompilerDeclContext &parent_decl_ctx,
185dda28197Spatrick llvm::function_ref<bool(DWARFDIE die)> callback) {
186*f6aab3d8Srobert ConstString name = lookup_info.GetLookupName();
187dda28197Spatrick m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
188*f6aab3d8Srobert return ProcessFunctionDIE(lookup_info, die_ref, dwarf, parent_decl_ctx,
189*f6aab3d8Srobert callback);
190dda28197Spatrick });
191061da546Spatrick }
192061da546Spatrick
GetFunctions(const RegularExpression & regex,llvm::function_ref<bool (DWARFDIE die)> callback)193dda28197Spatrick void AppleDWARFIndex::GetFunctions(
194dda28197Spatrick const RegularExpression ®ex,
195dda28197Spatrick llvm::function_ref<bool(DWARFDIE die)> callback) {
196061da546Spatrick if (!m_apple_names_up)
197061da546Spatrick return;
198061da546Spatrick
199061da546Spatrick DWARFMappedHash::DIEInfoArray hash_data;
200dda28197Spatrick m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
201dda28197Spatrick DWARFMappedHash::ExtractDIEArray(hash_data,
202dda28197Spatrick DIERefCallback(callback, regex.GetText()));
203061da546Spatrick }
204061da546Spatrick
Dump(Stream & s)205061da546Spatrick void AppleDWARFIndex::Dump(Stream &s) {
206061da546Spatrick if (m_apple_names_up)
207061da546Spatrick s.PutCString(".apple_names index present\n");
208061da546Spatrick if (m_apple_namespaces_up)
209061da546Spatrick s.PutCString(".apple_namespaces index present\n");
210061da546Spatrick if (m_apple_types_up)
211061da546Spatrick s.PutCString(".apple_types index present\n");
212061da546Spatrick if (m_apple_objc_up)
213061da546Spatrick s.PutCString(".apple_objc index present\n");
214061da546Spatrick // TODO: Dump index contents
215061da546Spatrick }
216