xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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 &regex,
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 &regex,
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