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