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