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  const DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
127  uint64_t cu_offset = cu.GetOffset();
128  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
129  for (DebugNames::NameTableEntry nte: ni) {
130  uint64_t entry_offset = nte.getEntryOffset();
131  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
132  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
133  if (entry_or->tag() != DW_TAG_variable)
134  continue;
135  if (entry_or->getCUOffset() != cu_offset)
136  continue;
137 
138  if (!ProcessEntry(*entry_or, callback,
139  llvm::StringRef(nte.getString())))
140  return;
141  }
142  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
143  }
144  }
145 
146  m_fallback.GetGlobalVariables(cu, callback);
147 }
148 
150  ConstString class_name, bool must_be_implementation,
151  llvm::function_ref<bool(DWARFDIE die)> callback) {
152  // Keep a list of incomplete types as fallback for when we don't find the
153  // complete type.
154  DIEArray incomplete_types;
155 
156  for (const DebugNames::Entry &entry :
157  m_debug_names_up->equal_range(class_name.GetStringRef())) {
158  if (entry.tag() != DW_TAG_structure_type &&
159  entry.tag() != DW_TAG_class_type)
160  continue;
161 
162  llvm::Optional<DIERef> ref = ToDIERef(entry);
163  if (!ref)
164  continue;
165 
166  DWARFUnit *cu = m_debug_info.GetUnit(*ref);
167  if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) {
168  incomplete_types.push_back(*ref);
169  continue;
170  }
171 
172  DWARFDIE die = m_debug_info.GetDIE(*ref);
173  if (!die) {
174  ReportInvalidDIERef(*ref, class_name.GetStringRef());
175  continue;
176  }
177 
178  if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
179  // If we find the complete version we're done.
180  callback(die);
181  return;
182  }
183  incomplete_types.push_back(*ref);
184  }
185 
186  auto dierefcallback = DIERefCallback(callback, class_name.GetStringRef());
187  for (DIERef ref : incomplete_types)
188  if (!dierefcallback(ref))
189  return;
190 
191  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
192 }
193 
195  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
196  for (const DebugNames::Entry &entry :
197  m_debug_names_up->equal_range(name.GetStringRef())) {
198  if (isType(entry.tag())) {
199  if (!ProcessEntry(entry, callback, name.GetStringRef()))
200  return;
201  }
202  }
203 
204  m_fallback.GetTypes(name, callback);
205 }
206 
208  const DWARFDeclContext &context,
209  llvm::function_ref<bool(DWARFDIE die)> callback) {
210  auto name = context[0].name;
211  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
212  if (entry.tag() == context[0].tag) {
213  if (!ProcessEntry(entry, callback, name))
214  return;
215  }
216  }
217 
218  m_fallback.GetTypes(context, callback);
219 }
220 
222  ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
223  for (const DebugNames::Entry &entry :
224  m_debug_names_up->equal_range(name.GetStringRef())) {
225  if (entry.tag() == DW_TAG_namespace) {
226  if (!ProcessEntry(entry, callback, name.GetStringRef()))
227  return;
228  }
229  }
230 
231  m_fallback.GetNamespaces(name, callback);
232 }
233 
236  const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
237  llvm::function_ref<bool(DWARFDIE die)> callback) {
238 
239  std::set<DWARFDebugInfoEntry *> seen;
240  for (const DebugNames::Entry &entry :
241  m_debug_names_up->equal_range(name.GetStringRef())) {
242  Tag tag = entry.tag();
243  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
244  continue;
245 
246  if (llvm::Optional<DIERef> ref = ToDIERef(entry)) {
247  if (!ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx,
248  name_type_mask, [&](DWARFDIE die) {
249  if (!seen.insert(die.GetDIE()).second)
250  return true;
251  return callback(die);
252  }))
253  return;
254  }
255  }
256 
257  m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask,
258  callback);
259 }
260 
262  const RegularExpression &regex,
263  llvm::function_ref<bool(DWARFDIE die)> callback) {
264  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
265  for (DebugNames::NameTableEntry nte: ni) {
266  if (!regex.Execute(nte.getString()))
267  continue;
268 
269  uint64_t entry_offset = nte.getEntryOffset();
270  llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
271  for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
272  Tag tag = entry_or->tag();
273  if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
274  continue;
275 
276  if (!ProcessEntry(*entry_or, callback,
277  llvm::StringRef(nte.getString())))
278  return;
279  }
280  MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
281  }
282  }
283 
284  m_fallback.GetFunctions(regex, callback);
285 }
286 
288  m_fallback.Dump(s);
289 
290  std::string data;
291  llvm::raw_string_ostream os(data);
292  m_debug_names_up->dump(os);
293  s.PutCString(os.str());
294 }
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:287
Module.h
SymbolFileDWARF
Definition: SymbolFileDWARF.h:58
lldb_private::Module
Definition: Module.h:75
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:15
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:221
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:38
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:129
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:149
lldb_private::DebugNamesDWARFIndex::ToDIERef
llvm::Optional< DIERef > ToDIERef(const DebugNames::Entry &entry)
Definition: DebugNamesDWARFIndex.cpp:44
DWARFUnit::GetNonSkeletonUnit
DWARFUnit & GetNonSkeletonUnit()
Definition: DWARFUnit.cpp:555
DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type
bool Supports_DW_AT_APPLE_objc_complete_type()
Definition: DWARFUnit.cpp:574
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:279
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:193
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:234
lldb_private::DebugNamesDWARFIndex::GetTypes
void GetTypes(ConstString name, llvm::function_ref< bool(DWARFDIE die)> callback) override
Definition: DebugNamesDWARFIndex.cpp:194
lldb_private::LogChannelDWARF::GetLogIfAll
static Log * GetLogIfAll(uint32_t mask)
Definition: LogChannelDWARF.h:30