]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / SymbolFile / DWARF / DebugNamesDWARFIndex.cpp
1 //===-- DebugNamesDWARFIndex.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/DebugNamesDWARFIndex.h"
10 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
11 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
12 #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
13 #include "lldb/Utility/RegularExpression.h"
14 #include "lldb/Utility/Stream.h"
15
16 using namespace lldb_private;
17 using namespace lldb;
18
19 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
20 DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
21                              DWARFDataExtractor debug_str,
22                              DWARFDebugInfo *debug_info) {
23   if (!debug_info) {
24     return llvm::make_error<llvm::StringError>("debug info null",
25                                                llvm::inconvertibleErrorCode());
26   }
27   auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(),
28                                                 debug_str.GetAsLLVM());
29   if (llvm::Error E = index_up->extract())
30     return std::move(E);
31
32   return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
33       module, std::move(index_up), debug_names, debug_str, *debug_info));
34 }
35
36 llvm::DenseSet<dw_offset_t>
37 DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
38   llvm::DenseSet<dw_offset_t> result;
39   for (const DebugNames::NameIndex &ni : debug_names) {
40     for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
41       result.insert(ni.getCUOffset(cu));
42   }
43   return result;
44 }
45
46 llvm::Optional<DIERef>
47 DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) {
48   llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
49   if (!cu_offset)
50     return llvm::None;
51
52   DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
53   if (!cu)
54     return llvm::None;
55
56   // This initializes the DWO symbol file. It's not possible for
57   // GetDwoSymbolFile to call this automatically because of mutual recursion
58   // between this and DWARFDebugInfoEntry::GetAttributeValue.
59   cu->ExtractUnitDIEIfNeeded();
60   cu = &cu->GetNonSkeletonUnit();
61
62   if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
63     return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(),
64                   DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);
65
66   return llvm::None;
67 }
68
69 void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry,
70                                   DIEArray &offsets) {
71   if (llvm::Optional<DIERef> ref = ToDIERef(entry))
72     offsets.push_back(*ref);
73 }
74
75 void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
76                                                const DebugNames::NameIndex &ni,
77                                                llvm::StringRef name) {
78   // Ignore SentinelErrors, log everything else.
79   LLDB_LOG_ERROR(
80       LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS),
81       handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
82       "Failed to parse index entries for index at {1:x}, name {2}: {0}",
83       ni.getUnitOffset(), name);
84 }
85
86 void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename,
87                                               DIEArray &offsets) {
88   m_fallback.GetGlobalVariables(basename, offsets);
89
90   for (const DebugNames::Entry &entry :
91        m_debug_names_up->equal_range(basename.GetStringRef())) {
92     if (entry.tag() != DW_TAG_variable)
93       continue;
94
95     Append(entry, offsets);
96   }
97 }
98
99 void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression &regex,
100                                               DIEArray &offsets) {
101   m_fallback.GetGlobalVariables(regex, offsets);
102
103   for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
104     for (DebugNames::NameTableEntry nte: ni) {
105       if (!regex.Execute(nte.getString()))
106         continue;
107
108       uint32_t entry_offset = nte.getEntryOffset();
109       llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
110       for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
111         if (entry_or->tag() != DW_TAG_variable)
112           continue;
113
114         Append(*entry_or, offsets);
115       }
116       MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
117     }
118   }
119 }
120
121 void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu,
122                                               DIEArray &offsets) {
123   m_fallback.GetGlobalVariables(cu, offsets);
124
125   uint64_t cu_offset = cu.GetOffset();
126   for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
127     for (DebugNames::NameTableEntry nte: ni) {
128       uint32_t entry_offset = nte.getEntryOffset();
129       llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
130       for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
131         if (entry_or->tag() != DW_TAG_variable)
132           continue;
133         if (entry_or->getCUOffset() != cu_offset)
134           continue;
135
136         Append(*entry_or, offsets);
137       }
138       MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
139     }
140   }
141 }
142
143 void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name,
144                                                 bool must_be_implementation,
145                                                 DIEArray &offsets) {
146   m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets);
147
148   // Keep a list of incomplete types as fallback for when we don't find the
149   // complete type.
150   DIEArray incomplete_types;
151
152   for (const DebugNames::Entry &entry :
153        m_debug_names_up->equal_range(class_name.GetStringRef())) {
154     if (entry.tag() != DW_TAG_structure_type &&
155         entry.tag() != DW_TAG_class_type)
156       continue;
157
158     llvm::Optional<DIERef> ref = ToDIERef(entry);
159     if (!ref)
160       continue;
161
162     DWARFUnit *cu = m_debug_info.GetUnit(*ref);
163     if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
164       incomplete_types.push_back(*ref);
165       continue;
166     }
167
168     // FIXME: We should return DWARFDIEs so we don't have to resolve it twice.
169     DWARFDIE die = m_debug_info.GetDIE(*ref);
170     if (!die)
171       continue;
172
173     if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
174       // If we find the complete version we're done.
175       offsets.push_back(*ref);
176       return;
177     } else {
178       incomplete_types.push_back(*ref);
179     }
180   }
181
182   offsets.insert(offsets.end(), incomplete_types.begin(),
183                  incomplete_types.end());
184 }
185
186 void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) {
187   m_fallback.GetTypes(name, offsets);
188
189   for (const DebugNames::Entry &entry :
190        m_debug_names_up->equal_range(name.GetStringRef())) {
191     if (isType(entry.tag()))
192       Append(entry, offsets);
193   }
194 }
195
196 void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context,
197                                     DIEArray &offsets) {
198   m_fallback.GetTypes(context, offsets);
199
200   for (const DebugNames::Entry &entry :
201        m_debug_names_up->equal_range(context[0].name)) {
202     if (entry.tag() == context[0].tag)
203       Append(entry, offsets);
204   }
205 }
206
207 void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) {
208   m_fallback.GetNamespaces(name, offsets);
209
210   for (const DebugNames::Entry &entry :
211        m_debug_names_up->equal_range(name.GetStringRef())) {
212     if (entry.tag() == DW_TAG_namespace)
213       Append(entry, offsets);
214   }
215 }
216
217 void DebugNamesDWARFIndex::GetFunctions(
218     ConstString name, SymbolFileDWARF &dwarf,
219     const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
220     std::vector<DWARFDIE> &dies) {
221
222   std::vector<DWARFDIE> v;
223   m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask, v);
224
225   for (const DebugNames::Entry &entry :
226        m_debug_names_up->equal_range(name.GetStringRef())) {
227     Tag tag = entry.tag();
228     if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
229       continue;
230
231     if (llvm::Optional<DIERef> ref = ToDIERef(entry))
232       ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx,
233                          name_type_mask, v);
234   }
235
236   std::set<DWARFDebugInfoEntry *> seen;
237   for (DWARFDIE die : v)
238     if (seen.insert(die.GetDIE()).second)
239       dies.push_back(die);
240 }
241
242 void DebugNamesDWARFIndex::GetFunctions(const RegularExpression &regex,
243                                         DIEArray &offsets) {
244   m_fallback.GetFunctions(regex, offsets);
245
246   for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
247     for (DebugNames::NameTableEntry nte: ni) {
248       if (!regex.Execute(nte.getString()))
249         continue;
250
251       uint32_t entry_offset = nte.getEntryOffset();
252       llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
253       for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
254         Tag tag = entry_or->tag();
255         if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
256           continue;
257
258         Append(*entry_or, offsets);
259       }
260       MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
261     }
262   }
263 }
264
265 void DebugNamesDWARFIndex::Dump(Stream &s) {
266   m_fallback.Dump(s);
267
268   std::string data;
269   llvm::raw_string_ostream os(data);
270   m_debug_names_up->dump(os);
271   s.PutCString(os.str());
272 }