LLDB  mainline
DebugNamesDWARFIndex.cpp
Go to the documentation of this file.
1 //===-- DebugNamesDWARFIndex.cpp ------------------------------------------===//
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 
13 #include "lldb/Core/Module.h"
15 #include "lldb/Utility/Stream.h"
16 
17 using namespace lldb_private;
18 using namespace lldb;
19 
20 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
22  DWARFDataExtractor debug_str,
24  auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(),
25  debug_str.GetAsLLVM());
26  if (llvm::Error E = index_up->extract())
27  return std::move(E);
28 
29  return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
30  module, std::move(index_up), debug_names, debug_str, dwarf));
31 }
32 
33 llvm::DenseSet<dw_offset_t>
35  llvm::DenseSet<dw_offset_t> result;
36  for (const DebugNames::NameIndex &ni : debug_names) {
37  for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
38  result.insert(ni.getCUOffset(cu));
39  }
40  return result;
41 }
42 
43 llvm::Optional<DIERef>
45  llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
46  if (!cu_offset)
47  return llvm::None;
48 
49  DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
50  if (!cu)
51  return llvm::None;
52 
53  cu = &cu->GetNonSkeletonUnit();
54  if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
55  return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(),
56  DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);
57 
58  return llvm::None;
59 }
60 
62  const DebugNames::Entry &entry,
63  llvm::function_ref<bool(DWARFDIE die)> callback, llvm::StringRef name) {
64  llvm::Optional<DIERef> ref = ToDIERef(entry);
65  if (!ref)
66  return true;
68  *llvm::cast<SymbolFileDWARF>(m_module.GetSymbolFile());
69  DWARFDIE die = dwarf.GetDIE(*ref);
70  if (!die)
71  return true;
72  return callback(die);
73 }
74 
76  const DebugNames::NameIndex &ni,
77  llvm::StringRef name) {
78  // Ignore SentinelErrors, log everything else.
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 
87  ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
88  for (const DebugNames::Entry &entry :
89  m_debug_names_up->equal_range(basename.GetStringRef())) {
90  if (entry.tag() != DW_TAG_variable)
91  continue;
92 
93  if (!ProcessEntry(entry, callback, basename.GetStringRef()))
94  return;
95  }
96 
97  m_fallback.GetGlobalVariables(basename, callback);
98 }
99 
101  const RegularExpression &regex,
102  llvm::function_ref<bool(DWARFDIE die)> callback) {
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  uint64_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  if (!ProcessEntry(*entry_or, callback,
115  llvm::StringRef(nte.getString())))
116  return;
117  }
118  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
119  }
120  }
121 
122  m_fallback.GetGlobalVariables(regex, callback);
123 }
124 
126  DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
128  uint64_t cu_offset = cu.GetOffset();
129  bool found_entry_for_cu = false;
130  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
131  for (DebugNames::NameTableEntry nte: ni) {
132  uint64_t entry_offset = nte.getEntryOffset();
133  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
134  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
135  if (entry_or->tag() != DW_TAG_variable)
136  continue;
137  if (entry_or->getCUOffset() != cu_offset)
138  continue;
139 
140  found_entry_for_cu = true;
141  if (!ProcessEntry(*entry_or, callback,
142  llvm::StringRef(nte.getString())))
143  return;
144  }
145  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
146  }
147  }
148  // If no name index for that particular CU was found, fallback to
149  // creating the manual index.
150  if (!found_entry_for_cu)
151  m_fallback.GetGlobalVariables(cu, callback);
152 }
153 
155  ConstString class_name, bool must_be_implementation,
156  llvm::function_ref<bool(DWARFDIE die)> callback) {
157  // Keep a list of incomplete types as fallback for when we don't find the
158  // complete type.
159  DIEArray incomplete_types;
160 
161  for (const DebugNames::Entry &entry :
162  m_debug_names_up->equal_range(class_name.GetStringRef())) {
163  if (entry.tag() != DW_TAG_structure_type &&
164  entry.tag() != DW_TAG_class_type)
165  continue;
166 
167  llvm::Optional<DIERef> ref = ToDIERef(entry);
168  if (!ref)
169  continue;
170 
171  DWARFUnit *cu = m_debug_info.GetUnit(*ref);
172  if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
173  incomplete_types.push_back(*ref);
174  continue;
175  }
176 
177  DWARFDIE die = m_debug_info.GetDIE(*ref);
178  if (!die) {
179  ReportInvalidDIERef(*ref, class_name.GetStringRef());
180  continue;
181  }
182 
183  if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
184  // If we find the complete version we're done.
185  callback(die);
186  return;
187  }
188  incomplete_types.push_back(*ref);
189  }
190 
191  auto dierefcallback = DIERefCallback(callback, class_name.GetStringRef());
192  for (DIERef ref : incomplete_types)
193  if (!dierefcallback(ref))
194  return;
195 
196  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
197 }
198 
200  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
201  for (const DebugNames::Entry &entry :
202  m_debug_names_up->equal_range(name.GetStringRef())) {
203  if (isType(entry.tag())) {
204  if (!ProcessEntry(entry, callback, name.GetStringRef()))
205  return;
206  }
207  }
208 
209  m_fallback.GetTypes(name, callback);
210 }
211 
213  const DWARFDeclContext &context,
214  llvm::function_ref<bool(DWARFDIE die)> callback) {
215  auto name = context[0].name;
216  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
217  if (entry.tag() == context[0].tag) {
218  if (!ProcessEntry(entry, callback, name))
219  return;
220  }
221  }
222 
223  m_fallback.GetTypes(context, callback);
224 }
225 
227  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
228  for (const DebugNames::Entry &entry :
229  m_debug_names_up->equal_range(name.GetStringRef())) {
230  if (entry.tag() == DW_TAG_namespace) {
231  if (!ProcessEntry(entry, callback, name.GetStringRef()))
232  return;
233  }
234  }
235 
236  m_fallback.GetNamespaces(name, callback);
237 }
238 
241  const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
242  llvm::function_ref<bool(DWARFDIE die)> callback) {
243 
244  std::set<DWARFDebugInfoEntry *> seen;
245  for (const DebugNames::Entry &entry :
246  m_debug_names_up->equal_range(name.GetStringRef())) {
247  Tag tag = entry.tag();
248  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
249  continue;
250 
251  if (llvm::Optional<DIERef> ref = ToDIERef(entry)) {
252  if (!ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx,
253  name_type_mask, [&](DWARFDIE die) {
254  if (!seen.insert(die.GetDIE()).second)
255  return true;
256  return callback(die);
257  }))
258  return;
259  }
260  }
261 
262  m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask,
263  callback);
264 }
265 
267  const RegularExpression &regex,
268  llvm::function_ref<bool(DWARFDIE die)> callback) {
269  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
270  for (DebugNames::NameTableEntry nte: ni) {
271  if (!regex.Execute(nte.getString()))
272  continue;
273 
274  uint64_t entry_offset = nte.getEntryOffset();
275  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
276  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
277  Tag tag = entry_or->tag();
278  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
279  continue;
280 
281  if (!ProcessEntry(*entry_or, callback,
282  llvm::StringRef(nte.getString())))
283  return;
284  }
285  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
286  }
287  }
288 
289  m_fallback.GetFunctions(regex, callback);
290 }
291 
293  m_fallback.Dump(s);
294 
295  std::string data;
296  llvm::raw_string_ostream os(data);
297  m_debug_names_up->dump(os);
298  s.PutCString(os.str());
299 }
RegularExpression.h
DIERef
Identifies a DWARF debug info entry within a given Module.
Definition: DIERef.h:26
lldb_private::DebugNamesDWARFIndex::DebugNames
llvm::DWARFDebugNames DebugNames
Definition: DebugNamesDWARFIndex.h:76
lldb_private::RegularExpression
Definition: RegularExpression.h:18
DWARF_LOG_LOOKUPS
#define DWARF_LOG_LOOKUPS
Definition: LogChannelDWARF.h:16
lldb_private::DebugNamesDWARFIndex::Dump
void Dump(Stream &s) override
Definition: DebugNamesDWARFIndex.cpp:292
Module.h
SymbolFileDWARF
Definition: SymbolFileDWARF.h:58
lldb_private::Module
Definition: Module.h:84
lldb_private::DebugNamesDWARFIndex
Definition: DebugNamesDWARFIndex.h:20
lldb_private::Stream
Definition: Stream.h:28
lldb_private::DWARFDataExtractor
Definition: DWARFDataExtractor.h:18
DWARFDeclContext.h
DIEArray
std::vector< DIERef > DIEArray
Definition: DIERef.h:63
DWARFDIE
Definition: DWARFDIE.h:16
SymbolFileDWARFDwo.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
DWARFUnit
Definition: DWARFUnit.h:80
lldb_private::DebugNamesDWARFIndex::GetUnits
static llvm::DenseSet< dw_offset_t > GetUnits(const DebugNames &debug_names)
Definition: DebugNamesDWARFIndex.cpp:34
dwarf
Definition: ABISysV_arc.cpp:61
lldb_private::ConstString::GetStringRef
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
Definition: ConstString.h:202
lldb_private::ConstString
Definition: ConstString.h:40
lldb_private::DebugNamesDWARFIndex::GetNamespaces
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:226
lldb_private::DebugNamesDWARFIndex::ProcessEntry
bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< bool(DWARFDIE die)> callback, llvm::StringRef name)
Definition: DebugNamesDWARFIndex.cpp:61
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:39
DWARFDebugInfo.h
lldb_private::CompilerDeclContext
Represents a generic declaration context in a program.
Definition: CompilerDeclContext.h:30
DWARFUnit::GetOffset
dw_offset_t GetOffset() const
Definition: DWARFUnit.h:130
lldbassert
#define lldbassert(x)
Definition: LLDBAssert.h:15
DWARFBaseDIE::GetAttributeValueAsUnsigned
uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const
Definition: DWARFBaseDIE.cpp:48
uint32_t
DWARFDIE::GetDIE
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:122
lldb_private::DebugNamesDWARFIndex::GetCompleteObjCClass
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:154
lldb_private::DebugNamesDWARFIndex::ToDIERef
llvm::Optional< DIERef > ToDIERef(const DebugNames::Entry &entry)
Definition: DebugNamesDWARFIndex.cpp:44
DWARFUnit::GetNonSkeletonUnit
DWARFUnit & GetNonSkeletonUnit()
Definition: DWARFUnit.cpp:628
DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type
bool Supports_DW_AT_APPLE_objc_complete_type()
Definition: DWARFUnit.cpp:647
lldb_private::DWARFDataExtractor::GetAsLLVM
llvm::DWARFDataExtractor GetAsLLVM() const
Definition: DWARFDataExtractor.cpp:24
DWARFDeclContext
Definition: DWARFDeclContext.h:23
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::DebugNamesDWARFIndex::MaybeLogLookupError
static void MaybeLogLookupError(llvm::Error error, const DebugNames::NameIndex &ni, llvm::StringRef name)
Definition: DebugNamesDWARFIndex.cpp:75
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::DebugNamesDWARFIndex::GetGlobalVariables
void GetGlobalVariables(ConstString basename, llvm::function_ref< bool(DWARFDIE die)> callback) override
Finds global variables with the given base name.
Definition: DebugNamesDWARFIndex.cpp:86
lldb_private::RegularExpression::Execute
bool Execute(llvm::StringRef string, llvm::SmallVectorImpl< llvm::StringRef > *matches=nullptr) const
Execute a regular expression match using the compiled regular expression that is already in this obje...
Definition: RegularExpression.cpp:23
lldb_private::DebugNamesDWARFIndex::Create
static llvm::Expected< std::unique_ptr< DebugNamesDWARFIndex > > Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, SymbolFileDWARF &dwarf)
Definition: DebugNamesDWARFIndex.cpp:21
SymbolFileDWARF::GetDwoNum
virtual llvm::Optional< uint32_t > GetDwoNum()
Definition: SymbolFileDWARF.h:277
Entry
FormatEntity::Entry Entry
Definition: FormatEntity.cpp:82
Stream.h
lldb_private::Stream::PutCString
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
DWARFUnit::GetSymbolFileDWARF
SymbolFileDWARF & GetSymbolFileDWARF() const
Definition: DWARFUnit.h:194
DebugNamesDWARFIndex.h
lldb
Definition: SBAddress.h:15
LLDB_LOG_ERROR
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:265
lldb_private::DebugNamesDWARFIndex::GetFunctions
void GetFunctions(ConstString name, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:239
lldb_private::DebugNamesDWARFIndex::GetTypes
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:199
lldb_private::LogChannelDWARF::GetLogIfAll
static Log * GetLogIfAll(uint32_t mask)
Definition: LogChannelDWARF.h:30