1 //===- DWARFAbbreviationDeclaration.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 LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H 11 12 #include "llvm/ADT/SmallVector.h" 13 #include "llvm/ADT/iterator_range.h" 14 #include "llvm/BinaryFormat/Dwarf.h" 15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 16 #include <cassert> 17 #include <cstddef> 18 #include <cstdint> 19 20 namespace llvm { 21 22 class DataExtractor; 23 class DWARFUnit; 24 class raw_ostream; 25 26 class DWARFAbbreviationDeclaration { 27 public: 28 enum class ExtractState { Complete, MoreItems }; 29 struct AttributeSpec { AttributeSpecAttributeSpec30 AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value) 31 : Attr(A), Form(F), Value(Value) { 32 assert(isImplicitConst()); 33 } AttributeSpecAttributeSpec34 AttributeSpec(dwarf::Attribute A, dwarf::Form F, 35 std::optional<uint8_t> ByteSize) 36 : Attr(A), Form(F) { 37 assert(!isImplicitConst()); 38 this->ByteSize.HasByteSize = ByteSize.has_value(); 39 if (this->ByteSize.HasByteSize) 40 this->ByteSize.ByteSize = *ByteSize; 41 } 42 getFormValueAttributeSpec43 DWARFFormValue getFormValue() const { 44 if (Form == dwarf::DW_FORM_implicit_const) 45 return DWARFFormValue::createFromSValue(Form, getImplicitConstValue()); 46 47 return DWARFFormValue(Form); 48 } 49 50 dwarf::Attribute Attr; 51 dwarf::Form Form; 52 53 private: 54 /// The following field is used for ByteSize for non-implicit_const 55 /// attributes and as value for implicit_const ones, indicated by 56 /// Form == DW_FORM_implicit_const. 57 /// The following cases are distinguished: 58 /// * Form != DW_FORM_implicit_const and HasByteSize is true: 59 /// ByteSize contains the fixed size in bytes for the Form in this 60 /// object. 61 /// * Form != DW_FORM_implicit_const and HasByteSize is false: 62 /// byte size of Form either varies according to the DWARFUnit 63 /// that it is contained in or the value size varies and must be 64 /// decoded from the debug information in order to determine its size. 65 /// * Form == DW_FORM_implicit_const: 66 /// Value contains value for the implicit_const attribute. 67 struct ByteSizeStorage { 68 bool HasByteSize; 69 uint8_t ByteSize; 70 }; 71 union { 72 ByteSizeStorage ByteSize; 73 int64_t Value; 74 }; 75 76 public: isImplicitConstAttributeSpec77 bool isImplicitConst() const { 78 return Form == dwarf::DW_FORM_implicit_const; 79 } 80 getImplicitConstValueAttributeSpec81 int64_t getImplicitConstValue() const { 82 assert(isImplicitConst()); 83 return Value; 84 } 85 86 /// Get the fixed byte size of this Form if possible. This function might 87 /// use the DWARFUnit to calculate the size of the Form, like for 88 /// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for 89 /// the ByteSize member. 90 std::optional<int64_t> getByteSize(const DWARFUnit &U) const; 91 }; 92 using AttributeSpecVector = SmallVector<AttributeSpec, 8>; 93 94 DWARFAbbreviationDeclaration(); 95 getCode()96 uint32_t getCode() const { return Code; } getCodeByteSize()97 uint8_t getCodeByteSize() const { return CodeByteSize; } getTag()98 dwarf::Tag getTag() const { return Tag; } hasChildren()99 bool hasChildren() const { return HasChildren; } 100 101 using attr_iterator_range = 102 iterator_range<AttributeSpecVector::const_iterator>; 103 attributes()104 attr_iterator_range attributes() const { 105 return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); 106 } 107 getFormByIndex(uint32_t idx)108 dwarf::Form getFormByIndex(uint32_t idx) const { 109 assert(idx < AttributeSpecs.size()); 110 return AttributeSpecs[idx].Form; 111 } 112 getNumAttributes()113 size_t getNumAttributes() const { 114 return AttributeSpecs.size(); 115 } 116 getAttrByIndex(uint32_t idx)117 dwarf::Attribute getAttrByIndex(uint32_t idx) const { 118 assert(idx < AttributeSpecs.size()); 119 return AttributeSpecs[idx].Attr; 120 } 121 getAttrIsImplicitConstByIndex(uint32_t idx)122 bool getAttrIsImplicitConstByIndex(uint32_t idx) const { 123 assert(idx < AttributeSpecs.size()); 124 return AttributeSpecs[idx].isImplicitConst(); 125 } 126 getAttrImplicitConstValueByIndex(uint32_t idx)127 int64_t getAttrImplicitConstValueByIndex(uint32_t idx) const { 128 assert(idx < AttributeSpecs.size()); 129 return AttributeSpecs[idx].getImplicitConstValue(); 130 } 131 132 /// Get the index of the specified attribute. 133 /// 134 /// Searches the this abbreviation declaration for the index of the specified 135 /// attribute. 136 /// 137 /// \param attr DWARF attribute to search for. 138 /// \returns Optional index of the attribute if found, std::nullopt otherwise. 139 std::optional<uint32_t> findAttributeIndex(dwarf::Attribute attr) const; 140 141 /// Extract a DWARF form value from a DIE specified by DIE offset. 142 /// 143 /// Extract an attribute value for a DWARFUnit given the DIE offset and the 144 /// attribute. 145 /// 146 /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation 147 /// code in the .debug_info data. 148 /// \param Attr DWARF attribute to search for. 149 /// \param U the DWARFUnit the contains the DIE. 150 /// \returns Optional DWARF form value if the attribute was extracted. 151 std::optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset, 152 const dwarf::Attribute Attr, 153 const DWARFUnit &U) const; 154 155 /// Compute an offset from a DIE specified by DIE offset and attribute index. 156 /// 157 /// \param AttrIndex an index of DWARF attribute. 158 /// \param DIEOffset the DIE offset that points to the ULEB128 abbreviation 159 /// code in the .debug_info data. 160 /// \param U the DWARFUnit the contains the DIE. 161 /// \returns an offset of the attribute. 162 uint64_t getAttributeOffsetFromIndex(uint32_t AttrIndex, uint64_t DIEOffset, 163 const DWARFUnit &U) const; 164 165 /// Extract a DWARF form value from a DIE speccified by attribute index and 166 /// its offset. 167 /// 168 /// \param AttrIndex an index of DWARF attribute. 169 /// \param Offset offset of the attribute. 170 /// \param U the DWARFUnit the contains the DIE. 171 /// \returns Optional DWARF form value if the attribute was extracted. 172 std::optional<DWARFFormValue> 173 getAttributeValueFromOffset(uint32_t AttrIndex, uint64_t Offset, 174 const DWARFUnit &U) const; 175 176 llvm::Expected<ExtractState> extract(DataExtractor Data, uint64_t *OffsetPtr); 177 void dump(raw_ostream &OS) const; 178 179 // Return an optional byte size of all attribute data in this abbreviation 180 // if a constant byte size can be calculated given a DWARFUnit. This allows 181 // DWARF parsing to be faster as many DWARF DIEs have a fixed byte size. 182 std::optional<size_t> getFixedAttributesByteSize(const DWARFUnit &U) const; 183 184 private: 185 void clear(); 186 187 /// A helper structure that can quickly determine the size in bytes of an 188 /// abbreviation declaration. 189 struct FixedSizeInfo { 190 /// The fixed byte size for fixed size forms. 191 uint16_t NumBytes = 0; 192 /// Number of DW_FORM_address forms in this abbrevation declaration. 193 uint8_t NumAddrs = 0; 194 /// Number of DW_FORM_ref_addr forms in this abbrevation declaration. 195 uint8_t NumRefAddrs = 0; 196 /// Number of 4 byte in DWARF32 and 8 byte in DWARF64 forms. 197 uint8_t NumDwarfOffsets = 0; 198 199 FixedSizeInfo() = default; 200 201 /// Calculate the fixed size in bytes given a DWARFUnit. 202 /// 203 /// \param U the DWARFUnit to use when determing the byte size. 204 /// \returns the size in bytes for all attribute data in this abbreviation. 205 /// The returned size does not include bytes for the ULEB128 abbreviation 206 /// code 207 size_t getByteSize(const DWARFUnit &U) const; 208 }; 209 210 uint32_t Code; 211 dwarf::Tag Tag; 212 uint8_t CodeByteSize; 213 bool HasChildren; 214 AttributeSpecVector AttributeSpecs; 215 /// If this abbreviation has a fixed byte size then FixedAttributeSize member 216 /// variable below will have a value. 217 std::optional<FixedSizeInfo> FixedAttributeSize; 218 }; 219 220 } // end namespace llvm 221 222 #endif // LLVM_DEBUGINFO_DWARF_DWARFABBREVIATIONDECLARATION_H 223