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