1 //===-- DebugNamesDWARFIndex.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/DebugNamesDWARFIndex.h" 11 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" 12 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" 13 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" 14 #include "lldb/Utility/RegularExpression.h" 15 #include "lldb/Utility/Stream.h" 16 17 using namespace lldb_private; 18 using namespace lldb; 19 20 static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) { 21 return llvm::DWARFDataExtractor( 22 llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()), 23 data.GetByteSize()), 24 data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize()); 25 } 26 27 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> 28 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, 29 DWARFDataExtractor debug_str, 30 DWARFDebugInfo *debug_info) { 31 if (!debug_info) { 32 return llvm::make_error<llvm::StringError>("debug info null", 33 llvm::inconvertibleErrorCode()); 34 } 35 auto index_up = 36 llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str)); 37 if (llvm::Error E = index_up->extract()) 38 return std::move(E); 39 40 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex( 41 module, std::move(index_up), debug_names, debug_str, *debug_info)); 42 } 43 44 llvm::DenseSet<dw_offset_t> 45 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { 46 llvm::DenseSet<dw_offset_t> result; 47 for (const DebugNames::NameIndex &ni : debug_names) { 48 for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu) 49 result.insert(ni.getCUOffset(cu)); 50 } 51 return result; 52 } 53 54 DIERef DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { 55 llvm::Optional<uint64_t> cu_offset = entry.getCUOffset(); 56 if (!cu_offset) 57 return DIERef(); 58 59 DWARFUnit *cu = m_debug_info.GetCompileUnit(*cu_offset); 60 if (!cu) 61 return DIERef(); 62 63 // This initializes the DWO symbol file. It's not possible for 64 // GetDwoSymbolFile to call this automatically because of mutual recursion 65 // between this and DWARFDebugInfoEntry::GetAttributeValue. 66 cu->ExtractUnitDIEIfNeeded(); 67 uint64_t die_bias = cu->GetDwoSymbolFile() ? 0 : *cu_offset; 68 69 if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset()) 70 return DIERef(*cu_offset, die_bias + *die_offset); 71 72 return DIERef(); 73 } 74 75 void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, 76 DIEArray &offsets) { 77 if (DIERef ref = ToDIERef(entry)) 78 offsets.push_back(ref); 79 } 80 81 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, 82 const DebugNames::NameIndex &ni, 83 llvm::StringRef name) { 84 // Ignore SentinelErrors, log everything else. 85 LLDB_LOG_ERROR( 86 LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS), 87 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}), 88 "Failed to parse index entries for index at {1:x}, name {2}: {0}", 89 ni.getUnitOffset(), name); 90 } 91 92 void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename, 93 DIEArray &offsets) { 94 m_fallback.GetGlobalVariables(basename, offsets); 95 96 for (const DebugNames::Entry &entry : 97 m_debug_names_up->equal_range(basename.GetStringRef())) { 98 if (entry.tag() != DW_TAG_variable) 99 continue; 100 101 Append(entry, offsets); 102 } 103 } 104 105 void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, 106 DIEArray &offsets) { 107 m_fallback.GetGlobalVariables(regex, offsets); 108 109 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 110 for (DebugNames::NameTableEntry nte: ni) { 111 if (!regex.Execute(nte.getString())) 112 continue; 113 114 uint32_t entry_offset = nte.getEntryOffset(); 115 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 116 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 117 if (entry_or->tag() != DW_TAG_variable) 118 continue; 119 120 Append(*entry_or, offsets); 121 } 122 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 123 } 124 } 125 } 126 127 void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, 128 DIEArray &offsets) { 129 m_fallback.GetGlobalVariables(cu, offsets); 130 131 uint64_t cu_offset = cu.GetOffset(); 132 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 133 for (DebugNames::NameTableEntry nte: ni) { 134 uint32_t entry_offset = nte.getEntryOffset(); 135 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 136 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 137 if (entry_or->tag() != DW_TAG_variable) 138 continue; 139 if (entry_or->getCUOffset() != cu_offset) 140 continue; 141 142 Append(*entry_or, offsets); 143 } 144 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 145 } 146 } 147 } 148 149 void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { 150 m_fallback.GetTypes(name, offsets); 151 152 for (const DebugNames::Entry &entry : 153 m_debug_names_up->equal_range(name.GetStringRef())) { 154 if (isType(entry.tag())) 155 Append(entry, offsets); 156 } 157 } 158 159 void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context, 160 DIEArray &offsets) { 161 m_fallback.GetTypes(context, offsets); 162 163 for (const DebugNames::Entry &entry : 164 m_debug_names_up->equal_range(context[0].name)) { 165 if (entry.tag() == context[0].tag) 166 Append(entry, offsets); 167 } 168 } 169 170 void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { 171 m_fallback.GetNamespaces(name, offsets); 172 173 for (const DebugNames::Entry &entry : 174 m_debug_names_up->equal_range(name.GetStringRef())) { 175 if (entry.tag() == DW_TAG_namespace) 176 Append(entry, offsets); 177 } 178 } 179 180 void DebugNamesDWARFIndex::GetFunctions( 181 ConstString name, DWARFDebugInfo &info, 182 const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, 183 std::vector<DWARFDIE> &dies) { 184 185 m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, dies); 186 187 for (const DebugNames::Entry &entry : 188 m_debug_names_up->equal_range(name.GetStringRef())) { 189 Tag tag = entry.tag(); 190 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) 191 continue; 192 193 if (DIERef ref = ToDIERef(entry)) 194 ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx, 195 name_type_mask, dies); 196 } 197 } 198 199 void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex, 200 DIEArray &offsets) { 201 m_fallback.GetFunctions(regex, offsets); 202 203 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 204 for (DebugNames::NameTableEntry nte: ni) { 205 if (!regex.Execute(nte.getString())) 206 continue; 207 208 uint32_t entry_offset = nte.getEntryOffset(); 209 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 210 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 211 Tag tag = entry_or->tag(); 212 if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) 213 continue; 214 215 Append(*entry_or, offsets); 216 } 217 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 218 } 219 } 220 } 221 222 void DebugNamesDWARFIndex::Dump(Stream &s) { 223 m_fallback.Dump(s); 224 225 std::string data; 226 llvm::raw_string_ostream os(data); 227 m_debug_names_up->dump(os); 228 s.PutCString(os.str()); 229 } 230