DWARFAbbreviationDeclaration.h 6.8 KB

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