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/DWARFDebugInfo.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 12 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" 13 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" 14 15 #include "lldb/Core/Module.h" 16 #include "lldb/Symbol/Function.h" 17 18 using namespace lldb_private; 19 using namespace lldb; 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 = llvm::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 llvm::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 = llvm::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 = llvm::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_names_table_up || apple_types_table_up || 47 apple_objc_table_up) 48 return llvm::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(ConstString basename, DIEArray &offsets) { 57 if (m_apple_names_up) 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 m_apple_objc_up->FindByName(class_name.GetStringRef(), offsets); 86 } 87 88 void AppleDWARFIndex::GetCompleteObjCClass(ConstString class_name, 89 bool must_be_implementation, 90 DIEArray &offsets) { 91 if (m_apple_types_up) { 92 m_apple_types_up->FindCompleteObjCClassByName( 93 class_name.GetStringRef(), offsets, must_be_implementation); 94 } 95 } 96 97 void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { 98 if (m_apple_types_up) 99 m_apple_types_up->FindByName(name.GetStringRef(), offsets); 100 } 101 102 void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, 103 DIEArray &offsets) { 104 if (!m_apple_types_up) 105 return; 106 107 Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | 108 DWARF_LOG_LOOKUPS); 109 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom( 110 DWARFMappedHash::eAtomTypeTag); 111 const bool has_qualified_name_hash = 112 m_apple_types_up->GetHeader().header_data.ContainsAtom( 113 DWARFMappedHash::eAtomTypeQualNameHash); 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 } else if (has_tag) { 124 if (log) 125 m_module.LogMessage(log, "FindByNameAndTag()"); 126 m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); 127 } else 128 m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); 129 } 130 131 void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { 132 if (m_apple_namespaces_up) 133 m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); 134 } 135 136 void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, 137 const CompilerDeclContext &parent_decl_ctx, 138 uint32_t name_type_mask, 139 std::vector<DWARFDIE> &dies) { 140 DIEArray offsets; 141 m_apple_names_up->FindByName(name.GetStringRef(), offsets); 142 for (const DIERef &die_ref : offsets) { 143 ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx, 144 name_type_mask, dies); 145 } 146 } 147 148 void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex, 149 DIEArray &offsets) { 150 if (!m_apple_names_up) 151 return; 152 153 DWARFMappedHash::DIEInfoArray hash_data; 154 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) 155 DWARFMappedHash::ExtractDIEArray(hash_data, offsets); 156 } 157 158 void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset, 159 llvm::StringRef name) { 160 m_module.ReportErrorIfModifyDetected( 161 "the DWARF debug information has been modified (accelerator table had " 162 "bad die 0x%8.8x for '%s')\n", 163 offset, name.str().c_str()); 164 } 165 166 void AppleDWARFIndex::Dump(Stream &s) { 167 if (m_apple_names_up) 168 s.PutCString(".apple_names index present\n"); 169 if (m_apple_namespaces_up) 170 s.PutCString(".apple_namespaces index present\n"); 171 if (m_apple_types_up) 172 s.PutCString(".apple_types index present\n"); 173 if (m_apple_objc_up) 174 s.PutCString(".apple_objc index present\n"); 175 // TODO: Dump index contents 176 } 177