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_names_table_up || apple_types_table_up || 46 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(DIERef ref)> callback) { 57 if (!m_apple_names_up) 58 return; 59 m_apple_names_up->FindByName(basename.GetStringRef(), callback); 60 } 61 62 void AppleDWARFIndex::GetGlobalVariables( 63 const RegularExpression ®ex, 64 llvm::function_ref<bool(DIERef ref)> callback) { 65 if (!m_apple_names_up) 66 return; 67 68 DWARFMappedHash::DIEInfoArray hash_data; 69 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data); 70 DWARFMappedHash::ExtractDIEArray(hash_data, callback); 71 } 72 73 void AppleDWARFIndex::GetGlobalVariables( 74 const DWARFUnit &cu, llvm::function_ref<bool(DIERef ref)> callback) { 75 if (!m_apple_names_up) 76 return; 77 78 DWARFMappedHash::DIEInfoArray hash_data; 79 m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), cu.GetNextUnitOffset(), 80 hash_data); 81 DWARFMappedHash::ExtractDIEArray(hash_data, callback); 82 } 83 84 void AppleDWARFIndex::GetObjCMethods( 85 ConstString class_name, llvm::function_ref<bool(DIERef ref)> callback) { 86 if (!m_apple_objc_up) 87 return; 88 m_apple_objc_up->FindByName(class_name.GetStringRef(), callback); 89 } 90 91 void AppleDWARFIndex::GetCompleteObjCClass( 92 ConstString class_name, bool must_be_implementation, 93 llvm::function_ref<bool(DIERef ref)> callback) { 94 if (!m_apple_types_up) 95 return; 96 m_apple_types_up->FindCompleteObjCClassByName( 97 class_name.GetStringRef(), callback, must_be_implementation); 98 } 99 100 void AppleDWARFIndex::GetTypes(ConstString name, 101 llvm::function_ref<bool(DIERef ref)> callback) { 102 if (!m_apple_types_up) 103 return; 104 m_apple_types_up->FindByName(name.GetStringRef(), callback); 105 } 106 107 void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, 108 llvm::function_ref<bool(DIERef ref)> callback) { 109 if (!m_apple_types_up) 110 return; 111 112 Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | 113 DWARF_LOG_LOOKUPS); 114 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom( 115 DWARFMappedHash::eAtomTypeTag); 116 const bool has_qualified_name_hash = 117 m_apple_types_up->GetHeader().header_data.ContainsAtom( 118 DWARFMappedHash::eAtomTypeQualNameHash); 119 120 const ConstString type_name(context[0].name); 121 const dw_tag_t tag = context[0].tag; 122 if (has_tag && has_qualified_name_hash) { 123 const char *qualified_name = context.GetQualifiedName(); 124 const uint32_t qualified_name_hash = llvm::djbHash(qualified_name); 125 if (log) 126 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); 127 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( 128 type_name.GetStringRef(), tag, qualified_name_hash, callback); 129 return; 130 } 131 132 if (has_tag) { 133 // When searching for a scoped type (for example, 134 // "std::vector<int>::const_iterator") searching for the innermost 135 // name alone ("const_iterator") could yield many false 136 // positives. By searching for the parent type ("vector<int>") 137 // first we can avoid extracting type DIEs from object files that 138 // would fail the filter anyway. 139 if (!has_qualified_name_hash && (context.GetSize() > 1) && 140 (context[1].tag == DW_TAG_class_type || 141 context[1].tag == DW_TAG_structure_type)) { 142 if (m_apple_types_up->FindByName(context[1].name, 143 [&](DIERef ref) { return false; })) 144 return; 145 } 146 147 if (log) 148 m_module.LogMessage(log, "FindByNameAndTag()"); 149 m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, callback); 150 return; 151 } 152 153 m_apple_types_up->FindByName(type_name.GetStringRef(), callback); 154 } 155 156 void AppleDWARFIndex::GetNamespaces( 157 ConstString name, llvm::function_ref<bool(DIERef ref)> callback) { 158 if (!m_apple_namespaces_up) 159 return; 160 m_apple_namespaces_up->FindByName(name.GetStringRef(), callback); 161 } 162 163 void AppleDWARFIndex::GetFunctions( 164 ConstString name, SymbolFileDWARF &dwarf, 165 const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, 166 llvm::function_ref<bool(DWARFDIE die)> callback) { 167 m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) { 168 return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, 169 parent_decl_ctx, name_type_mask, callback); 170 }); 171 } 172 173 void AppleDWARFIndex::GetFunctions( 174 const RegularExpression ®ex, 175 llvm::function_ref<bool(DIERef ref)> callback) { 176 if (!m_apple_names_up) 177 return; 178 179 DWARFMappedHash::DIEInfoArray hash_data; 180 m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data); 181 DWARFMappedHash::ExtractDIEArray(hash_data, callback); 182 } 183 184 void AppleDWARFIndex::ReportInvalidDIERef(const DIERef &ref, 185 llvm::StringRef name) { 186 m_module.ReportErrorIfModifyDetected( 187 "the DWARF debug information has been modified (accelerator table had " 188 "bad die 0x%8.8x for '%s')\n", 189 ref.die_offset(), name.str().c_str()); 190 } 191 192 void AppleDWARFIndex::Dump(Stream &s) { 193 if (m_apple_names_up) 194 s.PutCString(".apple_names index present\n"); 195 if (m_apple_namespaces_up) 196 s.PutCString(".apple_namespaces index present\n"); 197 if (m_apple_types_up) 198 s.PutCString(".apple_types index present\n"); 199 if (m_apple_objc_up) 200 s.PutCString(".apple_objc index present\n"); 201 // TODO: Dump index contents 202 } 203