1 //===-- AppleDWARFIndex.cpp ------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Plugins/SymbolFile/DWARF/AppleDWARFIndex.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 12 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 13 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" 14 #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" 15 16 #include "lldb/Core/Module.h" 17 #include "lldb/Symbol/Function.h" 18 19 using namespace lldb_private; 20 using namespace lldb; 21 22 std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create( 23 Module &module, DWARFDataExtractor apple_names, 24 DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types, 25 DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) { 26 auto apple_names_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( 27 apple_names, debug_str, ".apple_names"); 28 if (!apple_names_table_up->IsValid()) 29 apple_names_table_up.reset(); 30 31 auto apple_namespaces_table_up = 32 llvm::make_unique<DWARFMappedHash::MemoryTable>( 33 apple_namespaces, debug_str, ".apple_namespaces"); 34 if (!apple_namespaces_table_up->IsValid()) 35 apple_namespaces_table_up.reset(); 36 37 auto apple_types_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( 38 apple_types, debug_str, ".apple_types"); 39 if (!apple_types_table_up->IsValid()) 40 apple_types_table_up.reset(); 41 42 auto apple_objc_table_up = llvm::make_unique<DWARFMappedHash::MemoryTable>( 43 apple_objc, debug_str, ".apple_objc"); 44 if (!apple_objc_table_up->IsValid()) 45 apple_objc_table_up.reset(); 46 47 if (apple_names_table_up || apple_names_table_up || apple_types_table_up || 48 apple_objc_table_up) 49 return llvm::make_unique<AppleDWARFIndex>( 50 module, std::move(apple_names_table_up), 51 std::move(apple_namespaces_table_up), std::move(apple_types_table_up), 52 std::move(apple_objc_table_up)); 53 54 return nullptr; 55 } 56 57 void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) { 58 if (m_apple_names_up) 59 m_apple_names_up->FindByName(basename.GetStringRef(), offsets); 60 } 61 62 void AppleDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, 63 DIEArray &offsets) { 64 if (!m_apple_names_up) 65 return; 66 67 DWARFMappedHash::DIEInfoArray hash_data; 68 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) 69 DWARFMappedHash::ExtractDIEArray(hash_data, offsets); 70 } 71 72 void AppleDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, 73 DIEArray &offsets) { 74 if (!m_apple_names_up) 75 return; 76 77 DWARFMappedHash::DIEInfoArray hash_data; 78 if (m_apple_names_up->AppendAllDIEsInRange( 79 cu.GetOffset(), cu.GetNextCompileUnitOffset(), hash_data)) 80 DWARFMappedHash::ExtractDIEArray(hash_data, offsets); 81 } 82 83 void AppleDWARFIndex::GetObjCMethods(ConstString class_name, 84 DIEArray &offsets) { 85 if (m_apple_objc_up) 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 m_apple_types_up->FindCompleteObjCClassByName( 94 class_name.GetStringRef(), offsets, must_be_implementation); 95 } 96 } 97 98 void AppleDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { 99 if (m_apple_types_up) 100 m_apple_types_up->FindByName(name.GetStringRef(), offsets); 101 } 102 103 void AppleDWARFIndex::GetTypes(const DWARFDeclContext &context, 104 DIEArray &offsets) { 105 if (!m_apple_types_up) 106 return; 107 108 Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION | 109 DWARF_LOG_LOOKUPS); 110 const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom( 111 DWARFMappedHash::eAtomTypeTag); 112 const bool has_qualified_name_hash = 113 m_apple_types_up->GetHeader().header_data.ContainsAtom( 114 DWARFMappedHash::eAtomTypeQualNameHash); 115 const ConstString type_name(context[0].name); 116 const dw_tag_t tag = context[0].tag; 117 if (has_tag && has_qualified_name_hash) { 118 const char *qualified_name = context.GetQualifiedName(); 119 const uint32_t qualified_name_hash = llvm::djbHash(qualified_name); 120 if (log) 121 m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); 122 m_apple_types_up->FindByNameAndTagAndQualifiedNameHash( 123 type_name.GetStringRef(), tag, qualified_name_hash, offsets); 124 } else if (has_tag) { 125 if (log) 126 m_module.LogMessage(log, "FindByNameAndTag()"); 127 m_apple_types_up->FindByNameAndTag(type_name.GetStringRef(), tag, offsets); 128 } else 129 m_apple_types_up->FindByName(type_name.GetStringRef(), offsets); 130 } 131 132 void AppleDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { 133 if (m_apple_namespaces_up) 134 m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); 135 } 136 137 void AppleDWARFIndex::GetFunctions(ConstString name, DWARFDebugInfo &info, 138 const CompilerDeclContext &parent_decl_ctx, 139 uint32_t name_type_mask, 140 std::vector<DWARFDIE> &dies) { 141 DIEArray offsets; 142 m_apple_names_up->FindByName(name.GetStringRef(), offsets); 143 for (const DIERef &die_ref : offsets) { 144 ProcessFunctionDIE(name.GetStringRef(), die_ref, info, parent_decl_ctx, 145 name_type_mask, dies); 146 } 147 } 148 149 void AppleDWARFIndex::GetFunctions(const RegularExpression ®ex, 150 DIEArray &offsets) { 151 if (!m_apple_names_up) 152 return; 153 154 DWARFMappedHash::DIEInfoArray hash_data; 155 if (m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data)) 156 DWARFMappedHash::ExtractDIEArray(hash_data, offsets); 157 } 158 159 void AppleDWARFIndex::ReportInvalidDIEOffset(dw_offset_t offset, 160 llvm::StringRef name) { 161 m_module.ReportErrorIfModifyDetected( 162 "the DWARF debug information has been modified (accelerator table had " 163 "bad die 0x%8.8x for '%s')\n", 164 offset, name.str().c_str()); 165 } 166 167 void AppleDWARFIndex::Dump(Stream &s) { 168 if (m_apple_names_up) 169 s.PutCString(".apple_names index present\n"); 170 if (m_apple_namespaces_up) 171 s.PutCString(".apple_namespaces index present\n"); 172 if (m_apple_types_up) 173 s.PutCString(".apple_types index present\n"); 174 if (m_apple_objc_up) 175 s.PutCString(".apple_objc index present\n"); 176 // TODO: Dump index contents 177 } 178