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