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
Next()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
GetParent() const37 DWARFDIE::GetParent() const {
38 if (IsValid())
39 return DWARFDIE(m_cu, m_die->GetParent());
40 else
41 return DWARFDIE();
42 }
43
44 DWARFDIE
GetFirstChild() const45 DWARFDIE::GetFirstChild() const {
46 if (IsValid())
47 return DWARFDIE(m_cu, m_die->GetFirstChild());
48 else
49 return DWARFDIE();
50 }
51
52 DWARFDIE
GetSibling() const53 DWARFDIE::GetSibling() const {
54 if (IsValid())
55 return DWARFDIE(m_cu, m_die->GetSibling());
56 else
57 return DWARFDIE();
58 }
59
60 DWARFDIE
GetReferencedDIE(const dw_attr_t attr) const61 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
GetDIE(dw_offset_t die_offset) const71 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
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const79 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
LookupDeepestBlock(lldb::addr_t file_addr) const93 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
GetMangledName() const113 const char *DWARFDIE::GetMangledName() const {
114 if (IsValid())
115 return m_die->GetMangledName(GetDWARF(), m_cu);
116 else
117 return nullptr;
118 }
119
GetPubname() const120 const char *DWARFDIE::GetPubname() const {
121 if (IsValid())
122 return m_die->GetPubname(GetDWARF(), m_cu);
123 else
124 return nullptr;
125 }
126
GetQualifiedName(std::string & storage) const127 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
ResolveType() const134 lldb_private::Type *DWARFDIE::ResolveType() const {
135 if (IsValid())
136 return GetDWARF()->ResolveType(*this, true);
137 else
138 return nullptr;
139 }
140
ResolveTypeUID(const DIERef & die_ref) const141 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
GetDeclContextDIEs(DWARFDIECollection & decl_context_dies) const149 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
GetDWARFDeclContext(DWARFDeclContext & dwarf_decl_ctx) const160 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
GetDeclContext(std::vector<CompilerContext> & context) const169 void DWARFDIE::GetDeclContext(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.GetDeclContext(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
GetParentDeclContextDIE() const219 DWARFDIE::GetParentDeclContextDIE() const {
220 if (IsValid())
221 return m_die->GetParentDeclContextDIE(GetDWARF(), m_cu);
222 else
223 return DWARFDIE();
224 }
225
IsStructUnionOrClass() const226 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
IsMethod() const232 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
GetContainingDWOModuleDIE() const240 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
GetContainingDWOModule() const259 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
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) const272 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
GetDecl() const285 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
GetDeclContext() const293 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
GetContainingDeclContext() const301 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