DWARFDIE.cpp revision 314564
1//===-- DWARFDIE.cpp --------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "DWARFDIE.h"
11
12#include "DWARFASTParser.h"
13#include "DWARFCompileUnit.h"
14#include "DWARFDIECollection.h"
15#include "DWARFDebugAbbrev.h"
16#include "DWARFDebugAranges.h"
17#include "DWARFDebugInfo.h"
18#include "DWARFDebugInfoEntry.h"
19#include "DWARFDebugRanges.h"
20#include "DWARFDeclContext.h"
21#include "DWARFFormValue.h"
22#include "SymbolFileDWARF.h"
23
24#include "lldb/Core/Module.h"
25#include "lldb/Symbol/ObjectFile.h"
26#include "lldb/Symbol/Type.h"
27#include "lldb/Symbol/TypeSystem.h"
28
29using namespace lldb_private;
30
31DIERef DWARFDIE::GetDIERef() const {
32  if (!IsValid())
33    return DIERef();
34
35  dw_offset_t cu_offset = m_cu->GetOffset();
36  if (m_cu->GetBaseObjOffset() != DW_INVALID_OFFSET)
37    cu_offset = m_cu->GetBaseObjOffset();
38  return DIERef(cu_offset, m_die->GetOffset());
39}
40
41dw_tag_t DWARFDIE::Tag() const {
42  if (m_die)
43    return m_die->Tag();
44  else
45    return 0;
46}
47
48const char *DWARFDIE::GetTagAsCString() const {
49  return lldb_private::DW_TAG_value_to_name(Tag());
50}
51
52DWARFDIE
53DWARFDIE::GetParent() const {
54  if (IsValid())
55    return DWARFDIE(m_cu, m_die->GetParent());
56  else
57    return DWARFDIE();
58}
59
60DWARFDIE
61DWARFDIE::GetFirstChild() const {
62  if (IsValid())
63    return DWARFDIE(m_cu, m_die->GetFirstChild());
64  else
65    return DWARFDIE();
66}
67
68DWARFDIE
69DWARFDIE::GetSibling() const {
70  if (IsValid())
71    return DWARFDIE(m_cu, m_die->GetSibling());
72  else
73    return DWARFDIE();
74}
75
76DWARFDIE
77DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
78  const dw_offset_t die_offset =
79      GetAttributeValueAsReference(attr, DW_INVALID_OFFSET);
80  if (die_offset != DW_INVALID_OFFSET)
81    return GetDIE(die_offset);
82  else
83    return DWARFDIE();
84}
85
86DWARFDIE
87DWARFDIE::GetDIE(dw_offset_t die_offset) const {
88  if (IsValid())
89    return m_cu->GetDIE(die_offset);
90  else
91    return DWARFDIE();
92}
93
94const char *DWARFDIE::GetAttributeValueAsString(const dw_attr_t attr,
95                                                const char *fail_value) const {
96  if (IsValid())
97    return m_die->GetAttributeValueAsString(GetDWARF(), GetCU(), attr,
98                                            fail_value);
99  else
100    return fail_value;
101}
102
103uint64_t DWARFDIE::GetAttributeValueAsUnsigned(const dw_attr_t attr,
104                                               uint64_t fail_value) const {
105  if (IsValid())
106    return m_die->GetAttributeValueAsUnsigned(GetDWARF(), GetCU(), attr,
107                                              fail_value);
108  else
109    return fail_value;
110}
111
112int64_t DWARFDIE::GetAttributeValueAsSigned(const dw_attr_t attr,
113                                            int64_t fail_value) const {
114  if (IsValid())
115    return m_die->GetAttributeValueAsSigned(GetDWARF(), GetCU(), attr,
116                                            fail_value);
117  else
118    return fail_value;
119}
120
121DWARFDIE
122DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
123  if (IsValid()) {
124    DWARFCompileUnit *cu = GetCU();
125    SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
126    const bool check_specification_or_abstract_origin = true;
127    DWARFFormValue form_value;
128    if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr,
129                                 check_specification_or_abstract_origin))
130      return dwarf->GetDIE(DIERef(form_value));
131  }
132  return DWARFDIE();
133}
134
135uint64_t DWARFDIE::GetAttributeValueAsReference(const dw_attr_t attr,
136                                                uint64_t fail_value) const {
137  if (IsValid())
138    return m_die->GetAttributeValueAsReference(GetDWARF(), GetCU(), attr,
139                                               fail_value);
140  else
141    return fail_value;
142}
143
144uint64_t DWARFDIE::GetAttributeValueAsAddress(const dw_attr_t attr,
145                                              uint64_t fail_value) const {
146  if (IsValid())
147    return m_die->GetAttributeValueAsAddress(GetDWARF(), GetCU(), attr,
148                                             fail_value);
149  else
150    return fail_value;
151}
152
153DWARFDIE
154DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
155  if (IsValid()) {
156    SymbolFileDWARF *dwarf = GetDWARF();
157    DWARFCompileUnit *cu = GetCU();
158    DWARFDebugInfoEntry *function_die = nullptr;
159    DWARFDebugInfoEntry *block_die = nullptr;
160    if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) {
161      if (block_die && block_die != function_die) {
162        if (cu->ContainsDIEOffset(block_die->GetOffset()))
163          return DWARFDIE(cu, block_die);
164        else
165          return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit(
166                              DIERef(cu->GetOffset(), block_die->GetOffset())),
167                          block_die);
168      }
169    }
170  }
171  return DWARFDIE();
172}
173
174lldb::user_id_t DWARFDIE::GetID() const {
175  return GetDIERef().GetUID(GetDWARF());
176}
177
178const char *DWARFDIE::GetName() const {
179  if (IsValid())
180    return m_die->GetName(GetDWARF(), m_cu);
181  else
182    return nullptr;
183}
184
185const char *DWARFDIE::GetMangledName() const {
186  if (IsValid())
187    return m_die->GetMangledName(GetDWARF(), m_cu);
188  else
189    return nullptr;
190}
191
192const char *DWARFDIE::GetPubname() const {
193  if (IsValid())
194    return m_die->GetPubname(GetDWARF(), m_cu);
195  else
196    return nullptr;
197}
198
199const char *DWARFDIE::GetQualifiedName(std::string &storage) const {
200  if (IsValid())
201    return m_die->GetQualifiedName(GetDWARF(), m_cu, storage);
202  else
203    return nullptr;
204}
205
206lldb::LanguageType DWARFDIE::GetLanguage() const {
207  if (IsValid())
208    return m_cu->GetLanguageType();
209  else
210    return lldb::eLanguageTypeUnknown;
211}
212
213lldb::ModuleSP DWARFDIE::GetModule() const {
214  SymbolFileDWARF *dwarf = GetDWARF();
215  if (dwarf)
216    return dwarf->GetObjectFile()->GetModule();
217  else
218    return lldb::ModuleSP();
219}
220
221lldb_private::CompileUnit *DWARFDIE::GetLLDBCompileUnit() const {
222  if (IsValid())
223    return GetDWARF()->GetCompUnitForDWARFCompUnit(GetCU());
224  else
225    return nullptr;
226}
227
228lldb_private::Type *DWARFDIE::ResolveType() const {
229  if (IsValid())
230    return GetDWARF()->ResolveType(*this, true);
231  else
232    return nullptr;
233}
234
235lldb_private::Type *DWARFDIE::ResolveTypeUID(const DIERef &die_ref) const {
236  SymbolFileDWARF *dwarf = GetDWARF();
237  if (dwarf)
238    return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true);
239  else
240    return nullptr;
241}
242
243void DWARFDIE::GetDeclContextDIEs(DWARFDIECollection &decl_context_dies) const {
244  if (IsValid()) {
245    DWARFDIE parent_decl_ctx_die =
246        m_die->GetParentDeclContextDIE(GetDWARF(), GetCU());
247    if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) {
248      decl_context_dies.Append(parent_decl_ctx_die);
249      parent_decl_ctx_die.GetDeclContextDIEs(decl_context_dies);
250    }
251  }
252}
253
254void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
255  if (IsValid()) {
256    dwarf_decl_ctx.SetLanguage(GetLanguage());
257    m_die->GetDWARFDeclContext(GetDWARF(), GetCU(), dwarf_decl_ctx);
258  } else {
259    dwarf_decl_ctx.Clear();
260  }
261}
262
263void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const {
264  const dw_tag_t tag = Tag();
265  if (tag == DW_TAG_compile_unit)
266    return;
267  DWARFDIE parent = GetParent();
268  if (parent)
269    parent.GetDWOContext(context);
270  switch (tag) {
271  case DW_TAG_module:
272    context.push_back(
273        CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
274    break;
275  case DW_TAG_namespace:
276    context.push_back(CompilerContext(CompilerContextKind::Namespace,
277                                      ConstString(GetName())));
278    break;
279  case DW_TAG_structure_type:
280    context.push_back(CompilerContext(CompilerContextKind::Structure,
281                                      ConstString(GetName())));
282    break;
283  case DW_TAG_union_type:
284    context.push_back(
285        CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
286    break;
287  case DW_TAG_class_type:
288    context.push_back(
289        CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
290    break;
291  case DW_TAG_enumeration_type:
292    context.push_back(CompilerContext(CompilerContextKind::Enumeration,
293                                      ConstString(GetName())));
294    break;
295  case DW_TAG_subprogram:
296    context.push_back(CompilerContext(CompilerContextKind::Function,
297                                      ConstString(GetPubname())));
298    break;
299  case DW_TAG_variable:
300    context.push_back(CompilerContext(CompilerContextKind::Variable,
301                                      ConstString(GetPubname())));
302    break;
303  case DW_TAG_typedef:
304    context.push_back(
305        CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
306    break;
307  default:
308    break;
309  }
310}
311
312DWARFDIE
313DWARFDIE::GetParentDeclContextDIE() const {
314  if (IsValid())
315    return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
316  else
317    return DWARFDIE();
318}
319
320dw_offset_t DWARFDIE::GetOffset() const {
321  if (IsValid())
322    return m_die->GetOffset();
323  else
324    return DW_INVALID_OFFSET;
325}
326
327dw_offset_t DWARFDIE::GetCompileUnitRelativeOffset() const {
328  if (IsValid())
329    return m_die->GetOffset() - m_cu->GetOffset();
330  else
331    return DW_INVALID_OFFSET;
332}
333
334SymbolFileDWARF *DWARFDIE::GetDWARF() const {
335  if (m_cu)
336    return m_cu->GetSymbolFileDWARF();
337  else
338    return nullptr;
339}
340
341lldb_private::TypeSystem *DWARFDIE::GetTypeSystem() const {
342  if (m_cu)
343    return m_cu->GetTypeSystem();
344  else
345    return nullptr;
346}
347
348DWARFASTParser *DWARFDIE::GetDWARFParser() const {
349  lldb_private::TypeSystem *type_system = GetTypeSystem();
350  if (type_system)
351    return type_system->GetDWARFParser();
352  else
353    return nullptr;
354}
355
356bool DWARFDIE::IsStructOrClass() const {
357  const dw_tag_t tag = Tag();
358  return tag == DW_TAG_class_type || tag == DW_TAG_structure_type;
359}
360
361DWARFDIE
362DWARFDIE::GetContainingDWOModuleDIE() const {
363  if (IsValid()) {
364    DWARFDIE top_module_die;
365    // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
366    // if so
367    for (DWARFDIE parent = GetParent(); parent.IsValid();
368         parent = parent.GetParent()) {
369      const dw_tag_t tag = parent.Tag();
370      if (tag == DW_TAG_module)
371        top_module_die = parent;
372      else if (tag == DW_TAG_compile_unit)
373        break;
374    }
375
376    return top_module_die;
377  }
378  return DWARFDIE();
379}
380
381lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
382  if (IsValid()) {
383    DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
384
385    if (dwo_module_die) {
386      const char *module_name = dwo_module_die.GetName();
387      if (module_name)
388        return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name));
389    }
390  }
391  return lldb::ModuleSP();
392}
393
394bool DWARFDIE::HasChildren() const {
395  if (m_die)
396    return m_die->HasChildren();
397  else
398    return false;
399}
400
401bool DWARFDIE::Supports_DW_AT_APPLE_objc_complete_type() const {
402  if (IsValid())
403    return GetDWARF()->Supports_DW_AT_APPLE_objc_complete_type(m_cu);
404  else
405    return false;
406}
407
408size_t DWARFDIE::GetAttributes(DWARFAttributes &attributes,
409                               uint32_t depth) const {
410  if (IsValid()) {
411    return m_die->GetAttributes(m_cu, m_cu->GetFixedFormSizes(), attributes,
412                                depth);
413  }
414  if (depth == 0)
415    attributes.Clear();
416  return 0;
417}
418
419bool DWARFDIE::GetDIENamesAndRanges(
420    const char *&name, const char *&mangled, DWARFRangeList &ranges,
421    int &decl_file, int &decl_line, int &decl_column, int &call_file,
422    int &call_line, int &call_column,
423    lldb_private::DWARFExpression *frame_base) const {
424  if (IsValid()) {
425    return m_die->GetDIENamesAndRanges(
426        GetDWARF(), GetCU(), name, mangled, ranges, decl_file, decl_line,
427        decl_column, call_file, call_line, call_column, frame_base);
428  } else
429    return false;
430}
431
432void DWARFDIE::Dump(lldb_private::Stream *s,
433                    const uint32_t recurse_depth) const {
434  if (s && IsValid())
435    m_die->Dump(GetDWARF(), GetCU(), *s, recurse_depth);
436}
437
438CompilerDecl DWARFDIE::GetDecl() const {
439  DWARFASTParser *dwarf_ast = GetDWARFParser();
440  if (dwarf_ast)
441    return dwarf_ast->GetDeclForUIDFromDWARF(*this);
442  else
443    return CompilerDecl();
444}
445
446CompilerDeclContext DWARFDIE::GetDeclContext() const {
447  DWARFASTParser *dwarf_ast = GetDWARFParser();
448  if (dwarf_ast)
449    return dwarf_ast->GetDeclContextForUIDFromDWARF(*this);
450  else
451    return CompilerDeclContext();
452}
453
454CompilerDeclContext DWARFDIE::GetContainingDeclContext() const {
455  DWARFASTParser *dwarf_ast = GetDWARFParser();
456  if (dwarf_ast)
457    return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this);
458  else
459    return CompilerDeclContext();
460}
461
462bool operator==(const DWARFDIE &lhs, const DWARFDIE &rhs) {
463  return lhs.GetDIE() == rhs.GetDIE() && lhs.GetCU() == rhs.GetCU();
464}
465
466bool operator!=(const DWARFDIE &lhs, const DWARFDIE &rhs) {
467  return lhs.GetDIE() != rhs.GetDIE() || lhs.GetCU() != rhs.GetCU();
468}
469