xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp (revision 8cc087a1eee9ec1ca9f7ac1e63ad51bdb5a682eb)
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 
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();
28 
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();
34 
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();
39 
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();
44 
45   if (apple_names_table_up || apple_namespaces_table_up ||
46       apple_types_table_up || apple_objc_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));
51 
52   return nullptr;
53 }
54 
55 void AppleDWARFIndex::GetGlobalVariables(
56     ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
57   if (!m_apple_names_up)
58     return;
59   m_apple_names_up->FindByName(
60       basename.GetStringRef(),
61       DIERefCallback(callback, basename.GetStringRef()));
62 }
63 
64 void AppleDWARFIndex::GetGlobalVariables(
65     const RegularExpression &regex,
66     llvm::function_ref<bool(DWARFDIE die)> callback) {
67   if (!m_apple_names_up)
68     return;
69 
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()));
75 }
76 
77 void AppleDWARFIndex::GetGlobalVariables(
78     DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
79   if (!m_apple_names_up)
80     return;
81 
82   lldbassert(!cu.GetSymbolFileDWARF().GetDwoNum());
83   const DWARFUnit &non_skeleton_cu = cu.GetNonSkeletonUnit();
84   DWARFMappedHash::DIEInfoArray hash_data;
85   m_apple_names_up->AppendAllDIEsInRange(non_skeleton_cu.GetOffset(),
86                                          non_skeleton_cu.GetNextUnitOffset(),
87                                          hash_data);
88   DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
89 }
90 
91 void AppleDWARFIndex::GetObjCMethods(
92     ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
93   if (!m_apple_objc_up)
94     return;
95   m_apple_objc_up->FindByName(
96       class_name.GetStringRef(),
97       DIERefCallback(callback, class_name.GetStringRef()));
98 }
99 
100 void AppleDWARFIndex::GetCompleteObjCClass(
101     ConstString class_name, bool must_be_implementation,
102     llvm::function_ref<bool(DWARFDIE die)> callback) {
103   if (!m_apple_types_up)
104     return;
105   m_apple_types_up->FindCompleteObjCClassByName(
106       class_name.GetStringRef(),
107       DIERefCallback(callback, class_name.GetStringRef()),
108       must_be_implementation);
109 }
110 
111 void AppleDWARFIndex::GetTypes(
112     ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
113   if (!m_apple_types_up)
114     return;
115   m_apple_types_up->FindByName(name.GetStringRef(),
116                                DIERefCallback(callback, name.GetStringRef()));
117 }
118 
119 void AppleDWARFIndex::GetTypes(
120     const DWARFDeclContext &context,
121     llvm::function_ref<bool(DWARFDIE die)> callback) {
122   if (!m_apple_types_up)
123     return;
124 
125   Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
126   const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
127       DWARFMappedHash::eAtomTypeTag);
128   const bool has_qualified_name_hash =
129       m_apple_types_up->GetHeader().header_data.ContainsAtom(
130           DWARFMappedHash::eAtomTypeQualNameHash);
131 
132   const ConstString type_name(context[0].name);
133   const dw_tag_t tag = context[0].tag;
134   if (has_tag && has_qualified_name_hash) {
135     const char *qualified_name = context.GetQualifiedName();
136     const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
137     if (log)
138       m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
139     m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
140         type_name.GetStringRef(), tag, qualified_name_hash,
141         DIERefCallback(callback, type_name.GetStringRef()));
142     return;
143   }
144 
145   if (has_tag) {
146     // When searching for a scoped type (for example,
147     // "std::vector<int>::const_iterator") searching for the innermost
148     // name alone ("const_iterator") could yield many false
149     // positives. By searching for the parent type ("vector<int>")
150     // first we can avoid extracting type DIEs from object files that
151     // would fail the filter anyway.
152     if (!has_qualified_name_hash && (context.GetSize() > 1) &&
153         (context[1].tag == DW_TAG_class_type ||
154          context[1].tag == DW_TAG_structure_type)) {
155       if (m_apple_types_up->FindByName(context[1].name,
156                                        [&](DIERef ref) { return false; }))
157         return;
158     }
159 
160     if (log)
161       m_module.LogMessage(log, "FindByNameAndTag()");
162     m_apple_types_up->FindByNameAndTag(
163         type_name.GetStringRef(), tag,
164         DIERefCallback(callback, type_name.GetStringRef()));
165     return;
166   }
167 
168   m_apple_types_up->FindByName(
169       type_name.GetStringRef(),
170       DIERefCallback(callback, type_name.GetStringRef()));
171 }
172 
173 void AppleDWARFIndex::GetNamespaces(
174     ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
175   if (!m_apple_namespaces_up)
176     return;
177   m_apple_namespaces_up->FindByName(
178       name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
179 }
180 
181 void AppleDWARFIndex::GetFunctions(
182     ConstString name, SymbolFileDWARF &dwarf,
183     const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
184     llvm::function_ref<bool(DWARFDIE die)> callback) {
185   m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
186     return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf,
187                               parent_decl_ctx, name_type_mask, callback);
188   });
189 }
190 
191 void AppleDWARFIndex::GetFunctions(
192     const RegularExpression &regex,
193     llvm::function_ref<bool(DWARFDIE die)> callback) {
194   if (!m_apple_names_up)
195     return;
196 
197   DWARFMappedHash::DIEInfoArray hash_data;
198   m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
199   DWARFMappedHash::ExtractDIEArray(hash_data,
200                                    DIERefCallback(callback, regex.GetText()));
201 }
202 
203 void AppleDWARFIndex::Dump(Stream &s) {
204   if (m_apple_names_up)
205     s.PutCString(".apple_names index present\n");
206   if (m_apple_namespaces_up)
207     s.PutCString(".apple_namespaces index present\n");
208   if (m_apple_types_up)
209     s.PutCString(".apple_types index present\n");
210   if (m_apple_objc_up)
211     s.PutCString(".apple_objc index present\n");
212   // TODO: Dump index contents
213 }
214