LLDB  mainline
DWARFDIE.cpp
Go to the documentation of this file.
1 //===-- DWARFDIE.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 "DWARFDIE.h"
10 
11 #include "DWARFASTParser.h"
12 #include "DWARFDebugInfo.h"
13 #include "DWARFDebugInfoEntry.h"
14 #include "DWARFDeclContext.h"
15 #include "DWARFUnit.h"
16 
17 using namespace lldb_private;
18 
19 namespace {
20 
21 /// Iterate through all DIEs elaborating (i.e. reachable by a chain of
22 /// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
23 /// convenience, the starting die is included in the sequence as the first
24 /// item.
25 class ElaboratingDIEIterator
26  : public std::iterator<std::input_iterator_tag, DWARFDIE> {
27 
28  // The operating invariant is: top of m_worklist contains the "current" item
29  // and the rest of the list are items yet to be visited. An empty worklist
30  // means we've reached the end.
31  // Infinite recursion is prevented by maintaining a list of seen DIEs.
32  // Container sizes are optimized for the case of following DW_AT_specification
33  // and DW_AT_abstract_origin just once.
34  llvm::SmallVector<DWARFDIE, 2> m_worklist;
35  llvm::SmallSet<lldb::user_id_t, 3> m_seen;
36 
37  void Next() {
38  assert(!m_worklist.empty() && "Incrementing end iterator?");
39 
40  // Pop the current item from the list.
41  DWARFDIE die = m_worklist.back();
42  m_worklist.pop_back();
43 
44  // And add back any items that elaborate it.
45  for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
46  if (DWARFDIE d = die.GetReferencedDIE(attr))
47  if (m_seen.insert(die.GetID()).second)
48  m_worklist.push_back(d);
49  }
50  }
51 
52 public:
53  /// An iterator starting at die d.
54  explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
55 
56  /// End marker
57  ElaboratingDIEIterator() {}
58 
59  const DWARFDIE &operator*() const { return m_worklist.back(); }
60  ElaboratingDIEIterator &operator++() {
61  Next();
62  return *this;
63  }
64  ElaboratingDIEIterator operator++(int) {
65  ElaboratingDIEIterator I = *this;
66  Next();
67  return I;
68  }
69 
70  friend bool operator==(const ElaboratingDIEIterator &a,
71  const ElaboratingDIEIterator &b) {
72  if (a.m_worklist.empty() || b.m_worklist.empty())
73  return a.m_worklist.empty() == b.m_worklist.empty();
74  return a.m_worklist.back() == b.m_worklist.back();
75  }
76  friend bool operator!=(const ElaboratingDIEIterator &a,
77  const ElaboratingDIEIterator &b) {
78  return !(a == b);
79  }
80 };
81 
82 llvm::iterator_range<ElaboratingDIEIterator>
83 elaborating_dies(const DWARFDIE &die) {
84  return llvm::make_range(ElaboratingDIEIterator(die),
85  ElaboratingDIEIterator());
86 }
87 } // namespace
88 
91  if (IsValid())
92  return DWARFDIE(m_cu, m_die->GetParent());
93  else
94  return DWARFDIE();
95 }
96 
99  if (IsValid())
100  return DWARFDIE(m_cu, m_die->GetFirstChild());
101  else
102  return DWARFDIE();
103 }
104 
105 DWARFDIE
107  if (IsValid())
108  return DWARFDIE(m_cu, m_die->GetSibling());
109  else
110  return DWARFDIE();
111 }
112 
113 DWARFDIE
115  const dw_offset_t die_offset =
116  GetAttributeValueAsReference(attr, DW_INVALID_OFFSET);
117  if (die_offset != DW_INVALID_OFFSET)
118  return GetDIE(die_offset);
119  else
120  return DWARFDIE();
121 }
122 
123 DWARFDIE
124 DWARFDIE::GetDIE(dw_offset_t die_offset) const {
125  if (IsValid())
126  return m_cu->GetDIE(die_offset);
127  else
128  return DWARFDIE();
129 }
130 
131 DWARFDIE
133  if (IsValid()) {
134  DWARFUnit *cu = GetCU();
135  SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
136  const bool check_specification_or_abstract_origin = true;
137  DWARFFormValue form_value;
138  if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr,
139  check_specification_or_abstract_origin))
140  return dwarf->GetDIE(DIERef(form_value));
141  }
142  return DWARFDIE();
143 }
144 
145 DWARFDIE
147  if (IsValid()) {
148  SymbolFileDWARF *dwarf = GetDWARF();
149  DWARFUnit *cu = GetCU();
150  DWARFDebugInfoEntry *function_die = nullptr;
151  DWARFDebugInfoEntry *block_die = nullptr;
152  if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) {
153  if (block_die && block_die != function_die) {
154  if (cu->ContainsDIEOffset(block_die->GetOffset()))
155  return DWARFDIE(cu, block_die);
156  else
157  return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit(
158  DIERef(cu->GetOffset(), block_die->GetOffset())),
159  block_die);
160  }
161  }
162  }
163  return DWARFDIE();
164 }
165 
166 const char *DWARFDIE::GetMangledName() const {
167  if (IsValid())
168  return m_die->GetMangledName(GetDWARF(), m_cu);
169  else
170  return nullptr;
171 }
172 
173 const char *DWARFDIE::GetPubname() const {
174  if (IsValid())
175  return m_die->GetPubname(GetDWARF(), m_cu);
176  else
177  return nullptr;
178 }
179 
180 const char *DWARFDIE::GetQualifiedName(std::string &storage) const {
181  if (IsValid())
182  return m_die->GetQualifiedName(GetDWARF(), m_cu, storage);
183  else
184  return nullptr;
185 }
186 
188  if (IsValid())
189  return GetDWARF()->ResolveType(*this, true);
190  else
191  return nullptr;
192 }
193 
195  SymbolFileDWARF *dwarf = GetDWARF();
196  if (dwarf)
197  return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true);
198  else
199  return nullptr;
200 }
201 
202 std::vector<DWARFDIE> DWARFDIE::GetDeclContextDIEs() const {
203  if (!IsValid())
204  return {};
205 
206  std::vector<DWARFDIE> result;
207  DWARFDIE parent = GetParentDeclContextDIE();
208  while (parent.IsValid() && parent.GetDIE() != GetDIE()) {
209  result.push_back(std::move(parent));
210  parent = parent.GetParentDeclContextDIE();
211  }
212 
213  return result;
214 }
215 
216 void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
217  if (IsValid()) {
218  dwarf_decl_ctx.SetLanguage(GetLanguage());
219  m_die->GetDWARFDeclContext(GetDWARF(), GetCU(), dwarf_decl_ctx);
220  } else {
221  dwarf_decl_ctx.Clear();
222  }
223 }
224 
225 void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const {
226  const dw_tag_t tag = Tag();
227  if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
228  return;
229  DWARFDIE parent = GetParent();
230  if (parent)
231  parent.GetDeclContext(context);
232  switch (tag) {
233  case DW_TAG_module:
234  context.push_back(
236  break;
237  case DW_TAG_namespace:
239  ConstString(GetName())));
240  break;
241  case DW_TAG_structure_type:
243  ConstString(GetName())));
244  break;
245  case DW_TAG_union_type:
246  context.push_back(
248  break;
249  case DW_TAG_class_type:
250  context.push_back(
252  break;
253  case DW_TAG_enumeration_type:
255  ConstString(GetName())));
256  break;
257  case DW_TAG_subprogram:
259  ConstString(GetPubname())));
260  break;
261  case DW_TAG_variable:
263  ConstString(GetPubname())));
264  break;
265  case DW_TAG_typedef:
266  context.push_back(
268  break;
269  default:
270  break;
271  }
272 }
273 
274 DWARFDIE
276  if (IsValid())
277  return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
278  else
279  return DWARFDIE();
280 }
281 
283  const dw_tag_t tag = Tag();
284  return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
285  tag == DW_TAG_union_type;
286 }
287 
288 bool DWARFDIE::IsMethod() const {
289  for (DWARFDIE d : elaborating_dies(*this))
290  if (d.GetParent().IsStructUnionOrClass())
291  return true;
292  return false;
293 }
294 
295 DWARFDIE
297  if (IsValid()) {
298  DWARFDIE top_module_die;
299  // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
300  // if so
301  for (DWARFDIE parent = GetParent(); parent.IsValid();
302  parent = parent.GetParent()) {
303  const dw_tag_t tag = parent.Tag();
304  if (tag == DW_TAG_module)
305  top_module_die = parent;
306  else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
307  break;
308  }
309 
310  return top_module_die;
311  }
312  return DWARFDIE();
313 }
314 
315 lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
316  if (IsValid()) {
317  DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
318 
319  if (dwo_module_die) {
320  const char *module_name = dwo_module_die.GetName();
321  if (module_name)
322  return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name));
323  }
324  }
325  return lldb::ModuleSP();
326 }
327 
329  const char *&name, const char *&mangled, DWARFRangeList &ranges,
330  int &decl_file, int &decl_line, int &decl_column, int &call_file,
331  int &call_line, int &call_column,
332  lldb_private::DWARFExpression *frame_base) const {
333  if (IsValid()) {
334  return m_die->GetDIENamesAndRanges(
335  GetDWARF(), GetCU(), name, mangled, ranges, decl_file, decl_line,
336  decl_column, call_file, call_line, call_column, frame_base);
337  } else
338  return false;
339 }
340 
342  DWARFASTParser *dwarf_ast = GetDWARFParser();
343  if (dwarf_ast)
344  return dwarf_ast->GetDeclForUIDFromDWARF(*this);
345  else
346  return CompilerDecl();
347 }
348 
350  DWARFASTParser *dwarf_ast = GetDWARFParser();
351  if (dwarf_ast)
352  return dwarf_ast->GetDeclContextForUIDFromDWARF(*this);
353  else
354  return CompilerDeclContext();
355 }
356 
358  DWARFASTParser *dwarf_ast = GetDWARFParser();
359  if (dwarf_ast)
360  return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this);
361  else
362  return CompilerDeclContext();
363 }
DWARFDIE GetFirstChild() const
Definition: DWARFDIE.cpp:98
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
lldb::ModuleSP GetContainingDWOModule() const
Definition: DWARFDIE.cpp:315
bool ContainsDIEOffset(dw_offset_t die_offset) const
Definition: DWARFUnit.h:85
"lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location expression and interprets it...
lldb_private::CompilerDeclContext GetContainingDeclContext() const
Definition: DWARFDIE.cpp:357
DWARFDIE GetParent() const
Definition: DWARFDIE.cpp:90
lldb_private::CompilerDecl GetDecl() const
Definition: DWARFDIE.cpp:341
const char * GetQualifiedName(std::string &storage) const
Definition: DWARFDIE.cpp:180
Definition: DIERef.h:18
const Scalar operator*(const Scalar &lhs, const Scalar &rhs)
Definition: Scalar.cpp:2161
virtual lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die)=0
DWARFDIE GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const
Definition: DWARFDIE.cpp:132
bool operator==(const Address &lhs, const Address &rhs)
Definition: Address.cpp:973
lldb_private::CompilerDeclContext GetDeclContext() const
Definition: DWARFDIE.cpp:349
const char * GetPubname() const
Definition: DWARFDIE.cpp:173
bool IsStructUnionOrClass() const
Definition: DWARFDIE.cpp:282
lldb_private::Type * ResolveTypeUID(lldb::user_id_t type_uid) override
void SetLanguage(lldb::LanguageType language)
lldb_private::Type * ResolveTypeUID(const DIERef &die_ref) const
Definition: DWARFDIE.cpp:194
DWARFDIE GetSibling() const
Definition: DWARFDIE.cpp:106
const char * GetMangledName() const
Definition: DWARFDIE.cpp:166
dw_offset_t GetOffset() const
DWARFDebugInfo * DebugInfo()
bool GetDIENamesAndRanges(const char *&name, const char *&mangled, DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column, int &call_file, int &call_line, int &call_column, lldb_private::DWARFExpression *frame_base) const
Definition: DWARFDIE.cpp:328
bool operator!=(const Address &lhs, const Address &rhs)
Definition: Address.cpp:979
dw_offset_t GetOffset() const
Definition: DWARFUnit.h:76
DWARFDIE GetReferencedDIE(const dw_attr_t attr) const
Definition: DWARFDIE.cpp:114
std::vector< DWARFDIE > GetDeclContextDIEs() const
Definition: DWARFDIE.cpp:202
DWARFDebugInfoEntry * GetDIE() const
Definition: DWARFBaseDIE.h:54
void GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const
Definition: DWARFDIE.cpp:216
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
DWARFDIE GetContainingDWOModuleDIE() const
Definition: DWARFDIE.cpp:296
virtual lldb_private::CompilerDecl GetDeclForUIDFromDWARF(const DWARFDIE &die)=0
SymbolFileDWARF * GetSymbolFileDWARF() const
Definition: DWARFUnit.cpp:590
DWARFDIE GetDIE(dw_offset_t die_offset) const
Definition: DWARFDIE.cpp:124
DWARFUnit * GetCompileUnit(const DIERef &die_ref)
bool IsValid() const
Definition: DWARFBaseDIE.h:43
virtual lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(const DWARFDIE &die)=0
#define DW_INVALID_OFFSET
Definition: dwarf.h:34
DWARFDIE GetParentDeclContextDIE() const
Definition: DWARFDIE.cpp:275
lldb_private::Type * ResolveType() const
Definition: DWARFDIE.cpp:187
virtual DWARFDIE GetDIE(const DIERef &die_ref)
bool IsMethod() const
Definition: DWARFDIE.cpp:288
void GetDeclContext(std::vector< lldb_private::CompilerContext > &context) const
Return this DIE&#39;s decl context as it is needed to look up types in Clang&#39;s -gmodules debug info forma...
Definition: DWARFDIE.cpp:225
const char * GetName() const
DWARFDIE LookupDeepestBlock(lldb::addr_t file_addr) const
Definition: DWARFDIE.cpp:146