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 &regex,
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