1 //===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H 10 #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H 11 12 #include "SymbolFileDWARF.h" 13 #include "llvm/ADT/SmallVector.h" 14 15 #include "DWARFAttribute.h" 16 #include "DWARFBaseDIE.h" 17 #include "DWARFDebugRanges.h" 18 #include <map> 19 #include <optional> 20 #include <set> 21 #include <vector> 22 23 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 24 25 namespace lldb_private::plugin { 26 namespace dwarf { 27 class DWARFDeclContext; 28 29 #define DIE_SIBLING_IDX_BITSIZE 31 30 31 /// DWARFDebugInfoEntry objects assume that they are living in one big 32 /// vector and do pointer arithmetic on their this pointers. Don't 33 /// pass them by value. Due to the way they are constructed in a 34 /// std::vector, we cannot delete the copy constructor. 35 class DWARFDebugInfoEntry { 36 public: 37 typedef std::vector<DWARFDebugInfoEntry> collection; 38 typedef collection::iterator iterator; 39 typedef collection::const_iterator const_iterator; 40 DWARFDebugInfoEntry()41 DWARFDebugInfoEntry() 42 : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), 43 m_has_children(false) {} 44 45 explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } 46 bool operator==(const DWARFDebugInfoEntry &rhs) const; 47 bool operator!=(const DWARFDebugInfoEntry &rhs) const; 48 49 void BuildFunctionAddressRangeTable(DWARFUnit *cu, 50 DWARFDebugAranges *debug_aranges) const; 51 52 bool Extract(const DWARFDataExtractor &data, const DWARFUnit &cu, 53 lldb::offset_t *offset_ptr); 54 55 using Recurse = DWARFBaseDIE::Recurse; 56 DWARFAttributes GetAttributes(DWARFUnit *cu, 57 Recurse recurse = Recurse::yes) const { 58 DWARFAttributes attrs; 59 GetAttributes(cu, attrs, recurse, 0 /* curr_depth */); 60 return attrs; 61 } 62 63 dw_offset_t 64 GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, 65 DWARFFormValue &formValue, 66 dw_offset_t *end_attr_offset_ptr = nullptr, 67 bool check_specification_or_abstract_origin = false) const; 68 69 const char *GetAttributeValueAsString( 70 const DWARFUnit *cu, const dw_attr_t attr, const char *fail_value, 71 bool check_specification_or_abstract_origin = false) const; 72 73 uint64_t GetAttributeValueAsUnsigned( 74 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 75 bool check_specification_or_abstract_origin = false) const; 76 77 std::optional<uint64_t> GetAttributeValueAsOptionalUnsigned( 78 const DWARFUnit *cu, const dw_attr_t attr, 79 bool check_specification_or_abstract_origin = false) const; 80 81 DWARFDIE GetAttributeValueAsReference( 82 const DWARFUnit *cu, const dw_attr_t attr, 83 bool check_specification_or_abstract_origin = false) const; 84 85 uint64_t GetAttributeValueAsAddress( 86 const DWARFUnit *cu, const dw_attr_t attr, uint64_t fail_value, 87 bool check_specification_or_abstract_origin = false) const; 88 89 dw_addr_t 90 GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value, 91 bool check_specification_or_abstract_origin = false) const; 92 93 bool GetAttributeAddressRange( 94 const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc, 95 uint64_t fail_value, 96 bool check_specification_or_abstract_origin = false) const; 97 98 DWARFRangeList GetAttributeAddressRanges( 99 DWARFUnit *cu, bool check_hi_lo_pc, 100 bool check_specification_or_abstract_origin = false) const; 101 102 const char *GetName(const DWARFUnit *cu) const; 103 104 const char *GetMangledName(const DWARFUnit *cu, 105 bool substitute_name_allowed = true) const; 106 107 const char *GetPubname(const DWARFUnit *cu) const; 108 109 bool GetDIENamesAndRanges(DWARFUnit *cu, const char *&name, 110 const char *&mangled, DWARFRangeList &rangeList, 111 std::optional<int> &decl_file, 112 std::optional<int> &decl_line, 113 std::optional<int> &decl_column, 114 std::optional<int> &call_file, 115 std::optional<int> &call_line, 116 std::optional<int> &call_column, 117 DWARFExpressionList *frame_base = nullptr) const; 118 119 const llvm::DWARFAbbreviationDeclaration * 120 GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; 121 122 lldb::offset_t GetFirstAttributeOffset() const; 123 Tag()124 dw_tag_t Tag() const { return m_tag; } 125 IsNULL()126 bool IsNULL() const { return m_abbr_idx == 0; } 127 GetOffset()128 dw_offset_t GetOffset() const { return m_offset; } 129 HasChildren()130 bool HasChildren() const { return m_has_children; } 131 SetHasChildren(bool b)132 void SetHasChildren(bool b) { m_has_children = b; } 133 134 // We know we are kept in a vector of contiguous entries, so we know 135 // our parent will be some index behind "this". GetParent()136 DWARFDebugInfoEntry *GetParent() { 137 return m_parent_idx > 0 ? this - m_parent_idx : nullptr; 138 } GetParent()139 const DWARFDebugInfoEntry *GetParent() const { 140 return m_parent_idx > 0 ? this - m_parent_idx : nullptr; 141 } 142 // We know we are kept in a vector of contiguous entries, so we know 143 // our sibling will be some index after "this". GetSibling()144 DWARFDebugInfoEntry *GetSibling() { 145 return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; 146 } GetSibling()147 const DWARFDebugInfoEntry *GetSibling() const { 148 return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; 149 } 150 // We know we are kept in a vector of contiguous entries, so we know 151 // we don't need to store our child pointer, if we have a child it will 152 // be the next entry in the list... GetFirstChild()153 DWARFDebugInfoEntry *GetFirstChild() { 154 return HasChildren() ? this + 1 : nullptr; 155 } GetFirstChild()156 const DWARFDebugInfoEntry *GetFirstChild() const { 157 return HasChildren() ? this + 1 : nullptr; 158 } 159 SetSiblingIndex(uint32_t idx)160 void SetSiblingIndex(uint32_t idx) { m_sibling_idx = idx; } SetParentIndex(uint32_t idx)161 void SetParentIndex(uint32_t idx) { m_parent_idx = idx; } 162 163 // This function returns true if the variable scope is either 164 // global or (file-static). It will return false for static variables 165 // that are local to a function, as they have local scope. 166 bool IsGlobalOrStaticScopeVariable() const; 167 168 protected: 169 // Up to 2TB offset within the .debug_info/.debug_types 170 dw_offset_t m_offset : DW_DIE_OFFSET_MAX_BITSIZE; 171 // How many to subtract from "this" to get the parent. If zero this die has no 172 // parent 173 dw_offset_t m_parent_idx : 64 - DW_DIE_OFFSET_MAX_BITSIZE; 174 // How many to add to "this" to get the sibling. 175 // If it is zero, then the DIE doesn't have children, 176 // or the DWARF claimed it had children but the DIE 177 // only contained a single NULL terminating child. 178 uint32_t m_sibling_idx : 31, m_has_children : 1; 179 uint16_t m_abbr_idx = 0; 180 /// A copy of the DW_TAG value so we don't have to go through the compile 181 /// unit abbrev table 182 dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; 183 184 private: 185 void GetAttributes(DWARFUnit *cu, DWARFAttributes &attrs, Recurse recurse, 186 uint32_t curr_depth) const; 187 }; 188 } // namespace dwarf 189 } // namespace lldb_private::plugin 190 191 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H 192