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 = llvm::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 llvm::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 = llvm::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 = llvm::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 llvm::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 const ConstString type_name(context[0].name); 114 const dw_tag_t tag = context[0].tag; 115 if (has_tag && has_qualified_name_hash) { 116 const char *qualified_name = context.GetQualifiedName(); 117 const uint32_t qualified_name_hash = llvm::djbHash(qualified_name); 118 if (log) 119 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); 120 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( 121 type_name.GetStringRef(), tag, qualified_name_hash, offsets); 122 } else if (has_tag) { 123 if (log) 124 m_module.LogMessage(log, "FindByNameAndTag()"); 125 m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); 126 } else 127 m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); 128 } 129 130 void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { 131 if (m_apple_namespaces_up) 132 m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); 133 } 134 135 void AppleDWARFIndex::GetFunctions(ConstString name, SymbolFileDWARF &dwarf, 136 const CompilerDeclContext &parent_decl_ctx, 137 uint32_t name_type_mask, 138 std::vector<DWARFDIE> &dies) { 139 DIEArray offsets; 140 m_apple_names_up->FindByName(name.GetStringRef(), offsets); 141 for (const DIERef &die_ref : offsets) { 142 ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf, parent_decl_ctx, 143 name_type_mask, dies); 144 } 145 } 146 147 void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex, 148 DIEArray &offsets) { 149 if (!m_apple_names_up) 150 return; 151 152 DWARFMappedHash::DIEInfoArray hash_data; 153 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) 154 DWARFMappedHash::ExtractDIEArray(hash_data, offsets); 155 } 156 157 void AppleDWARFIndex::ReportInvalidDIERef(const DIERef &ref, 158 llvm::StringRef name) { 159 m_module.ReportErrorIfModifyDetected( 160 "the DWARF debug information has been modified (accelerator table had " 161 "bad die 0x%8.8x for '%s')\n", 162 ref.die_offset(), name.str().c_str()); 163 } 164 165 void AppleDWARFIndex::Dump(Stream &s) { 166 if (m_apple_names_up) 167 s.PutCString(".apple_names index present\n"); 168 if (m_apple_namespaces_up) 169 s.PutCString(".apple_namespaces index present\n"); 170 if (m_apple_types_up) 171 s.PutCString(".apple_types index present\n"); 172 if (m_apple_objc_up) 173 s.PutCString(".apple_objc index present\n"); 174 // TODO: Dump index contents 175 } 176