1 //===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===//
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(ConstString basename, DIEArray &offsets) {
57 m_apple_names_up->FindByName(basename.GetStringRef(), offsets);
60 void AppleDWARFIndex::GetGlobalVariables(const RegularExpression ®ex,
62 if (!m_apple_names_up)
65 DWARFMappedHash::DIEInfoArray hash_data;
66 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
67 DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
70 void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
72 if (!m_apple_names_up)
75 DWARFMappedHash::DIEInfoArray hash_data;
76 if (m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(),
77 cu.GetNextUnitOffset(), hash_data))
78 DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
81 void AppleDWARFIndex::GetObjCMethods(ConstString class_name,
84 m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets);
87 void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name,
88 bool must_be_implementation,
90 if (m_apple_types_up) {
91 m_apple_types_up->FindCompleteObjCClassByName(
92 class_name.GetStringRef(), offsets, must_be_implementation);
96 void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
98 m_apple_types_up->FindByName(name.GetStringRef(), offsets);
101 void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context,
103 if (!m_apple_types_up)
106 Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
108 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
109 DWARFMappedHash::eAtomTypeTag);
110 const bool has_qualified_name_hash =
111 m_apple_types_up->GetHeader().header_data.ContainsAtom(
112 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);
120 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
121 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
122 type_name.GetStringRef(), tag, qualified_name_hash, offsets);
127 // When searching for a scoped type (for example,
128 // "std::vector<int>::const_iterator") searching for the innermost
129 // name alone ("const_iterator") could yield many false
130 // positives. By searching for the parent type ("vector<int>")
131 // first we can avoid extracting type DIEs from object files that
132 // would fail the filter anyway.
133 if (!has_qualified_name_hash && (context.GetSize() > 1) &&
134 (context[1].tag == DW_TAG_class_type ||
135 context[1].tag == DW_TAG_structure_type)) {
136 DIEArray class_matches;
137 m_apple_types_up->FindByName(context[1].name, class_matches);
138 if (class_matches.empty())
143 m_module.LogMessage(log, "FindByNameAndTag()");
144 m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets);
148 m_apple_types_up->FindByName(type_name.GetStringRef(), offsets);
151 void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
152 if (m_apple_namespaces_up)
153 m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets);
156 void AppleDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf,
157 const CompilerDeclContext &parent_decl_ctx,
158 uint32_t name_type_mask,
159 std::vector<DWARFDIE> &dies) {
161 m_apple_names_up->FindByName(name.GetStringRef(), offsets);
162 for (const DIERef &die_ref : offsets) {
163 ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, parent_decl_ctx,
164 name_type_mask, dies);
168 void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex,
170 if (!m_apple_names_up)
173 DWARFMappedHash::DIEInfoArray hash_data;
174 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data))
175 DWARFMappedHash::ExtractDIEArray(hash_data, offsets);
178 void AppleDWARFIndex::ReportInvalidDIERef(const DIERef &ref,
179 llvm::StringRef name) {
180 m_module.ReportErrorIfModifyDetected(
181 "the DWARF debug information has been modified (accelerator table had "
182 "bad die 0x%8.8x for '%s')\n",
183 ref.die_offset(), name.str().c_str());
186 void AppleDWARFIndex::Dump(Stream &s) {
187 if (m_apple_names_up)
188 s.PutCString(".apple_names index present\n");
189 if (m_apple_namespaces_up)
190 s.PutCString(".apple_namespaces index present\n");
191 if (m_apple_types_up)
192 s.PutCString(".apple_types index present\n");
194 s.PutCString(".apple_objc index present\n");
195 // TODO: Dump index contents