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 "lldb/Utility/RegularExpression.h" 12 #include "lldb/Utility/Stream.h" 13 14 using namespace lldb_private; 15 using namespace lldb; 16 17 static llvm::DWARFDataExtractor ToLLVM(const DWARFDataExtractor &data) { 18 return llvm::DWARFDataExtractor( 19 llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()), 20 data.GetByteSize()), 21 data.GetByteOrder() == eByteOrderLittle, data.GetAddressByteSize()); 22 } 23 24 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> 25 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, 26 DWARFDataExtractor debug_str, 27 DWARFDebugInfo *debug_info) { 28 auto index_up = 29 llvm::make_unique<DebugNames>(ToLLVM(debug_names), ToLLVM(debug_str)); 30 if (llvm::Error E = index_up->extract()) 31 return std::move(E); 32 33 return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex( 34 module, std::move(index_up), debug_names, debug_str, debug_info)); 35 } 36 37 llvm::DenseSet<dw_offset_t> 38 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { 39 llvm::DenseSet<dw_offset_t> result; 40 for (const DebugNames::NameIndex &ni : debug_names) { 41 for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu) 42 result.insert(ni.getCUOffset(cu)); 43 } 44 return result; 45 } 46 47 void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, 48 DIEArray &offsets) { 49 llvm::Optional<uint64_t> cu_offset = entry.getCUOffset(); 50 llvm::Optional<uint64_t> die_offset = entry.getDIESectionOffset(); 51 if (cu_offset && die_offset) 52 offsets.emplace_back(*cu_offset, *die_offset); 53 } 54 55 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, 56 const DebugNames::NameIndex &ni, 57 llvm::StringRef name) { 58 // Ignore SentinelErrors, log everything else. 59 LLDB_LOG_ERROR( 60 LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS), 61 handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}), 62 "Failed to parse index entries for index at {1:x}, name {2}: {0}", 63 ni.getUnitOffset(), name); 64 } 65 66 void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename, 67 DIEArray &offsets) { 68 m_fallback.GetGlobalVariables(basename, offsets); 69 70 for (const DebugNames::Entry &entry : 71 m_debug_names_up->equal_range(basename.GetStringRef())) { 72 if (entry.tag() != DW_TAG_variable) 73 continue; 74 75 Append(entry, offsets); 76 } 77 } 78 79 void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, 80 DIEArray &offsets) { 81 m_fallback.GetGlobalVariables(regex, offsets); 82 83 for (const DebugNames::NameIndex &ni: *m_debug_names_up) { 84 for (DebugNames::NameTableEntry nte: ni) { 85 if (!regex.Execute(nte.getString())) 86 continue; 87 88 uint32_t entry_offset = nte.getEntryOffset(); 89 llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); 90 for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { 91 if (entry_or->tag() != DW_TAG_variable) 92 continue; 93 94 Append(*entry_or, offsets); 95 } 96 MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); 97 } 98 } 99 } 100 101 void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { 102 m_fallback.GetTypes(name, offsets); 103 104 for (const DebugNames::Entry &entry : 105 m_debug_names_up->equal_range(name.GetStringRef())) { 106 if (isType(entry.tag())) 107 Append(entry, offsets); 108 } 109 } 110 111 void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { 112 m_fallback.GetNamespaces(name, offsets); 113 114 for (const DebugNames::Entry &entry : 115 m_debug_names_up->equal_range(name.GetStringRef())) { 116 if (entry.tag() == DW_TAG_namespace) 117 Append(entry, offsets); 118 } 119 } 120 121 void DebugNamesDWARFIndex::Dump(Stream &s) { 122 m_fallback.Dump(s); 123 124 std::string data; 125 llvm::raw_string_ostream os(data); 126 m_debug_names_up->dump(os); 127 s.PutCString(os.str()); 128 } 129