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