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 ®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 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 ®ex, 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