1 //===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===//
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/DWARFDebugInfo.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
12 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
13 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
14 
15 #include "lldb/Core/Module.h"
16 #include "lldb/Symbol/Function.h"
17 
18 using namespace lldb_private;
19 using namespace lldb;
20 
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 = llvm::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       llvm::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 = llvm::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 = llvm::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_names_table_up || apple_types_table_up ||
47       apple_objc_table_up)
48     return llvm::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 
56 void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) {
57   if (m_apple_names_up)
58     m_apple_names_up->FindByName(basename.GetStringRef(), offsets);
59 }
60 
61 void AppleDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
62                                          DIEArray &offsets) {
63   if (!m_apple_names_up)
64     return;
65 
66   DWARFMappedHash::DIEInfoArray hash_data;
67   if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
68     DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
69 }
70 
71 void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
72                                          DIEArray &offsets) {
73   if (!m_apple_names_up)
74     return;
75 
76   DWARFMappedHash::DIEInfoArray hash_data;
77   if (m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(),
78                                              cu.GetNextUnitOffset(), hash_data))
79     DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
80 }
81 
82 void AppleDWARFIndex::GetObjCMethods(ConstString class_name,
83                                      DIEArray &offsets) {
84   if (m_apple_objc_up)
85     m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets);
86 }
87 
88 void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name,
89                                            bool must_be_implementation,
90                                            DIEArray &offsets) {
91   if (m_apple_types_up) {
92     m_apple_types_up->FindCompleteObjCClassByName(
93         class_name.GetStringRef(), offsets, must_be_implementation);
94   }
95 }
96 
97 void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
98   if (m_apple_types_up)
99     m_apple_types_up->FindByName(name.GetStringRef(), offsets);
100 }
101 
102 void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context,
103                                DIEArray &offsets) {
104   if (!m_apple_types_up)
105     return;
106 
107   Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
108                                           DWARF_LOG_LOOKUPS);
109   const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
110       DWARFMappedHash::eAtomTypeTag);
111   const bool has_qualified_name_hash =
112       m_apple_types_up->GetHeader().header_data.ContainsAtom(
113           DWARFMappedHash::eAtomTypeQualNameHash);
114   const ConstString type_name(context[0].name);
115   const dw_tag_t tag = context[0].tag;
116   if (has_tag && has_qualified_name_hash) {
117     const char *qualified_name = context.GetQualifiedName();
118     const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
119     if (log)
120       m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
121     m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
122         type_name.GetStringRef(), tag, qualified_name_hash, offsets);
123   } else if (has_tag) {
124     if (log)
125       m_module.LogMessage(log, "FindByNameAndTag()");
126     m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets);
127   } else
128     m_apple_types_up->FindByName(type_name.GetStringRef(), offsets);
129 }
130 
131 void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
132   if (m_apple_namespaces_up)
133     m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
134 }
135 
136 void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info,
137                                    const CompilerDeclContext &parent_decl_ctx,
138                                    uint32_t name_type_mask,
139                                    std::vector<DWARFDIE> &dies) {
140   DIEArray offsets;
141   m_apple_names_up->FindByName(name.GetStringRef(), offsets);
142   for (const DIERef &die_ref : offsets) {
143     ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx,
144                        name_type_mask, dies);
145   }
146 }
147 
148 void AppleDWARFIndex::GetFunctions(const RegularExpression &regex,
149                                    DIEArray &offsets) {
150   if (!m_apple_names_up)
151     return;
152 
153   DWARFMappedHash::DIEInfoArray hash_data;
154   if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
155     DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
156 }
157 
158 void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset,
159                                              llvm::StringRef name) {
160   m_module.ReportErrorIfModifyDetected(
161       "the DWARF debug information has been modified (accelerator table had "
162       "bad die 0x%8.8x for '%s')\n",
163       offset, name.str().c_str());
164 }
165 
166 void AppleDWARFIndex::Dump(Stream &s) {
167   if (m_apple_names_up)
168     s.PutCString(".apple_names index present\n");
169   if (m_apple_namespaces_up)
170     s.PutCString(".apple_namespaces index present\n");
171   if (m_apple_types_up)
172     s.PutCString(".apple_types index present\n");
173   if (m_apple_objc_up)
174     s.PutCString(".apple_objc index present\n");
175   // TODO: Dump index contents
176 }
177