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 #include <optional>
17 
18 using namespace lldb_private;
19 using namespace lldb;
20 using namespace lldb_private::dwarf;
21 
22 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
24  DWARFDataExtractor debug_str,
26  auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(),
27  debug_str.GetAsLLVM());
28  if (llvm::Error E = index_up->extract())
29  return std::move(E);
30 
31  return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
32  module, std::move(index_up), debug_names, debug_str, dwarf));
33 }
34 
35 llvm::DenseSet<dw_offset_t>
37  llvm::DenseSet<dw_offset_t> result;
38  for (const DebugNames::NameIndex &ni : debug_names) {
39  for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
40  result.insert(ni.getCUOffset(cu));
41  }
42  return result;
43 }
44 
45 std::optional<DIERef>
47  std::optional<uint64_t> cu_offset = entry.getCUOffset();
48  if (!cu_offset)
49  return std::nullopt;
50 
51  DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
52  if (!cu)
53  return std::nullopt;
54 
55  cu = &cu->GetNonSkeletonUnit();
56  if (std::optional<uint64_t> die_offset = entry.getDIEUnitOffset())
57  return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(),
58  DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);
59 
60  return std::nullopt;
61 }
62 
64  const DebugNames::Entry &entry,
65  llvm::function_ref<bool(DWARFDIE die)> callback, llvm::StringRef name) {
66  std::optional<DIERef> ref = ToDIERef(entry);
67  if (!ref)
68  return true;
69  SymbolFileDWARF &dwarf = *llvm::cast<SymbolFileDWARF>(
70  m_module.GetSymbolFile()->GetBackingSymbolFile());
71  DWARFDIE die = dwarf.GetDIE(*ref);
72  if (!die)
73  return true;
74  return callback(die);
75 }
76 
78  const DebugNames::NameIndex &ni,
79  llvm::StringRef name) {
80  // Ignore SentinelErrors, log everything else.
83  handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
84  "Failed to parse index entries for index at {1:x}, name {2}: {0}",
85  ni.getUnitOffset(), name);
86 }
87 
89  ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
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  if (!ProcessEntry(entry, callback, basename.GetStringRef()))
96  return;
97  }
98 
99  m_fallback.GetGlobalVariables(basename, callback);
100 }
101 
103  const RegularExpression &regex,
104  llvm::function_ref<bool(DWARFDIE die)> callback) {
105  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
106  for (DebugNames::NameTableEntry nte: ni) {
107  if (!regex.Execute(nte.getString()))
108  continue;
109 
110  uint64_t entry_offset = nte.getEntryOffset();
111  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
112  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
113  if (entry_or->tag() != DW_TAG_variable)
114  continue;
115 
116  if (!ProcessEntry(*entry_or, callback,
117  llvm::StringRef(nte.getString())))
118  return;
119  }
120  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
121  }
122  }
123 
124  m_fallback.GetGlobalVariables(regex, callback);
125 }
126 
128  DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
130  uint64_t cu_offset = cu.GetOffset();
131  bool found_entry_for_cu = false;
132  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
133  for (DebugNames::NameTableEntry nte: ni) {
134  uint64_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  found_entry_for_cu = true;
143  if (!ProcessEntry(*entry_or, callback,
144  llvm::StringRef(nte.getString())))
145  return;
146  }
147  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
148  }
149  }
150  // If no name index for that particular CU was found, fallback to
151  // creating the manual index.
152  if (!found_entry_for_cu)
153  m_fallback.GetGlobalVariables(cu, callback);
154 }
155 
157  ConstString class_name, bool must_be_implementation,
158  llvm::function_ref<bool(DWARFDIE die)> callback) {
159  // Keep a list of incomplete types as fallback for when we don't find the
160  // complete type.
161  DIEArray incomplete_types;
162 
163  for (const DebugNames::Entry &entry :
164  m_debug_names_up->equal_range(class_name.GetStringRef())) {
165  if (entry.tag() != DW_TAG_structure_type &&
166  entry.tag() != DW_TAG_class_type)
167  continue;
168 
169  std::optional<DIERef> ref = ToDIERef(entry);
170  if (!ref)
171  continue;
172 
173  DWARFUnit *cu = m_debug_info.GetUnit(*ref);
174  if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
175  incomplete_types.push_back(*ref);
176  continue;
177  }
178 
179  DWARFDIE die = m_debug_info.GetDIE(*ref);
180  if (!die) {
181  ReportInvalidDIERef(*ref, class_name.GetStringRef());
182  continue;
183  }
184 
185  if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
186  // If we find the complete version we're done.
187  callback(die);
188  return;
189  }
190  incomplete_types.push_back(*ref);
191  }
192 
193  auto dierefcallback = DIERefCallback(callback, class_name.GetStringRef());
194  for (DIERef ref : incomplete_types)
195  if (!dierefcallback(ref))
196  return;
197 
198  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
199 }
200 
202  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
203  for (const DebugNames::Entry &entry :
204  m_debug_names_up->equal_range(name.GetStringRef())) {
205  if (isType(entry.tag())) {
206  if (!ProcessEntry(entry, callback, name.GetStringRef()))
207  return;
208  }
209  }
210 
211  m_fallback.GetTypes(name, callback);
212 }
213 
215  const DWARFDeclContext &context,
216  llvm::function_ref<bool(DWARFDIE die)> callback) {
217  auto name = context[0].name;
218  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
219  if (entry.tag() == context[0].tag) {
220  if (!ProcessEntry(entry, callback, name))
221  return;
222  }
223  }
224 
225  m_fallback.GetTypes(context, callback);
226 }
227 
229  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
230  for (const DebugNames::Entry &entry :
231  m_debug_names_up->equal_range(name.GetStringRef())) {
232  if (entry.tag() == DW_TAG_namespace) {
233  if (!ProcessEntry(entry, callback, name.GetStringRef()))
234  return;
235  }
236  }
237 
238  m_fallback.GetNamespaces(name, callback);
239 }
240 
242  const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
243  const CompilerDeclContext &parent_decl_ctx,
244  llvm::function_ref<bool(DWARFDIE die)> callback) {
245  ConstString name = lookup_info.GetLookupName();
246  std::set<DWARFDebugInfoEntry *> seen;
247  for (const DebugNames::Entry &entry :
248  m_debug_names_up->equal_range(name.GetStringRef())) {
249  Tag tag = entry.tag();
250  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
251  continue;
252 
253  if (std::optional<DIERef> ref = ToDIERef(entry)) {
254  if (!ProcessFunctionDIE(lookup_info, *ref, dwarf, parent_decl_ctx,
255  [&](DWARFDIE die) {
256  if (!seen.insert(die.GetDIE()).second)
257  return true;
258  return callback(die);
259  }))
260  return;
261  }
262  }
263 
264  m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
265 }
266 
268  const RegularExpression &regex,
269  llvm::function_ref<bool(DWARFDIE die)> callback) {
270  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
271  for (DebugNames::NameTableEntry nte: ni) {
272  if (!regex.Execute(nte.getString()))
273  continue;
274 
275  uint64_t entry_offset = nte.getEntryOffset();
276  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
277  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
278  Tag tag = entry_or->tag();
279  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
280  continue;
281 
282  if (!ProcessEntry(*entry_or, callback,
283  llvm::StringRef(nte.getString())))
284  return;
285  }
286  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
287  }
288  }
289 
290  m_fallback.GetFunctions(regex, callback);
291 }
292 
294  m_fallback.Dump(s);
295 
296  std::string data;
297  llvm::raw_string_ostream os(data);
298  m_debug_names_up->dump(os);
299  s.PutCString(os.str());
300 }
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:77
lldb_private::RegularExpression
Definition: RegularExpression.h:18
lldb_private::DebugNamesDWARFIndex::GetFunctions
void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:241
lldb_private::DebugNamesDWARFIndex::Dump
void Dump(Stream &s) override
Definition: DebugNamesDWARFIndex.cpp:293
Module.h
SymbolFileDWARF
Definition: SymbolFileDWARF.h:61
lldb_private::DebugNamesDWARFIndex::ToDIERef
std::optional< DIERef > ToDIERef(const DebugNames::Entry &entry)
Definition: DebugNamesDWARFIndex.cpp:46
lldb_private::Module
Definition: Module.h:87
lldb_private::DebugNamesDWARFIndex
Definition: DebugNamesDWARFIndex.h:21
lldb_private::Stream
Definition: Stream.h:28
lldb_private::DWARFDataExtractor
Definition: DWARFDataExtractor.h:18
DWARFDeclContext.h
DIEArray
std::vector< DIERef > DIEArray
Definition: DIERef.h:94
DWARFDIE
Definition: DWARFDIE.h:16
lldb_private::Module::LookupInfo
Definition: Module.h:950
SymbolFileDWARFDwo.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
DWARFUnit
Definition: DWARFUnit.h:84
lldb_private::DebugNamesDWARFIndex::GetUnits
static llvm::DenseSet< dw_offset_t > GetUnits(const DebugNames &debug_names)
Definition: DebugNamesDWARFIndex.cpp:36
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:201
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::DebugNamesDWARFIndex::GetNamespaces
void GetNamespaces(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:228
lldb_private::DebugNamesDWARFIndex::ProcessEntry
bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< bool(DWARFDIE die)> callback, llvm::StringRef name)
Definition: DebugNamesDWARFIndex.cpp:63
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:40
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:134
lldbassert
#define lldbassert(x)
Definition: LLDBAssert.h:15
SymbolFileDWARF::GetDwoNum
virtual std::optional< uint32_t > GetDwoNum()
Definition: SymbolFileDWARF.h:282
DWARFBaseDIE::GetAttributeValueAsUnsigned
uint64_t GetAttributeValueAsUnsigned(const dw_attr_t attr, uint64_t fail_value) const
Definition: DWARFBaseDIE.cpp:49
lldb_private::Module::LookupInfo::GetLookupName
ConstString GetLookupName() const
Definition: Module.h:961
uint32_t
DWARFDIE::GetDIE
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:118
lldb_private::DebugNamesDWARFIndex::GetCompleteObjCClass
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:156
DWARFUnit::GetNonSkeletonUnit
DWARFUnit & GetNonSkeletonUnit()
Definition: DWARFUnit.cpp:662
DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type
bool Supports_DW_AT_APPLE_objc_complete_type()
Definition: DWARFUnit.cpp:681
lldb_private::DWARFLog::Lookups
@ Lookups
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:77
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:35
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:88
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:23
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:200
DebugNamesDWARFIndex.h
lldb_private::GetLog
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:309
lldb
Definition: SBAddress.h:15
LLDB_LOG_ERROR
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:360
lldb_private::dwarf
Definition: dwarf.h:19
lldb_private::DebugNamesDWARFIndex::GetTypes
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:201