1 //===--- DWARFExpression.h - DWARF Expression handling ----------*- 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_DWARFEXPRESSION_H 11 #define LLVM_DEBUGINFO_DWARFEXPRESSION_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/iterator.h" 15 #include "llvm/ADT/iterator_range.h" 16 #include "llvm/Support/DataExtractor.h" 17 18 namespace llvm { 19 class DWARFUnit; 20 class MCRegisterInfo; 21 class raw_ostream; 22 23 class DWARFExpression { 24 public: 25 class iterator; 26 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 SignBit = 0x8, 46 SignedSize1 = SignBit | Size1, 47 SignedSize2 = SignBit | Size2, 48 SignedSize4 = SignBit | Size4, 49 SignedSize8 = SignBit | Size8, 50 SignedSizeLEB = SignBit | SizeLEB, 51 SizeNA = 0xFF ///< Unused operands get this encoding. 52 }; 53 54 enum DwarfVersion : uint8_t { 55 DwarfNA, ///< Serves as a marker for unused entries 56 Dwarf2 = 2, 57 Dwarf3, 58 Dwarf4 59 }; 60 61 /// Description of the encoding of one expression Op. 62 struct Description { 63 DwarfVersion Version; ///< Dwarf version where the Op was introduced. 64 Encoding Op[2]; ///< Encoding for Op operands, or SizeNA. 65 66 Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA, 67 Encoding Op2 = SizeNA) VersionDescription68 : Version(Version) { 69 Op[0] = Op1; 70 Op[1] = Op2; 71 } 72 }; 73 74 private: 75 friend class DWARFExpression::iterator; 76 uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>. 77 Description Desc; 78 bool Error; 79 uint32_t EndOffset; 80 uint64_t Operands[2]; 81 82 public: getDescription()83 Description &getDescription() { return Desc; } getCode()84 uint8_t getCode() { return Opcode; } getRawOperand(unsigned Idx)85 uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; } getEndOffset()86 uint32_t getEndOffset() { return EndOffset; } 87 bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize, 88 uint32_t Offset); isError()89 bool isError() { return Error; } 90 bool print(raw_ostream &OS, const DWARFExpression *U, 91 const MCRegisterInfo *RegInfo, bool isEH); 92 }; 93 94 /// An iterator to go through the expression operations. 95 class iterator 96 : public iterator_facade_base<iterator, std::forward_iterator_tag, 97 Operation> { 98 friend class DWARFExpression; 99 const DWARFExpression *Expr; 100 uint32_t Offset; 101 Operation Op; iterator(const DWARFExpression * Expr,uint32_t Offset)102 iterator(const DWARFExpression *Expr, uint32_t Offset) 103 : Expr(Expr), Offset(Offset) { 104 Op.Error = 105 Offset >= Expr->Data.getData().size() || 106 !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset); 107 } 108 109 public: 110 class Operation &operator++() { 111 Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset; 112 Op.Error = 113 Offset >= Expr->Data.getData().size() || 114 !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset); 115 return Op; 116 } 117 118 class Operation &operator*() { 119 return Op; 120 } 121 122 // Comparison operators are provided out of line. 123 friend bool operator==(const iterator &, const iterator &); 124 }; 125 DWARFExpression(DataExtractor Data,uint16_t Version,uint8_t AddressSize)126 DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize) 127 : Data(Data), Version(Version), AddressSize(AddressSize) { 128 assert(AddressSize == 8 || AddressSize == 4); 129 } 130 begin()131 iterator begin() const { return iterator(this, 0); } end()132 iterator end() const { return iterator(this, Data.getData().size()); } 133 134 void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, 135 bool IsEH = false) const; 136 137 private: 138 DataExtractor Data; 139 uint16_t Version; 140 uint8_t AddressSize; 141 }; 142 143 inline bool operator==(const DWARFExpression::iterator &LHS, 144 const DWARFExpression::iterator &RHS) { 145 return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset; 146 } 147 148 inline bool operator!=(const DWARFExpression::iterator &LHS, 149 const DWARFExpression::iterator &RHS) { 150 return !(LHS == RHS); 151 } 152 } 153 #endif 154