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 using namespace lldb_private::dwarf;
20 
21 llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
23  DWARFDataExtractor debug_str,
25  auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVM(),
26  debug_str.GetAsLLVM());
27  if (llvm::Error E = index_up->extract())
28  return std::move(E);
29 
30  return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
31  module, std::move(index_up), debug_names, debug_str, dwarf));
32 }
33 
34 llvm::DenseSet<dw_offset_t>
36  llvm::DenseSet<dw_offset_t> result;
37  for (const DebugNames::NameIndex &ni : debug_names) {
38  for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu)
39  result.insert(ni.getCUOffset(cu));
40  }
41  return result;
42 }
43 
44 llvm::Optional<DIERef>
46  llvm::Optional<uint64_t> cu_offset = entry.getCUOffset();
47  if (!cu_offset)
48  return llvm::None;
49 
50  DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
51  if (!cu)
52  return llvm::None;
53 
54  cu = &cu->GetNonSkeletonUnit();
55  if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset())
56  return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(),
57  DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset);
58 
59  return llvm::None;
60 }
61 
63  const DebugNames::Entry &entry,
64  llvm::function_ref<bool(DWARFDIE die)> callback, llvm::StringRef name) {
65  llvm::Optional<DIERef> ref = ToDIERef(entry);
66  if (!ref)
67  return true;
68  SymbolFileDWARF &dwarf = *llvm::cast<SymbolFileDWARF>(
69  m_module.GetSymbolFile()->GetBackingSymbolFile());
70  DWARFDIE die = dwarf.GetDIE(*ref);
71  if (!die)
72  return true;
73  return callback(die);
74 }
75 
77  const DebugNames::NameIndex &ni,
78  llvm::StringRef name) {
79  // Ignore SentinelErrors, log everything else.
82  handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
83  "Failed to parse index entries for index at {1:x}, name {2}: {0}",
84  ni.getUnitOffset(), name);
85 }
86 
88  ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
89  for (const DebugNames::Entry &entry :
90  m_debug_names_up->equal_range(basename.GetStringRef())) {
91  if (entry.tag() != DW_TAG_variable)
92  continue;
93 
94  if (!ProcessEntry(entry, callback, basename.GetStringRef()))
95  return;
96  }
97 
98  m_fallback.GetGlobalVariables(basename, callback);
99 }
100 
102  const RegularExpression &regex,
103  llvm::function_ref<bool(DWARFDIE die)> callback) {
104  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
105  for (DebugNames::NameTableEntry nte: ni) {
106  if (!regex.Execute(nte.getString()))
107  continue;
108 
109  uint64_t entry_offset = nte.getEntryOffset();
110  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
111  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
112  if (entry_or->tag() != DW_TAG_variable)
113  continue;
114 
115  if (!ProcessEntry(*entry_or, callback,
116  llvm::StringRef(nte.getString())))
117  return;
118  }
119  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
120  }
121  }
122 
123  m_fallback.GetGlobalVariables(regex, callback);
124 }
125 
127  DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
129  uint64_t cu_offset = cu.GetOffset();
130  bool found_entry_for_cu = false;
131  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
132  for (DebugNames::NameTableEntry nte: ni) {
133  uint64_t entry_offset = nte.getEntryOffset();
134  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
135  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
136  if (entry_or->tag() != DW_TAG_variable)
137  continue;
138  if (entry_or->getCUOffset() != cu_offset)
139  continue;
140 
141  found_entry_for_cu = true;
142  if (!ProcessEntry(*entry_or, callback,
143  llvm::StringRef(nte.getString())))
144  return;
145  }
146  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
147  }
148  }
149  // If no name index for that particular CU was found, fallback to
150  // creating the manual index.
151  if (!found_entry_for_cu)
152  m_fallback.GetGlobalVariables(cu, callback);
153 }
154 
156  ConstString class_name, bool must_be_implementation,
157  llvm::function_ref<bool(DWARFDIE die)> callback) {
158  // Keep a list of incomplete types as fallback for when we don't find the
159  // complete type.
160  DIEArray incomplete_types;
161 
162  for (const DebugNames::Entry &entry :
163  m_debug_names_up->equal_range(class_name.GetStringRef())) {
164  if (entry.tag() != DW_TAG_structure_type &&
165  entry.tag() != DW_TAG_class_type)
166  continue;
167 
168  llvm::Optional<DIERef> ref = ToDIERef(entry);
169  if (!ref)
170  continue;
171 
172  DWARFUnit *cu = m_debug_info.GetUnit(*ref);
173  if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
174  incomplete_types.push_back(*ref);
175  continue;
176  }
177 
178  DWARFDIE die = m_debug_info.GetDIE(*ref);
179  if (!die) {
180  ReportInvalidDIERef(*ref, class_name.GetStringRef());
181  continue;
182  }
183 
184  if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
185  // If we find the complete version we're done.
186  callback(die);
187  return;
188  }
189  incomplete_types.push_back(*ref);
190  }
191 
192  auto dierefcallback = DIERefCallback(callback, class_name.GetStringRef());
193  for (DIERef ref : incomplete_types)
194  if (!dierefcallback(ref))
195  return;
196 
197  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
198 }
199 
201  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
202  for (const DebugNames::Entry &entry :
203  m_debug_names_up->equal_range(name.GetStringRef())) {
204  if (isType(entry.tag())) {
205  if (!ProcessEntry(entry, callback, name.GetStringRef()))
206  return;
207  }
208  }
209 
210  m_fallback.GetTypes(name, callback);
211 }
212 
214  const DWARFDeclContext &context,
215  llvm::function_ref<bool(DWARFDIE die)> callback) {
216  auto name = context[0].name;
217  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
218  if (entry.tag() == context[0].tag) {
219  if (!ProcessEntry(entry, callback, name))
220  return;
221  }
222  }
223 
224  m_fallback.GetTypes(context, callback);
225 }
226 
228  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
229  for (const DebugNames::Entry &entry :
230  m_debug_names_up->equal_range(name.GetStringRef())) {
231  if (entry.tag() == DW_TAG_namespace) {
232  if (!ProcessEntry(entry, callback, name.GetStringRef()))
233  return;
234  }
235  }
236 
237  m_fallback.GetNamespaces(name, callback);
238 }
239 
241  const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
242  const CompilerDeclContext &parent_decl_ctx,
243  llvm::function_ref<bool(DWARFDIE die)> callback) {
244  ConstString name = lookup_info.GetLookupName();
245  std::set<DWARFDebugInfoEntry *> seen;
246  for (const DebugNames::Entry &entry :
247  m_debug_names_up->equal_range(name.GetStringRef())) {
248  Tag tag = entry.tag();
249  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
250  continue;
251 
252  if (llvm::Optional<DIERef> ref = ToDIERef(entry)) {
253  if (!ProcessFunctionDIE(lookup_info, *ref, dwarf, parent_decl_ctx,
254  [&](DWARFDIE die) {
255  if (!seen.insert(die.GetDIE()).second)
256  return true;
257  return callback(die);
258  }))
259  return;
260  }
261  }
262 
263  m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, 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
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:240
lldb_private::DebugNamesDWARFIndex::Dump
void Dump(Stream &s) override
Definition: DebugNamesDWARFIndex.cpp:292
Module.h
SymbolFileDWARF
Definition: SymbolFileDWARF.h:60
lldb_private::Module
Definition: Module.h:85
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:94
DWARFDIE
Definition: DWARFDIE.h:16
lldb_private::Module::LookupInfo
Definition: Module.h:931
SymbolFileDWARFDwo.h
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
DWARFUnit
Definition: DWARFUnit.h:83
lldb_private::DebugNamesDWARFIndex::GetUnits
static llvm::DenseSet< dw_offset_t > GetUnits(const DebugNames &debug_names)
Definition: DebugNamesDWARFIndex.cpp:35
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:227
lldb_private::DebugNamesDWARFIndex::ProcessEntry
bool ProcessEntry(const DebugNames::Entry &entry, llvm::function_ref< bool(DWARFDIE die)> callback, llvm::StringRef name)
Definition: DebugNamesDWARFIndex.cpp:62
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:133
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
lldb_private::Module::LookupInfo::GetLookupName
ConstString GetLookupName() const
Definition: Module.h:942
uint32_t
DWARFDIE::GetDIE
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:123
lldb_private::DebugNamesDWARFIndex::GetCompleteObjCClass
void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:155
lldb_private::DebugNamesDWARFIndex::ToDIERef
llvm::Optional< DIERef > ToDIERef(const DebugNames::Entry &entry)
Definition: DebugNamesDWARFIndex.cpp:45
DWARFUnit::GetNonSkeletonUnit
DWARFUnit & GetNonSkeletonUnit()
Definition: DWARFUnit.cpp:641
DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type
bool Supports_DW_AT_APPLE_objc_complete_type()
Definition: DWARFUnit.cpp:660
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:76
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
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:87
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:22
SymbolFileDWARF::GetDwoNum
virtual llvm::Optional< uint32_t > GetDwoNum()
Definition: SymbolFileDWARF.h:278
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:199
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:308
lldb
Definition: SBAddress.h:15
LLDB_LOG_ERROR
#define LLDB_LOG_ERROR(log, error,...)
Definition: Log.h:359
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:200