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