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