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 "DWARFUnit.h"
14 #include "DWARFDIECollection.h"
15 #include "DWARFDebugInfo.h"
16 #include "DWARFDeclContext.h"
17 
18 #include "DWARFDebugInfoEntry.h"
19 
20 using namespace lldb_private;
21 
22 DWARFDIE
23 DWARFDIE::GetParent() const {
24   if (IsValid())
25     return DWARFDIE(m_cu, m_die->GetParent());
26   else
27     return DWARFDIE();
28 }
29 
30 DWARFDIE
31 DWARFDIE::GetFirstChild() const {
32   if (IsValid())
33     return DWARFDIE(m_cu, m_die->GetFirstChild());
34   else
35     return DWARFDIE();
36 }
37 
38 DWARFDIE
39 DWARFDIE::GetSibling() const {
40   if (IsValid())
41     return DWARFDIE(m_cu, m_die->GetSibling());
42   else
43     return DWARFDIE();
44 }
45 
46 DWARFDIE
47 DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
48   const dw_offset_t die_offset =
49       GetAttributeValueAsReference(attr, DW_INVALID_OFFSET);
50   if (die_offset != DW_INVALID_OFFSET)
51     return GetDIE(die_offset);
52   else
53     return DWARFDIE();
54 }
55 
56 DWARFDIE
57 DWARFDIE::GetDIE(dw_offset_t die_offset) const {
58   if (IsValid())
59     return m_cu->GetDIE(die_offset);
60   else
61     return DWARFDIE();
62 }
63 
64 DWARFDIE
65 DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
66   if (IsValid()) {
67     DWARFUnit *cu = GetCU();
68     SymbolFileDWARF *dwarf = cu->GetSymbolFileDWARF();
69     const bool check_specification_or_abstract_origin = true;
70     DWARFFormValue form_value;
71     if (m_die->GetAttributeValue(dwarf, cu, attr, form_value, nullptr,
72                                  check_specification_or_abstract_origin))
73       return dwarf->GetDIE(DIERef(form_value));
74   }
75   return DWARFDIE();
76 }
77 
78 DWARFDIE
79 DWARFDIE::LookupDeepestBlock(lldb::addr_t file_addr) const {
80   if (IsValid()) {
81     SymbolFileDWARF *dwarf = GetDWARF();
82     DWARFUnit *cu = GetCU();
83     DWARFDebugInfoEntry *function_die = nullptr;
84     DWARFDebugInfoEntry *block_die = nullptr;
85     if (m_die->LookupAddress(file_addr, dwarf, cu, &function_die, &block_die)) {
86       if (block_die && block_die != function_die) {
87         if (cu->ContainsDIEOffset(block_die->GetOffset()))
88           return DWARFDIE(cu, block_die);
89         else
90           return DWARFDIE(dwarf->DebugInfo()->GetCompileUnit(
91                               DIERef(cu->GetOffset(), block_die->GetOffset())),
92                           block_die);
93       }
94     }
95   }
96   return DWARFDIE();
97 }
98 
99 const char *DWARFDIE::GetMangledName() const {
100   if (IsValid())
101     return m_die->GetMangledName(GetDWARF(), m_cu);
102   else
103     return nullptr;
104 }
105 
106 const char *DWARFDIE::GetPubname() const {
107   if (IsValid())
108     return m_die->GetPubname(GetDWARF(), m_cu);
109   else
110     return nullptr;
111 }
112 
113 const char *DWARFDIE::GetQualifiedName(std::string &storage) const {
114   if (IsValid())
115     return m_die->GetQualifiedName(GetDWARF(), m_cu, storage);
116   else
117     return nullptr;
118 }
119 
120 lldb_private::Type *DWARFDIE::ResolveType() const {
121   if (IsValid())
122     return GetDWARF()->ResolveType(*this, true);
123   else
124     return nullptr;
125 }
126 
127 lldb_private::Type *DWARFDIE::ResolveTypeUID(const DIERef &die_ref) const {
128   SymbolFileDWARF *dwarf = GetDWARF();
129   if (dwarf)
130     return dwarf->ResolveTypeUID(dwarf->GetDIE(die_ref), true);
131   else
132     return nullptr;
133 }
134 
135 void DWARFDIE::GetDeclContextDIEs(DWARFDIECollection &decl_context_dies) const {
136   if (IsValid()) {
137     DWARFDIE parent_decl_ctx_die =
138         m_die->GetParentDeclContextDIE(GetDWARF(), GetCU());
139     if (parent_decl_ctx_die && parent_decl_ctx_die.GetDIE() != GetDIE()) {
140       decl_context_dies.Append(parent_decl_ctx_die);
141       parent_decl_ctx_die.GetDeclContextDIEs(decl_context_dies);
142     }
143   }
144 }
145 
146 void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
147   if (IsValid()) {
148     dwarf_decl_ctx.SetLanguage(GetLanguage());
149     m_die->GetDWARFDeclContext(GetDWARF(), GetCU(), dwarf_decl_ctx);
150   } else {
151     dwarf_decl_ctx.Clear();
152   }
153 }
154 
155 void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const {
156   const dw_tag_t tag = Tag();
157   if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
158     return;
159   DWARFDIE parent = GetParent();
160   if (parent)
161     parent.GetDWOContext(context);
162   switch (tag) {
163   case DW_TAG_module:
164     context.push_back(
165         CompilerContext(CompilerContextKind::Module, ConstString(GetName())));
166     break;
167   case DW_TAG_namespace:
168     context.push_back(CompilerContext(CompilerContextKind::Namespace,
169                                       ConstString(GetName())));
170     break;
171   case DW_TAG_structure_type:
172     context.push_back(CompilerContext(CompilerContextKind::Structure,
173                                       ConstString(GetName())));
174     break;
175   case DW_TAG_union_type:
176     context.push_back(
177         CompilerContext(CompilerContextKind::Union, ConstString(GetName())));
178     break;
179   case DW_TAG_class_type:
180     context.push_back(
181         CompilerContext(CompilerContextKind::Class, ConstString(GetName())));
182     break;
183   case DW_TAG_enumeration_type:
184     context.push_back(CompilerContext(CompilerContextKind::Enumeration,
185                                       ConstString(GetName())));
186     break;
187   case DW_TAG_subprogram:
188     context.push_back(CompilerContext(CompilerContextKind::Function,
189                                       ConstString(GetPubname())));
190     break;
191   case DW_TAG_variable:
192     context.push_back(CompilerContext(CompilerContextKind::Variable,
193                                       ConstString(GetPubname())));
194     break;
195   case DW_TAG_typedef:
196     context.push_back(
197         CompilerContext(CompilerContextKind::Typedef, ConstString(GetName())));
198     break;
199   default:
200     break;
201   }
202 }
203 
204 DWARFDIE
205 DWARFDIE::GetParentDeclContextDIE() const {
206   if (IsValid())
207     return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
208   else
209     return DWARFDIE();
210 }
211 
212 bool DWARFDIE::IsStructClassOrUnion() const {
213   const dw_tag_t tag = Tag();
214   return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
215          tag == DW_TAG_union_type;
216 }
217 
218 DWARFDIE
219 DWARFDIE::GetContainingDWOModuleDIE() const {
220   if (IsValid()) {
221     DWARFDIE top_module_die;
222     // Now make sure this DIE is scoped in a DW_TAG_module tag and return true
223     // if so
224     for (DWARFDIE parent = GetParent(); parent.IsValid();
225          parent = parent.GetParent()) {
226       const dw_tag_t tag = parent.Tag();
227       if (tag == DW_TAG_module)
228         top_module_die = parent;
229       else if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
230         break;
231     }
232 
233     return top_module_die;
234   }
235   return DWARFDIE();
236 }
237 
238 lldb::ModuleSP DWARFDIE::GetContainingDWOModule() const {
239   if (IsValid()) {
240     DWARFDIE dwo_module_die = GetContainingDWOModuleDIE();
241 
242     if (dwo_module_die) {
243       const char *module_name = dwo_module_die.GetName();
244       if (module_name)
245         return GetDWARF()->GetDWOModule(lldb_private::ConstString(module_name));
246     }
247   }
248   return lldb::ModuleSP();
249 }
250 
251 bool DWARFDIE::GetDIENamesAndRanges(
252     const char *&name, const char *&mangled, DWARFRangeList &ranges,
253     int &decl_file, int &decl_line, int &decl_column, int &call_file,
254     int &call_line, int &call_column,
255     lldb_private::DWARFExpression *frame_base) const {
256   if (IsValid()) {
257     return m_die->GetDIENamesAndRanges(
258         GetDWARF(), GetCU(), name, mangled, ranges, decl_file, decl_line,
259         decl_column, call_file, call_line, call_column, frame_base);
260   } else
261     return false;
262 }
263 
264 CompilerDecl DWARFDIE::GetDecl() const {
265   DWARFASTParser *dwarf_ast = GetDWARFParser();
266   if (dwarf_ast)
267     return dwarf_ast->GetDeclForUIDFromDWARF(*this);
268   else
269     return CompilerDecl();
270 }
271 
272 CompilerDeclContext DWARFDIE::GetDeclContext() const {
273   DWARFASTParser *dwarf_ast = GetDWARFParser();
274   if (dwarf_ast)
275     return dwarf_ast->GetDeclContextForUIDFromDWARF(*this);
276   else
277     return CompilerDeclContext();
278 }
279 
280 CompilerDeclContext DWARFDIE::GetContainingDeclContext() const {
281   DWARFASTParser *dwarf_ast = GetDWARFParser();
282   if (dwarf_ast)
283     return dwarf_ast->GetDeclContextContainingUIDFromDWARF(*this);
284   else
285     return CompilerDeclContext();
286 }
287