| 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 | |
| 14 | #include "DWARFAttribute.h" |
| 15 | #include "DWARFBaseDIE.h" |
| 16 | #include <map> |
| 17 | #include <optional> |
| 18 | #include <set> |
| 19 | #include <vector> |
| 20 | |
| 21 | #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" |
| 22 | #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" |
| 23 | |
| 24 | namespace lldb_private::plugin { |
| 25 | namespace dwarf { |
| 26 | class DWARFDeclContext; |
| 27 | |
| 28 | #define DIE_SIBLING_IDX_BITSIZE 31 |
| 29 | |
| 30 | /// DWARFDebugInfoEntry objects assume that they are living in one big |
| 31 | /// vector and do pointer arithmetic on their this pointers. Don't |
| 32 | /// pass them by value. Due to the way they are constructed in a |
| 33 | /// std::vector, we cannot delete the copy constructor. |
| 34 | class DWARFDebugInfoEntry { |
| 35 | public: |
| 36 | typedef std::vector<DWARFDebugInfoEntry> collection; |
| 37 | typedef collection::iterator iterator; |
| 38 | typedef collection::const_iterator const_iterator; |
| 39 | |
| 40 | DWARFDebugInfoEntry() |
| 41 | : m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0), |
| 42 | m_has_children(false) {} |
| 43 | |
| 44 | explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; } |
| 45 | bool operator==(const DWARFDebugInfoEntry &rhs) const; |
| 46 | bool operator!=(const DWARFDebugInfoEntry &rhs) const; |
| 47 | |
| 48 | void BuildFunctionAddressRangeTable(DWARFUnit *cu, |
| 49 | DWARFDebugAranges *debug_aranges) const; |
| 50 | |
| 51 | bool (const DWARFDataExtractor &data, const DWARFUnit &cu, |
| 52 | lldb::offset_t *offset_ptr); |
| 53 | |
| 54 | using Recurse = DWARFBaseDIE::Recurse; |
| 55 | |
| 56 | /// Get all attribute values for a given DIE, optionally following any |
| 57 | /// specifications and abstract origins and including their attributes |
| 58 | /// in the result too. |
| 59 | /// |
| 60 | /// When following specifications/abstract origins, the attributes |
| 61 | /// on the referring DIE are guaranteed to be visited before the attributes of |
| 62 | /// the referenced DIE. |
| 63 | /// |
| 64 | /// \param[in] cu DWARFUnit that this entry belongs to. |
| 65 | /// |
| 66 | /// \param[in] recurse If set to \c Recurse::yes, will include attributes |
| 67 | /// on DIEs referenced via \c DW_AT_specification and \c DW_AT_abstract_origin |
| 68 | /// (including across multiple levels of indirection). |
| 69 | /// |
| 70 | /// \returns DWARFAttributes that include all attributes found on this DIE |
| 71 | /// (and possibly referenced DIEs). Attributes may appear multiple times |
| 72 | /// (e.g., if a declaration and definition both specify the same attribute). |
| 73 | /// On failure, the returned DWARFAttributes will be empty. |
| 74 | /// |
| 75 | DWARFAttributes GetAttributes(const DWARFUnit *cu, |
| 76 | Recurse recurse = Recurse::yes) const; |
| 77 | |
| 78 | dw_offset_t GetAttributeValue(const DWARFUnit *cu, const dw_attr_t attr, |
| 79 | DWARFFormValue &formValue, |
| 80 | dw_offset_t *end_attr_offset_ptr = nullptr, |
| 81 | bool check_elaborating_dies = false) const; |
| 82 | |
| 83 | const char * |
| 84 | GetAttributeValueAsString(const DWARFUnit *cu, const dw_attr_t attr, |
| 85 | const char *fail_value, |
| 86 | bool check_elaborating_dies = false) const; |
| 87 | |
| 88 | uint64_t |
| 89 | GetAttributeValueAsUnsigned(const DWARFUnit *cu, const dw_attr_t attr, |
| 90 | uint64_t fail_value, |
| 91 | bool check_elaborating_dies = false) const; |
| 92 | |
| 93 | std::optional<uint64_t> GetAttributeValueAsOptionalUnsigned( |
| 94 | const DWARFUnit *cu, const dw_attr_t attr, |
| 95 | bool check_elaborating_dies = false) const; |
| 96 | |
| 97 | DWARFDIE |
| 98 | GetAttributeValueAsReference(const DWARFUnit *cu, const dw_attr_t attr, |
| 99 | bool check_elaborating_dies = false) const; |
| 100 | |
| 101 | uint64_t |
| 102 | GetAttributeValueAsAddress(const DWARFUnit *cu, const dw_attr_t attr, |
| 103 | uint64_t fail_value, |
| 104 | bool check_elaborating_dies = false) const; |
| 105 | |
| 106 | dw_addr_t GetAttributeHighPC(const DWARFUnit *cu, dw_addr_t lo_pc, |
| 107 | uint64_t fail_value, |
| 108 | bool check_elaborating_dies = false) const; |
| 109 | |
| 110 | bool GetAttributeAddressRange(const DWARFUnit *cu, dw_addr_t &lo_pc, |
| 111 | dw_addr_t &hi_pc, uint64_t fail_value, |
| 112 | bool check_elaborating_dies = false) const; |
| 113 | |
| 114 | llvm::Expected<llvm::DWARFAddressRangesVector> |
| 115 | GetAttributeAddressRanges(DWARFUnit *cu, bool check_hi_lo_pc, |
| 116 | bool check_elaborating_dies = false) const; |
| 117 | |
| 118 | const char *GetName(const DWARFUnit *cu) const; |
| 119 | |
| 120 | const char *GetMangledName(const DWARFUnit *cu, |
| 121 | bool substitute_name_allowed = true) const; |
| 122 | |
| 123 | const char *GetPubname(const DWARFUnit *cu) const; |
| 124 | |
| 125 | bool GetDIENamesAndRanges( |
| 126 | DWARFUnit *cu, const char *&name, const char *&mangled, |
| 127 | llvm::DWARFAddressRangesVector &rangeList, std::optional<int> &decl_file, |
| 128 | std::optional<int> &decl_line, std::optional<int> &decl_column, |
| 129 | std::optional<int> &call_file, std::optional<int> &call_line, |
| 130 | std::optional<int> &call_column, |
| 131 | DWARFExpressionList *frame_base = nullptr) const; |
| 132 | |
| 133 | const llvm::DWARFAbbreviationDeclaration * |
| 134 | GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const; |
| 135 | |
| 136 | lldb::offset_t GetFirstAttributeOffset() const; |
| 137 | |
| 138 | dw_tag_t Tag() const { return m_tag; } |
| 139 | |
| 140 | bool IsNULL() const { return m_abbr_idx == 0; } |
| 141 | |
| 142 | dw_offset_t GetOffset() const { return m_offset; } |
| 143 | |
| 144 | bool HasChildren() const { return m_has_children; } |
| 145 | |
| 146 | void SetHasChildren(bool b) { m_has_children = b; } |
| 147 | |
| 148 | // We know we are kept in a vector of contiguous entries, so we know |
| 149 | // our parent will be some index behind "this". |
| 150 | DWARFDebugInfoEntry *GetParent() { |
| 151 | return m_parent_idx > 0 ? this - m_parent_idx : nullptr; |
| 152 | } |
| 153 | const DWARFDebugInfoEntry *GetParent() const { |
| 154 | return m_parent_idx > 0 ? this - m_parent_idx : nullptr; |
| 155 | } |
| 156 | // We know we are kept in a vector of contiguous entries, so we know |
| 157 | // our sibling will be some index after "this". |
| 158 | DWARFDebugInfoEntry *GetSibling() { |
| 159 | return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; |
| 160 | } |
| 161 | const DWARFDebugInfoEntry *GetSibling() const { |
| 162 | return m_sibling_idx > 0 ? this + m_sibling_idx : nullptr; |
| 163 | } |
| 164 | // We know we are kept in a vector of contiguous entries, so we know |
| 165 | // we don't need to store our child pointer, if we have a child it will |
| 166 | // be the next entry in the list... |
| 167 | DWARFDebugInfoEntry *GetFirstChild() { |
| 168 | return HasChildren() ? this + 1 : nullptr; |
| 169 | } |
| 170 | const DWARFDebugInfoEntry *GetFirstChild() const { |
| 171 | return HasChildren() ? this + 1 : nullptr; |
| 172 | } |
| 173 | |
| 174 | void SetSiblingIndex(uint32_t idx) { m_sibling_idx = idx; } |
| 175 | void SetParentIndex(uint32_t idx) { m_parent_idx = idx; } |
| 176 | |
| 177 | // This function returns true if the variable scope is either |
| 178 | // global or (file-static). It will return false for static variables |
| 179 | // that are local to a function, as they have local scope. |
| 180 | bool IsGlobalOrStaticScopeVariable() const; |
| 181 | |
| 182 | protected: |
| 183 | // Up to 2TB offset within the .debug_info/.debug_types |
| 184 | dw_offset_t m_offset : DW_DIE_OFFSET_MAX_BITSIZE; |
| 185 | // How many to subtract from "this" to get the parent. If zero this die has no |
| 186 | // parent |
| 187 | dw_offset_t m_parent_idx : 64 - DW_DIE_OFFSET_MAX_BITSIZE; |
| 188 | // How many to add to "this" to get the sibling. |
| 189 | // If it is zero, then the DIE doesn't have children, |
| 190 | // or the DWARF claimed it had children but the DIE |
| 191 | // only contained a single NULL terminating child. |
| 192 | uint32_t m_sibling_idx : 31, m_has_children : 1; |
| 193 | uint16_t m_abbr_idx = 0; |
| 194 | /// A copy of the DW_TAG value so we don't have to go through the compile |
| 195 | /// unit abbrev table |
| 196 | dw_tag_t m_tag = llvm::dwarf::DW_TAG_null; |
| 197 | }; |
| 198 | } // namespace dwarf |
| 199 | } // namespace lldb_private::plugin |
| 200 | |
| 201 | #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFDEBUGINFOENTRY_H |
| 202 | |