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