DWARFExpression.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===--- DWARFExpression.h - DWARF Expression handling ----------*- 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_DWARF_DWARFEXPRESSION_H
  14. #define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
  15. #include "llvm/ADT/StringRef.h"
  16. #include "llvm/ADT/iterator.h"
  17. #include "llvm/BinaryFormat/Dwarf.h"
  18. #include "llvm/Support/DataExtractor.h"
  19. namespace llvm {
  20. class DWARFUnit;
  21. struct DIDumpOptions;
  22. class MCRegisterInfo;
  23. class raw_ostream;
  24. class DWARFExpression {
  25. public:
  26. class iterator;
  27. /// This class represents an Operation in the Expression. Each operation can
  28. /// have up to 2 oprerands.
  29. ///
  30. /// An Operation can be in Error state (check with isError()). This
  31. /// means that it couldn't be decoded successfully and if it is the
  32. /// case, all others fields contain undefined values.
  33. class Operation {
  34. public:
  35. /// Size and signedness of expression operations' operands.
  36. enum Encoding : uint8_t {
  37. Size1 = 0,
  38. Size2 = 1,
  39. Size4 = 2,
  40. Size8 = 3,
  41. SizeLEB = 4,
  42. SizeAddr = 5,
  43. SizeRefAddr = 6,
  44. SizeBlock = 7, ///< Preceding operand contains block size
  45. BaseTypeRef = 8,
  46. WasmLocationArg = 30,
  47. SignBit = 0x80,
  48. SignedSize1 = SignBit | Size1,
  49. SignedSize2 = SignBit | Size2,
  50. SignedSize4 = SignBit | Size4,
  51. SignedSize8 = SignBit | Size8,
  52. SignedSizeLEB = SignBit | SizeLEB,
  53. SizeNA = 0xFF ///< Unused operands get this encoding.
  54. };
  55. enum DwarfVersion : uint8_t {
  56. DwarfNA, ///< Serves as a marker for unused entries
  57. Dwarf2 = 2,
  58. Dwarf3,
  59. Dwarf4,
  60. Dwarf5
  61. };
  62. /// Description of the encoding of one expression Op.
  63. struct Description {
  64. DwarfVersion Version; ///< Dwarf version where the Op was introduced.
  65. Encoding Op[2]; ///< Encoding for Op operands, or SizeNA.
  66. Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
  67. Encoding Op2 = SizeNA)
  68. : Version(Version) {
  69. Op[0] = Op1;
  70. Op[1] = Op2;
  71. }
  72. };
  73. private:
  74. friend class DWARFExpression::iterator;
  75. uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
  76. Description Desc;
  77. bool Error = false;
  78. uint64_t EndOffset;
  79. uint64_t Operands[2];
  80. uint64_t OperandEndOffsets[2];
  81. public:
  82. const Description &getDescription() const { return Desc; }
  83. uint8_t getCode() const { return Opcode; }
  84. uint64_t getRawOperand(unsigned Idx) const { return Operands[Idx]; }
  85. uint64_t getOperandEndOffset(unsigned Idx) const {
  86. return OperandEndOffsets[Idx];
  87. }
  88. uint64_t getEndOffset() const { return EndOffset; }
  89. bool isError() const { return Error; }
  90. bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
  91. const DWARFExpression *Expr, DWARFUnit *U) const;
  92. /// Verify \p Op. Does not affect the return of \a isError().
  93. static bool verify(const Operation &Op, DWARFUnit *U);
  94. private:
  95. bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
  96. std::optional<dwarf::DwarfFormat> Format);
  97. };
  98. /// An iterator to go through the expression operations.
  99. class iterator
  100. : public iterator_facade_base<iterator, std::forward_iterator_tag,
  101. const Operation> {
  102. friend class DWARFExpression;
  103. const DWARFExpression *Expr;
  104. uint64_t Offset;
  105. Operation Op;
  106. iterator(const DWARFExpression *Expr, uint64_t Offset)
  107. : Expr(Expr), Offset(Offset) {
  108. Op.Error =
  109. Offset >= Expr->Data.getData().size() ||
  110. !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
  111. }
  112. public:
  113. iterator &operator++() {
  114. Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
  115. Op.Error =
  116. Offset >= Expr->Data.getData().size() ||
  117. !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
  118. return *this;
  119. }
  120. const Operation &operator*() const { return Op; }
  121. iterator skipBytes(uint64_t Add) const {
  122. return iterator(Expr, Op.EndOffset + Add);
  123. }
  124. // Comparison operators are provided out of line.
  125. friend bool operator==(const iterator &, const iterator &);
  126. };
  127. DWARFExpression(DataExtractor Data, uint8_t AddressSize,
  128. std::optional<dwarf::DwarfFormat> Format = std::nullopt)
  129. : Data(Data), AddressSize(AddressSize), Format(Format) {
  130. assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
  131. }
  132. iterator begin() const { return iterator(this, 0); }
  133. iterator end() const { return iterator(this, Data.getData().size()); }
  134. void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U,
  135. bool IsEH = false) const;
  136. /// Print the expression in a format intended to be compact and useful to a
  137. /// user, but not perfectly unambiguous, or capable of representing every
  138. /// valid DWARF expression. Returns true if the expression was sucessfully
  139. /// printed.
  140. bool printCompact(raw_ostream &OS,
  141. std::function<StringRef(uint64_t RegNum, bool IsEH)>
  142. GetNameForDWARFReg = nullptr);
  143. bool verify(DWARFUnit *U);
  144. bool operator==(const DWARFExpression &RHS) const;
  145. StringRef getData() const { return Data.getData(); }
  146. static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
  147. DIDumpOptions DumpOpts, uint8_t Opcode,
  148. const uint64_t Operands[2]);
  149. private:
  150. DataExtractor Data;
  151. uint8_t AddressSize;
  152. std::optional<dwarf::DwarfFormat> Format;
  153. };
  154. inline bool operator==(const DWARFExpression::iterator &LHS,
  155. const DWARFExpression::iterator &RHS) {
  156. return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
  157. }
  158. }
  159. #endif
  160. #ifdef __GNUC__
  161. #pragma GCC diagnostic pop
  162. #endif