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