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