xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- DWARFDIE.cpp ------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "DWARFDIE.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "DWARFASTParser.h"
120b57cec5SDimitry Andric #include "DWARFDebugInfo.h"
130b57cec5SDimitry Andric #include "DWARFDebugInfoEntry.h"
140b57cec5SDimitry Andric #include "DWARFDeclContext.h"
150b57cec5SDimitry Andric #include "DWARFUnit.h"
16*0fca6ea1SDimitry Andric #include "lldb/Symbol/Type.h"
170b57cec5SDimitry Andric 
18bdd1243dSDimitry Andric #include "llvm/ADT/iterator.h"
19*0fca6ea1SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h"
20bdd1243dSDimitry Andric 
210b57cec5SDimitry Andric using namespace lldb_private;
2281ad6265SDimitry Andric using namespace lldb_private::dwarf;
235f757f3fSDimitry Andric using namespace lldb_private::plugin::dwarf;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric namespace {
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric /// Iterate through all DIEs elaborating (i.e. reachable by a chain of
280b57cec5SDimitry Andric /// DW_AT_specification and DW_AT_abstract_origin attributes) a given DIE. For
290b57cec5SDimitry Andric /// convenience, the starting die is included in the sequence as the first
300b57cec5SDimitry Andric /// item.
310b57cec5SDimitry Andric class ElaboratingDIEIterator
32bdd1243dSDimitry Andric     : public llvm::iterator_facade_base<
33bdd1243dSDimitry Andric           ElaboratingDIEIterator, std::input_iterator_tag, DWARFDIE,
34bdd1243dSDimitry Andric           std::ptrdiff_t, DWARFDIE *, DWARFDIE *> {
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   // The operating invariant is: top of m_worklist contains the "current" item
370b57cec5SDimitry Andric   // and the rest of the list are items yet to be visited. An empty worklist
380b57cec5SDimitry Andric   // means we've reached the end.
390b57cec5SDimitry Andric   // Infinite recursion is prevented by maintaining a list of seen DIEs.
400b57cec5SDimitry Andric   // Container sizes are optimized for the case of following DW_AT_specification
410b57cec5SDimitry Andric   // and DW_AT_abstract_origin just once.
420b57cec5SDimitry Andric   llvm::SmallVector<DWARFDIE, 2> m_worklist;
435ffd83dbSDimitry Andric   llvm::SmallSet<DWARFDebugInfoEntry *, 3> m_seen;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   void Next() {
460b57cec5SDimitry Andric     assert(!m_worklist.empty() && "Incrementing end iterator?");
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric     // Pop the current item from the list.
490b57cec5SDimitry Andric     DWARFDIE die = m_worklist.back();
500b57cec5SDimitry Andric     m_worklist.pop_back();
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     // And add back any items that elaborate it.
530b57cec5SDimitry Andric     for (dw_attr_t attr : {DW_AT_specification, DW_AT_abstract_origin}) {
540b57cec5SDimitry Andric       if (DWARFDIE d = die.GetReferencedDIE(attr))
555ffd83dbSDimitry Andric         if (m_seen.insert(die.GetDIE()).second)
560b57cec5SDimitry Andric           m_worklist.push_back(d);
570b57cec5SDimitry Andric     }
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric public:
610b57cec5SDimitry Andric   /// An iterator starting at die d.
620b57cec5SDimitry Andric   explicit ElaboratingDIEIterator(DWARFDIE d) : m_worklist(1, d) {}
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   /// End marker
65fe6060f1SDimitry Andric   ElaboratingDIEIterator() = default;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   const DWARFDIE &operator*() const { return m_worklist.back(); }
680b57cec5SDimitry Andric   ElaboratingDIEIterator &operator++() {
690b57cec5SDimitry Andric     Next();
700b57cec5SDimitry Andric     return *this;
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   friend bool operator==(const ElaboratingDIEIterator &a,
740b57cec5SDimitry Andric                          const ElaboratingDIEIterator &b) {
750b57cec5SDimitry Andric     if (a.m_worklist.empty() || b.m_worklist.empty())
760b57cec5SDimitry Andric       return a.m_worklist.empty() == b.m_worklist.empty();
770b57cec5SDimitry Andric     return a.m_worklist.back() == b.m_worklist.back();
780b57cec5SDimitry Andric   }
790b57cec5SDimitry Andric };
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric llvm::iterator_range<ElaboratingDIEIterator>
820b57cec5SDimitry Andric elaborating_dies(const DWARFDIE &die) {
830b57cec5SDimitry Andric   return llvm::make_range(ElaboratingDIEIterator(die),
840b57cec5SDimitry Andric                           ElaboratingDIEIterator());
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric } // namespace
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric DWARFDIE
890b57cec5SDimitry Andric DWARFDIE::GetParent() const {
900b57cec5SDimitry Andric   if (IsValid())
910b57cec5SDimitry Andric     return DWARFDIE(m_cu, m_die->GetParent());
920b57cec5SDimitry Andric   else
930b57cec5SDimitry Andric     return DWARFDIE();
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric DWARFDIE
970b57cec5SDimitry Andric DWARFDIE::GetFirstChild() const {
980b57cec5SDimitry Andric   if (IsValid())
990b57cec5SDimitry Andric     return DWARFDIE(m_cu, m_die->GetFirstChild());
1000b57cec5SDimitry Andric   else
1010b57cec5SDimitry Andric     return DWARFDIE();
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric DWARFDIE
1050b57cec5SDimitry Andric DWARFDIE::GetSibling() const {
1060b57cec5SDimitry Andric   if (IsValid())
1070b57cec5SDimitry Andric     return DWARFDIE(m_cu, m_die->GetSibling());
1080b57cec5SDimitry Andric   else
1090b57cec5SDimitry Andric     return DWARFDIE();
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric DWARFDIE
1130b57cec5SDimitry Andric DWARFDIE::GetReferencedDIE(const dw_attr_t attr) const {
1140b57cec5SDimitry Andric   if (IsValid())
1150b57cec5SDimitry Andric     return m_die->GetAttributeValueAsReference(GetCU(), attr);
1160b57cec5SDimitry Andric   else
1170b57cec5SDimitry Andric     return {};
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric DWARFDIE
1210b57cec5SDimitry Andric DWARFDIE::GetDIE(dw_offset_t die_offset) const {
1220b57cec5SDimitry Andric   if (IsValid())
1230b57cec5SDimitry Andric     return m_cu->GetDIE(die_offset);
1240b57cec5SDimitry Andric   else
1250b57cec5SDimitry Andric     return DWARFDIE();
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric DWARFDIE
1290b57cec5SDimitry Andric DWARFDIE::GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const {
1300b57cec5SDimitry Andric   if (IsValid()) {
1310b57cec5SDimitry Andric     DWARFUnit *cu = GetCU();
1320b57cec5SDimitry Andric     const bool check_specification_or_abstract_origin = true;
1330b57cec5SDimitry Andric     DWARFFormValue form_value;
1340b57cec5SDimitry Andric     if (m_die->GetAttributeValue(cu, attr, form_value, nullptr,
1350b57cec5SDimitry Andric                                  check_specification_or_abstract_origin))
1360b57cec5SDimitry Andric       return form_value.Reference();
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric   return DWARFDIE();
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric DWARFDIE
1425ffd83dbSDimitry Andric DWARFDIE::LookupDeepestBlock(lldb::addr_t address) const {
1435ffd83dbSDimitry Andric   if (!IsValid())
1440b57cec5SDimitry Andric     return DWARFDIE();
1455ffd83dbSDimitry Andric 
1465ffd83dbSDimitry Andric   DWARFDIE result;
1475ffd83dbSDimitry Andric   bool check_children = false;
1485ffd83dbSDimitry Andric   bool match_addr_range = false;
1495ffd83dbSDimitry Andric   switch (Tag()) {
1505ffd83dbSDimitry Andric   case DW_TAG_class_type:
1515ffd83dbSDimitry Andric   case DW_TAG_namespace:
1525ffd83dbSDimitry Andric   case DW_TAG_structure_type:
1535ffd83dbSDimitry Andric   case DW_TAG_common_block:
1545ffd83dbSDimitry Andric     check_children = true;
1555ffd83dbSDimitry Andric     break;
1565ffd83dbSDimitry Andric   case DW_TAG_compile_unit:
1575ffd83dbSDimitry Andric   case DW_TAG_module:
1585ffd83dbSDimitry Andric   case DW_TAG_catch_block:
1595ffd83dbSDimitry Andric   case DW_TAG_subprogram:
1605ffd83dbSDimitry Andric   case DW_TAG_try_block:
1615ffd83dbSDimitry Andric   case DW_TAG_partial_unit:
1625ffd83dbSDimitry Andric     match_addr_range = true;
1635ffd83dbSDimitry Andric     break;
1645ffd83dbSDimitry Andric   case DW_TAG_lexical_block:
1655ffd83dbSDimitry Andric   case DW_TAG_inlined_subroutine:
1665ffd83dbSDimitry Andric     check_children = true;
1675ffd83dbSDimitry Andric     match_addr_range = true;
1685ffd83dbSDimitry Andric     break;
1695ffd83dbSDimitry Andric   default:
1705ffd83dbSDimitry Andric     break;
1715ffd83dbSDimitry Andric   }
1725ffd83dbSDimitry Andric 
1735ffd83dbSDimitry Andric   if (match_addr_range) {
17406c3fb27SDimitry Andric     DWARFRangeList ranges =
17506c3fb27SDimitry Andric         m_die->GetAttributeAddressRanges(m_cu, /*check_hi_lo_pc=*/true);
17606c3fb27SDimitry Andric     if (ranges.FindEntryThatContains(address)) {
1775ffd83dbSDimitry Andric       check_children = true;
1785ffd83dbSDimitry Andric       switch (Tag()) {
1795ffd83dbSDimitry Andric       default:
1805ffd83dbSDimitry Andric         break;
1815ffd83dbSDimitry Andric 
1825ffd83dbSDimitry Andric       case DW_TAG_inlined_subroutine: // Inlined Function
1835ffd83dbSDimitry Andric       case DW_TAG_lexical_block:      // Block { } in code
1845ffd83dbSDimitry Andric         result = *this;
1855ffd83dbSDimitry Andric         break;
1865ffd83dbSDimitry Andric       }
1875ffd83dbSDimitry Andric     } else {
1885ffd83dbSDimitry Andric       check_children = false;
1895ffd83dbSDimitry Andric     }
1905ffd83dbSDimitry Andric   }
1915ffd83dbSDimitry Andric 
1925ffd83dbSDimitry Andric   if (check_children) {
193fe6060f1SDimitry Andric     for (DWARFDIE child : children()) {
1945ffd83dbSDimitry Andric       if (DWARFDIE child_result = child.LookupDeepestBlock(address))
1955ffd83dbSDimitry Andric         return child_result;
1965ffd83dbSDimitry Andric     }
1975ffd83dbSDimitry Andric   }
1985ffd83dbSDimitry Andric   return result;
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric const char *DWARFDIE::GetMangledName() const {
2020b57cec5SDimitry Andric   if (IsValid())
2030b57cec5SDimitry Andric     return m_die->GetMangledName(m_cu);
2040b57cec5SDimitry Andric   else
2050b57cec5SDimitry Andric     return nullptr;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric const char *DWARFDIE::GetPubname() const {
2090b57cec5SDimitry Andric   if (IsValid())
2100b57cec5SDimitry Andric     return m_die->GetPubname(m_cu);
2110b57cec5SDimitry Andric   else
2120b57cec5SDimitry Andric     return nullptr;
2130b57cec5SDimitry Andric }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric // GetName
2160b57cec5SDimitry Andric //
2170b57cec5SDimitry Andric // Get value of the DW_AT_name attribute and place that value into the supplied
2180b57cec5SDimitry Andric // stream object. If the DIE is a NULL object "NULL" is placed into the stream,
2190b57cec5SDimitry Andric // and if no DW_AT_name attribute exists for the DIE then nothing is printed.
2200b57cec5SDimitry Andric void DWARFDIE::GetName(Stream &s) const {
2210b57cec5SDimitry Andric   if (!IsValid())
2220b57cec5SDimitry Andric     return;
2230b57cec5SDimitry Andric   if (GetDIE()->IsNULL()) {
2240b57cec5SDimitry Andric     s.PutCString("NULL");
2250b57cec5SDimitry Andric     return;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric   const char *name = GetDIE()->GetAttributeValueAsString(GetCU(), DW_AT_name, nullptr, true);
2280b57cec5SDimitry Andric   if (!name)
2290b57cec5SDimitry Andric     return;
2300b57cec5SDimitry Andric   s.PutCString(name);
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric // AppendTypeName
2340b57cec5SDimitry Andric //
2350b57cec5SDimitry Andric // Follows the type name definition down through all needed tags to end up with
2360b57cec5SDimitry Andric // a fully qualified type name and dump the results to the supplied stream.
2370b57cec5SDimitry Andric // This is used to show the name of types given a type identifier.
2380b57cec5SDimitry Andric void DWARFDIE::AppendTypeName(Stream &s) const {
2390b57cec5SDimitry Andric   if (!IsValid())
2400b57cec5SDimitry Andric     return;
2410b57cec5SDimitry Andric   if (GetDIE()->IsNULL()) {
2420b57cec5SDimitry Andric     s.PutCString("NULL");
2430b57cec5SDimitry Andric     return;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric   if (const char *name = GetPubname()) {
2460b57cec5SDimitry Andric     s.PutCString(name);
2470b57cec5SDimitry Andric     return;
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric   switch (Tag()) {
2500b57cec5SDimitry Andric   case DW_TAG_array_type:
2510b57cec5SDimitry Andric     break; // print out a "[]" after printing the full type of the element
2520b57cec5SDimitry Andric            // below
2530b57cec5SDimitry Andric   case DW_TAG_base_type:
2540b57cec5SDimitry Andric     s.PutCString("base ");
2550b57cec5SDimitry Andric     break;
2560b57cec5SDimitry Andric   case DW_TAG_class_type:
2570b57cec5SDimitry Andric     s.PutCString("class ");
2580b57cec5SDimitry Andric     break;
2590b57cec5SDimitry Andric   case DW_TAG_const_type:
2600b57cec5SDimitry Andric     s.PutCString("const ");
2610b57cec5SDimitry Andric     break;
2620b57cec5SDimitry Andric   case DW_TAG_enumeration_type:
2630b57cec5SDimitry Andric     s.PutCString("enum ");
2640b57cec5SDimitry Andric     break;
2650b57cec5SDimitry Andric   case DW_TAG_file_type:
2660b57cec5SDimitry Andric     s.PutCString("file ");
2670b57cec5SDimitry Andric     break;
2680b57cec5SDimitry Andric   case DW_TAG_interface_type:
2690b57cec5SDimitry Andric     s.PutCString("interface ");
2700b57cec5SDimitry Andric     break;
2710b57cec5SDimitry Andric   case DW_TAG_packed_type:
2720b57cec5SDimitry Andric     s.PutCString("packed ");
2730b57cec5SDimitry Andric     break;
2740b57cec5SDimitry Andric   case DW_TAG_pointer_type:
2750b57cec5SDimitry Andric     break; // print out a '*' after printing the full type below
2760b57cec5SDimitry Andric   case DW_TAG_ptr_to_member_type:
2770b57cec5SDimitry Andric     break; // print out a '*' after printing the full type below
2780b57cec5SDimitry Andric   case DW_TAG_reference_type:
2790b57cec5SDimitry Andric     break; // print out a '&' after printing the full type below
2800b57cec5SDimitry Andric   case DW_TAG_restrict_type:
2810b57cec5SDimitry Andric     s.PutCString("restrict ");
2820b57cec5SDimitry Andric     break;
2830b57cec5SDimitry Andric   case DW_TAG_set_type:
2840b57cec5SDimitry Andric     s.PutCString("set ");
2850b57cec5SDimitry Andric     break;
2860b57cec5SDimitry Andric   case DW_TAG_shared_type:
2870b57cec5SDimitry Andric     s.PutCString("shared ");
2880b57cec5SDimitry Andric     break;
2890b57cec5SDimitry Andric   case DW_TAG_string_type:
2900b57cec5SDimitry Andric     s.PutCString("string ");
2910b57cec5SDimitry Andric     break;
2920b57cec5SDimitry Andric   case DW_TAG_structure_type:
2930b57cec5SDimitry Andric     s.PutCString("struct ");
2940b57cec5SDimitry Andric     break;
2950b57cec5SDimitry Andric   case DW_TAG_subrange_type:
2960b57cec5SDimitry Andric     s.PutCString("subrange ");
2970b57cec5SDimitry Andric     break;
2980b57cec5SDimitry Andric   case DW_TAG_subroutine_type:
2990b57cec5SDimitry Andric     s.PutCString("function ");
3000b57cec5SDimitry Andric     break;
3010b57cec5SDimitry Andric   case DW_TAG_thrown_type:
3020b57cec5SDimitry Andric     s.PutCString("thrown ");
3030b57cec5SDimitry Andric     break;
3040b57cec5SDimitry Andric   case DW_TAG_union_type:
3050b57cec5SDimitry Andric     s.PutCString("union ");
3060b57cec5SDimitry Andric     break;
3070b57cec5SDimitry Andric   case DW_TAG_unspecified_type:
3080b57cec5SDimitry Andric     s.PutCString("unspecified ");
3090b57cec5SDimitry Andric     break;
3100b57cec5SDimitry Andric   case DW_TAG_volatile_type:
3110b57cec5SDimitry Andric     s.PutCString("volatile ");
3120b57cec5SDimitry Andric     break;
313bdd1243dSDimitry Andric   case DW_TAG_LLVM_ptrauth_type: {
314bdd1243dSDimitry Andric     unsigned key = GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_key, 0);
315bdd1243dSDimitry Andric     bool isAddressDiscriminated = GetAttributeValueAsUnsigned(
316bdd1243dSDimitry Andric         DW_AT_LLVM_ptrauth_address_discriminated, 0);
317bdd1243dSDimitry Andric     unsigned extraDiscriminator =
318bdd1243dSDimitry Andric         GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_extra_discriminator, 0);
319bdd1243dSDimitry Andric     bool isaPointer =
320bdd1243dSDimitry Andric         GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_isa_pointer, 0);
321*0fca6ea1SDimitry Andric     bool authenticatesNullValues = GetAttributeValueAsUnsigned(
322*0fca6ea1SDimitry Andric         DW_AT_LLVM_ptrauth_authenticates_null_values, 0);
323*0fca6ea1SDimitry Andric     unsigned authenticationMode =
324*0fca6ea1SDimitry Andric         GetAttributeValueAsUnsigned(DW_AT_LLVM_ptrauth_authentication_mode, 3);
325*0fca6ea1SDimitry Andric 
326*0fca6ea1SDimitry Andric     s.Printf("__ptrauth(%d, %d, 0x0%x, %d, %d, %d)", key,
327*0fca6ea1SDimitry Andric              isAddressDiscriminated, extraDiscriminator, isaPointer,
328*0fca6ea1SDimitry Andric              authenticatesNullValues, authenticationMode);
329bdd1243dSDimitry Andric     break;
330bdd1243dSDimitry Andric   }
3310b57cec5SDimitry Andric   default:
3320b57cec5SDimitry Andric     return;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   // Follow the DW_AT_type if possible
3360b57cec5SDimitry Andric   if (DWARFDIE next_die = GetAttributeValueAsReferenceDIE(DW_AT_type))
3370b57cec5SDimitry Andric     next_die.AppendTypeName(s);
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric   switch (Tag()) {
3400b57cec5SDimitry Andric   case DW_TAG_array_type:
3410b57cec5SDimitry Andric     s.PutCString("[]");
3420b57cec5SDimitry Andric     break;
3430b57cec5SDimitry Andric   case DW_TAG_pointer_type:
3440b57cec5SDimitry Andric     s.PutChar('*');
3450b57cec5SDimitry Andric     break;
3460b57cec5SDimitry Andric   case DW_TAG_ptr_to_member_type:
3470b57cec5SDimitry Andric     s.PutChar('*');
3480b57cec5SDimitry Andric     break;
3490b57cec5SDimitry Andric   case DW_TAG_reference_type:
3500b57cec5SDimitry Andric     s.PutChar('&');
3510b57cec5SDimitry Andric     break;
3520b57cec5SDimitry Andric   default:
3530b57cec5SDimitry Andric     break;
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric lldb_private::Type *DWARFDIE::ResolveType() const {
3580b57cec5SDimitry Andric   if (IsValid())
3590b57cec5SDimitry Andric     return GetDWARF()->ResolveType(*this, true);
3600b57cec5SDimitry Andric   else
3610b57cec5SDimitry Andric     return nullptr;
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric lldb_private::Type *DWARFDIE::ResolveTypeUID(const DWARFDIE &die) const {
3650b57cec5SDimitry Andric   if (SymbolFileDWARF *dwarf = GetDWARF())
3660b57cec5SDimitry Andric     return dwarf->ResolveTypeUID(die, true);
3670b57cec5SDimitry Andric   return nullptr;
3680b57cec5SDimitry Andric }
3690b57cec5SDimitry Andric 
370*0fca6ea1SDimitry Andric static void GetDeclContextImpl(DWARFDIE die,
371*0fca6ea1SDimitry Andric                                llvm::SmallSet<lldb::user_id_t, 4> &seen,
372*0fca6ea1SDimitry Andric                                std::vector<CompilerContext> &context) {
373297eecfbSDimitry Andric   // Stop if we hit a cycle.
374*0fca6ea1SDimitry Andric   while (die && seen.insert(die.GetID()).second) {
375297eecfbSDimitry Andric     // Handle outline member function DIEs by following the specification.
376*0fca6ea1SDimitry Andric     if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_specification)) {
377*0fca6ea1SDimitry Andric       die = spec;
378*0fca6ea1SDimitry Andric       continue;
379*0fca6ea1SDimitry Andric     }
380*0fca6ea1SDimitry Andric     // To find the name of a type in a type unit, we must follow the signature.
381*0fca6ea1SDimitry Andric     if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_signature)) {
382*0fca6ea1SDimitry Andric       die = spec;
383*0fca6ea1SDimitry Andric       continue;
384*0fca6ea1SDimitry Andric     }
385297eecfbSDimitry Andric 
386297eecfbSDimitry Andric     // Add this DIE's contribution at the end of the chain.
3875f757f3fSDimitry Andric     auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
3885f757f3fSDimitry Andric       context.push_back({kind, ConstString(name)});
3895f757f3fSDimitry Andric     };
390297eecfbSDimitry Andric     switch (die.Tag()) {
3910b57cec5SDimitry Andric     case DW_TAG_module:
392297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Module, die.GetName());
3930b57cec5SDimitry Andric       break;
3940b57cec5SDimitry Andric     case DW_TAG_namespace:
395297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Namespace, die.GetName());
3960b57cec5SDimitry Andric       break;
397*0fca6ea1SDimitry Andric     case DW_TAG_class_type:
3980b57cec5SDimitry Andric     case DW_TAG_structure_type:
399*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::ClassOrStruct, die.GetName());
4000b57cec5SDimitry Andric       break;
4010b57cec5SDimitry Andric     case DW_TAG_union_type:
402297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Union, die.GetName());
4030b57cec5SDimitry Andric       break;
4040b57cec5SDimitry Andric     case DW_TAG_enumeration_type:
405297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Enum, die.GetName());
4060b57cec5SDimitry Andric       break;
4070b57cec5SDimitry Andric     case DW_TAG_subprogram:
408297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Function, die.GetName());
4090b57cec5SDimitry Andric       break;
4100b57cec5SDimitry Andric     case DW_TAG_variable:
411297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Variable, die.GetPubname());
4120b57cec5SDimitry Andric       break;
4130b57cec5SDimitry Andric     case DW_TAG_typedef:
414297eecfbSDimitry Andric       push_ctx(CompilerContextKind::Typedef, die.GetName());
4150b57cec5SDimitry Andric       break;
4160b57cec5SDimitry Andric     default:
4170b57cec5SDimitry Andric       break;
4180b57cec5SDimitry Andric     }
419*0fca6ea1SDimitry Andric     // Now process the parent.
420*0fca6ea1SDimitry Andric     die = die.GetParent();
421*0fca6ea1SDimitry Andric   }
422*0fca6ea1SDimitry Andric }
423*0fca6ea1SDimitry Andric 
424*0fca6ea1SDimitry Andric std::vector<CompilerContext> DWARFDIE::GetDeclContext() const {
425*0fca6ea1SDimitry Andric   llvm::SmallSet<lldb::user_id_t, 4> seen;
426*0fca6ea1SDimitry Andric   std::vector<CompilerContext> context;
427*0fca6ea1SDimitry Andric   GetDeclContextImpl(*this, seen, context);
428*0fca6ea1SDimitry Andric   std::reverse(context.begin(), context.end());
4295f757f3fSDimitry Andric   return context;
4305f757f3fSDimitry Andric }
4315f757f3fSDimitry Andric 
432*0fca6ea1SDimitry Andric static void GetTypeLookupContextImpl(DWARFDIE die,
433*0fca6ea1SDimitry Andric                                      llvm::SmallSet<lldb::user_id_t, 4> &seen,
434*0fca6ea1SDimitry Andric                                      std::vector<CompilerContext> &context) {
435*0fca6ea1SDimitry Andric   // Stop if we hit a cycle.
436*0fca6ea1SDimitry Andric   while (die && seen.insert(die.GetID()).second) {
437*0fca6ea1SDimitry Andric     // To find the name of a type in a type unit, we must follow the signature.
438*0fca6ea1SDimitry Andric     if (DWARFDIE spec = die.GetReferencedDIE(DW_AT_signature)) {
439*0fca6ea1SDimitry Andric       die = spec;
440*0fca6ea1SDimitry Andric       continue;
441297eecfbSDimitry Andric     }
442297eecfbSDimitry Andric 
4435f757f3fSDimitry Andric     // If there is no name, then there is no need to look anything up for this
4445f757f3fSDimitry Andric     // DIE.
445*0fca6ea1SDimitry Andric     const char *name = die.GetName();
4465f757f3fSDimitry Andric     if (!name || !name[0])
447*0fca6ea1SDimitry Andric       return;
448*0fca6ea1SDimitry Andric 
449*0fca6ea1SDimitry Andric     // Add this DIE's contribution at the end of the chain.
4505f757f3fSDimitry Andric     auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) {
4515f757f3fSDimitry Andric       context.push_back({kind, ConstString(name)});
4525f757f3fSDimitry Andric     };
453*0fca6ea1SDimitry Andric     switch (die.Tag()) {
4545f757f3fSDimitry Andric     case DW_TAG_namespace:
455*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::Namespace, die.GetName());
4565f757f3fSDimitry Andric       break;
4575f757f3fSDimitry Andric     case DW_TAG_class_type:
458*0fca6ea1SDimitry Andric     case DW_TAG_structure_type:
459*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::ClassOrStruct, die.GetName());
460*0fca6ea1SDimitry Andric       break;
461*0fca6ea1SDimitry Andric     case DW_TAG_union_type:
462*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::Union, die.GetName());
4635f757f3fSDimitry Andric       break;
4645f757f3fSDimitry Andric     case DW_TAG_enumeration_type:
465*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::Enum, die.GetName());
4665f757f3fSDimitry Andric       break;
4675f757f3fSDimitry Andric     case DW_TAG_variable:
468*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::Variable, die.GetPubname());
4695f757f3fSDimitry Andric       break;
4705f757f3fSDimitry Andric     case DW_TAG_typedef:
471*0fca6ea1SDimitry Andric       push_ctx(CompilerContextKind::Typedef, die.GetName());
4725f757f3fSDimitry Andric       break;
4735f757f3fSDimitry Andric     case DW_TAG_base_type:
4745f757f3fSDimitry Andric       push_ctx(CompilerContextKind::Builtin, name);
4755f757f3fSDimitry Andric       break;
476*0fca6ea1SDimitry Andric     // If any of the tags below appear in the parent chain, stop the decl
477*0fca6ea1SDimitry Andric     // context and return. Prior to these being in here, if a type existed in a
478*0fca6ea1SDimitry Andric     // namespace "a" like "a::my_struct", but we also have a function in that
479*0fca6ea1SDimitry Andric     // same namespace "a" which contained a type named "my_struct", both would
480*0fca6ea1SDimitry Andric     // return "a::my_struct" as the declaration context since the
481*0fca6ea1SDimitry Andric     // DW_TAG_subprogram would be skipped and its parent would be found.
482*0fca6ea1SDimitry Andric     case DW_TAG_compile_unit:
483*0fca6ea1SDimitry Andric     case DW_TAG_type_unit:
484*0fca6ea1SDimitry Andric     case DW_TAG_subprogram:
485*0fca6ea1SDimitry Andric     case DW_TAG_lexical_block:
486*0fca6ea1SDimitry Andric     case DW_TAG_inlined_subroutine:
487*0fca6ea1SDimitry Andric       return;
4885f757f3fSDimitry Andric     default:
4895f757f3fSDimitry Andric       break;
4905f757f3fSDimitry Andric     }
491*0fca6ea1SDimitry Andric     // Now process the parent.
492*0fca6ea1SDimitry Andric     die = die.GetParent();
493*0fca6ea1SDimitry Andric   }
494*0fca6ea1SDimitry Andric }
495*0fca6ea1SDimitry Andric 
496*0fca6ea1SDimitry Andric std::vector<CompilerContext> DWARFDIE::GetTypeLookupContext() const {
497*0fca6ea1SDimitry Andric   llvm::SmallSet<lldb::user_id_t, 4> seen;
498*0fca6ea1SDimitry Andric   std::vector<CompilerContext> context;
499*0fca6ea1SDimitry Andric   GetTypeLookupContextImpl(*this, seen, context);
500*0fca6ea1SDimitry Andric   std::reverse(context.begin(), context.end());
5015f757f3fSDimitry Andric   return context;
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
504*0fca6ea1SDimitry Andric static DWARFDeclContext GetDWARFDeclContextImpl(DWARFDIE die) {
505*0fca6ea1SDimitry Andric   DWARFDeclContext dwarf_decl_ctx;
506*0fca6ea1SDimitry Andric   while (die) {
507*0fca6ea1SDimitry Andric     const dw_tag_t tag = die.Tag();
508*0fca6ea1SDimitry Andric     if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
509*0fca6ea1SDimitry Andric       break;
510*0fca6ea1SDimitry Andric     dwarf_decl_ctx.AppendDeclContext(tag, die.GetName());
511*0fca6ea1SDimitry Andric     DWARFDIE parent_decl_ctx_die = die.GetParentDeclContextDIE();
512*0fca6ea1SDimitry Andric     if (parent_decl_ctx_die == die)
513*0fca6ea1SDimitry Andric       break;
514*0fca6ea1SDimitry Andric     die = parent_decl_ctx_die;
515*0fca6ea1SDimitry Andric   }
516*0fca6ea1SDimitry Andric   return dwarf_decl_ctx;
517*0fca6ea1SDimitry Andric }
518*0fca6ea1SDimitry Andric 
519*0fca6ea1SDimitry Andric DWARFDeclContext DWARFDIE::GetDWARFDeclContext() const {
520*0fca6ea1SDimitry Andric   return GetDWARFDeclContextImpl(*this);
521*0fca6ea1SDimitry Andric }
522*0fca6ea1SDimitry Andric 
523*0fca6ea1SDimitry Andric static DWARFDIE GetParentDeclContextDIEImpl(DWARFDIE die) {
524*0fca6ea1SDimitry Andric   DWARFDIE orig_die = die;
525*0fca6ea1SDimitry Andric   while (die) {
526*0fca6ea1SDimitry Andric     // If this is the original DIE that we are searching for a declaration for,
527*0fca6ea1SDimitry Andric     // then don't look in the cache as we don't want our own decl context to be
528*0fca6ea1SDimitry Andric     // our decl context...
529*0fca6ea1SDimitry Andric     if (die != orig_die) {
530*0fca6ea1SDimitry Andric       switch (die.Tag()) {
531*0fca6ea1SDimitry Andric       case DW_TAG_compile_unit:
532*0fca6ea1SDimitry Andric       case DW_TAG_partial_unit:
533*0fca6ea1SDimitry Andric       case DW_TAG_namespace:
534*0fca6ea1SDimitry Andric       case DW_TAG_structure_type:
535*0fca6ea1SDimitry Andric       case DW_TAG_union_type:
536*0fca6ea1SDimitry Andric       case DW_TAG_class_type:
537*0fca6ea1SDimitry Andric         return die;
538*0fca6ea1SDimitry Andric 
539*0fca6ea1SDimitry Andric       default:
540*0fca6ea1SDimitry Andric         break;
541*0fca6ea1SDimitry Andric       }
542*0fca6ea1SDimitry Andric     }
543*0fca6ea1SDimitry Andric 
544*0fca6ea1SDimitry Andric     if (DWARFDIE spec_die = die.GetReferencedDIE(DW_AT_specification)) {
545*0fca6ea1SDimitry Andric       if (DWARFDIE decl_ctx_die = spec_die.GetParentDeclContextDIE())
546*0fca6ea1SDimitry Andric         return decl_ctx_die;
547*0fca6ea1SDimitry Andric     }
548*0fca6ea1SDimitry Andric 
549*0fca6ea1SDimitry Andric     if (DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin)) {
550*0fca6ea1SDimitry Andric       if (DWARFDIE decl_ctx_die = abs_die.GetParentDeclContextDIE())
551*0fca6ea1SDimitry Andric         return decl_ctx_die;
552*0fca6ea1SDimitry Andric     }
553*0fca6ea1SDimitry Andric 
554*0fca6ea1SDimitry Andric     die = die.GetParent();
555*0fca6ea1SDimitry Andric   }
556*0fca6ea1SDimitry Andric   return DWARFDIE();
557*0fca6ea1SDimitry Andric }
558*0fca6ea1SDimitry Andric 
5590b57cec5SDimitry Andric DWARFDIE
5600b57cec5SDimitry Andric DWARFDIE::GetParentDeclContextDIE() const {
561*0fca6ea1SDimitry Andric   return GetParentDeclContextDIEImpl(*this);
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric bool DWARFDIE::IsStructUnionOrClass() const {
5650b57cec5SDimitry Andric   const dw_tag_t tag = Tag();
5660b57cec5SDimitry Andric   return tag == DW_TAG_class_type || tag == DW_TAG_structure_type ||
5670b57cec5SDimitry Andric          tag == DW_TAG_union_type;
5680b57cec5SDimitry Andric }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric bool DWARFDIE::IsMethod() const {
5710b57cec5SDimitry Andric   for (DWARFDIE d : elaborating_dies(*this))
5720b57cec5SDimitry Andric     if (d.GetParent().IsStructUnionOrClass())
5730b57cec5SDimitry Andric       return true;
5740b57cec5SDimitry Andric   return false;
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric bool DWARFDIE::GetDIENamesAndRanges(
5780b57cec5SDimitry Andric     const char *&name, const char *&mangled, DWARFRangeList &ranges,
57906c3fb27SDimitry Andric     std::optional<int> &decl_file, std::optional<int> &decl_line,
58006c3fb27SDimitry Andric     std::optional<int> &decl_column, std::optional<int> &call_file,
58106c3fb27SDimitry Andric     std::optional<int> &call_line, std::optional<int> &call_column,
582753f127fSDimitry Andric     lldb_private::DWARFExpressionList *frame_base) const {
5830b57cec5SDimitry Andric   if (IsValid()) {
5840b57cec5SDimitry Andric     return m_die->GetDIENamesAndRanges(
5850b57cec5SDimitry Andric         GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column,
5860b57cec5SDimitry Andric         call_file, call_line, call_column, frame_base);
5870b57cec5SDimitry Andric   } else
5880b57cec5SDimitry Andric     return false;
5890b57cec5SDimitry Andric }
590349cc55cSDimitry Andric 
591349cc55cSDimitry Andric llvm::iterator_range<DWARFDIE::child_iterator> DWARFDIE::children() const {
592349cc55cSDimitry Andric   return llvm::make_range(child_iterator(*this), child_iterator());
593349cc55cSDimitry Andric }
594