10b57cec5SDimitry Andric //===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9fe6060f1SDimitry Andric #ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H 10fe6060f1SDimitry Andric #define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H 110b57cec5SDimitry Andric 1281ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 130b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 145ffd83dbSDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 150b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric namespace llvm { 180b57cec5SDimitry Andric class DWARFUnit; 1981ad6265SDimitry Andric struct DIDumpOptions; 200b57cec5SDimitry Andric class MCRegisterInfo; 210b57cec5SDimitry Andric class raw_ostream; 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric class DWARFExpression { 240b57cec5SDimitry Andric public: 250b57cec5SDimitry Andric class iterator; 260b57cec5SDimitry Andric 2706c3fb27SDimitry Andric /// This class represents an Operation in the Expression. 280b57cec5SDimitry Andric /// 290b57cec5SDimitry Andric /// An Operation can be in Error state (check with isError()). This 300b57cec5SDimitry Andric /// means that it couldn't be decoded successfully and if it is the 310b57cec5SDimitry Andric /// case, all others fields contain undefined values. 320b57cec5SDimitry Andric class Operation { 330b57cec5SDimitry Andric public: 340b57cec5SDimitry Andric /// Size and signedness of expression operations' operands. 350b57cec5SDimitry Andric enum Encoding : uint8_t { 360b57cec5SDimitry Andric Size1 = 0, 370b57cec5SDimitry Andric Size2 = 1, 380b57cec5SDimitry Andric Size4 = 2, 390b57cec5SDimitry Andric Size8 = 3, 400b57cec5SDimitry Andric SizeLEB = 4, 410b57cec5SDimitry Andric SizeAddr = 5, 420b57cec5SDimitry Andric SizeRefAddr = 6, 430b57cec5SDimitry Andric SizeBlock = 7, ///< Preceding operand contains block size 440b57cec5SDimitry Andric BaseTypeRef = 8, 4506c3fb27SDimitry Andric /// The operand is a ULEB128 encoded SubOpcode. This is only valid 4606c3fb27SDimitry Andric /// for the first operand of an operation. 4706c3fb27SDimitry Andric SizeSubOpLEB = 9, 485ffd83dbSDimitry Andric WasmLocationArg = 30, 490b57cec5SDimitry Andric SignBit = 0x80, 500b57cec5SDimitry Andric SignedSize1 = SignBit | Size1, 510b57cec5SDimitry Andric SignedSize2 = SignBit | Size2, 520b57cec5SDimitry Andric SignedSize4 = SignBit | Size4, 530b57cec5SDimitry Andric SignedSize8 = SignBit | Size8, 540b57cec5SDimitry Andric SignedSizeLEB = SignBit | SizeLEB, 550b57cec5SDimitry Andric }; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric enum DwarfVersion : uint8_t { 580b57cec5SDimitry Andric DwarfNA, ///< Serves as a marker for unused entries 590b57cec5SDimitry Andric Dwarf2 = 2, 600b57cec5SDimitry Andric Dwarf3, 610b57cec5SDimitry Andric Dwarf4, 620b57cec5SDimitry Andric Dwarf5 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric /// Description of the encoding of one expression Op. 660b57cec5SDimitry Andric struct Description { 670b57cec5SDimitry Andric DwarfVersion Version; ///< Dwarf version where the Op was introduced. 6806c3fb27SDimitry Andric SmallVector<Encoding> Op; ///< Encoding for Op operands. 690b57cec5SDimitry Andric 7006c3fb27SDimitry Andric template <typename... Ts> DescriptionDescription7106c3fb27SDimitry Andric Description(DwarfVersion Version, Ts... Op) 7206c3fb27SDimitry Andric : Version(Version), Op{Op...} {} DescriptionDescription7306c3fb27SDimitry Andric Description() : Description(DwarfNA) {} 7406c3fb27SDimitry Andric ~Description() = default; 750b57cec5SDimitry Andric }; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric private: 780b57cec5SDimitry Andric friend class DWARFExpression::iterator; 790b57cec5SDimitry Andric uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>. 800b57cec5SDimitry Andric Description Desc; 81fe6060f1SDimitry Andric bool Error = false; 828bcb0991SDimitry Andric uint64_t EndOffset; 8306c3fb27SDimitry Andric SmallVector<uint64_t> Operands; 8406c3fb27SDimitry Andric SmallVector<uint64_t> OperandEndOffsets; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric public: getDescription()87349cc55cSDimitry Andric const Description &getDescription() const { return Desc; } getCode()88349cc55cSDimitry Andric uint8_t getCode() const { return Opcode; } 8906c3fb27SDimitry Andric std::optional<unsigned> getSubCode() const; getNumOperands()9006c3fb27SDimitry Andric uint64_t getNumOperands() const { return Operands.size(); } getRawOperands()9106c3fb27SDimitry Andric ArrayRef<uint64_t> getRawOperands() const { return Operands; }; getRawOperand(unsigned Idx)92349cc55cSDimitry Andric uint64_t getRawOperand(unsigned Idx) const { return Operands[Idx]; } getOperandEndOffsets()9306c3fb27SDimitry Andric ArrayRef<uint64_t> getOperandEndOffsets() const { 9406c3fb27SDimitry Andric return OperandEndOffsets; 9506c3fb27SDimitry Andric } getOperandEndOffset(unsigned Idx)96349cc55cSDimitry Andric uint64_t getOperandEndOffset(unsigned Idx) const { 97349cc55cSDimitry Andric return OperandEndOffsets[Idx]; 98349cc55cSDimitry Andric } getEndOffset()99349cc55cSDimitry Andric uint64_t getEndOffset() const { return EndOffset; } isError()100349cc55cSDimitry Andric bool isError() const { return Error; } 101e8d8bef9SDimitry Andric bool print(raw_ostream &OS, DIDumpOptions DumpOpts, 102bdd1243dSDimitry Andric const DWARFExpression *Expr, DWARFUnit *U) const; 103349cc55cSDimitry Andric 104349cc55cSDimitry Andric /// Verify \p Op. Does not affect the return of \a isError(). 105349cc55cSDimitry Andric static bool verify(const Operation &Op, DWARFUnit *U); 106349cc55cSDimitry Andric 107349cc55cSDimitry Andric private: 108349cc55cSDimitry Andric bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset, 109bdd1243dSDimitry Andric std::optional<dwarf::DwarfFormat> Format); 1100b57cec5SDimitry Andric }; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric /// An iterator to go through the expression operations. 1130b57cec5SDimitry Andric class iterator 1140b57cec5SDimitry Andric : public iterator_facade_base<iterator, std::forward_iterator_tag, 115349cc55cSDimitry Andric const Operation> { 1160b57cec5SDimitry Andric friend class DWARFExpression; 1170b57cec5SDimitry Andric const DWARFExpression *Expr; 1188bcb0991SDimitry Andric uint64_t Offset; 1190b57cec5SDimitry Andric Operation Op; iterator(const DWARFExpression * Expr,uint64_t Offset)1208bcb0991SDimitry Andric iterator(const DWARFExpression *Expr, uint64_t Offset) 1210b57cec5SDimitry Andric : Expr(Expr), Offset(Offset) { 1220b57cec5SDimitry Andric Op.Error = 1230b57cec5SDimitry Andric Offset >= Expr->Data.getData().size() || 1245ffd83dbSDimitry Andric !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric public: 128349cc55cSDimitry Andric iterator &operator++() { 1290b57cec5SDimitry Andric Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset; 1300b57cec5SDimitry Andric Op.Error = 1310b57cec5SDimitry Andric Offset >= Expr->Data.getData().size() || 1325ffd83dbSDimitry Andric !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format); 133349cc55cSDimitry Andric return *this; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 136349cc55cSDimitry Andric const Operation &operator*() const { return Op; } 1370b57cec5SDimitry Andric skipBytes(uint64_t Add)138349cc55cSDimitry Andric iterator skipBytes(uint64_t Add) const { 1395ffd83dbSDimitry Andric return iterator(Expr, Op.EndOffset + Add); 1405ffd83dbSDimitry Andric } 1415ffd83dbSDimitry Andric 1420b57cec5SDimitry Andric // Comparison operators are provided out of line. 1430b57cec5SDimitry Andric friend bool operator==(const iterator &, const iterator &); 1440b57cec5SDimitry Andric }; 1450b57cec5SDimitry Andric 1465ffd83dbSDimitry Andric DWARFExpression(DataExtractor Data, uint8_t AddressSize, 147bdd1243dSDimitry Andric std::optional<dwarf::DwarfFormat> Format = std::nullopt) Data(Data)1485ffd83dbSDimitry Andric : Data(Data), AddressSize(AddressSize), Format(Format) { 1490b57cec5SDimitry Andric assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2); 1500b57cec5SDimitry Andric } 1510b57cec5SDimitry Andric begin()1520b57cec5SDimitry Andric iterator begin() const { return iterator(this, 0); } end()1530b57cec5SDimitry Andric iterator end() const { return iterator(this, Data.getData().size()); } 1540b57cec5SDimitry Andric 155bdd1243dSDimitry Andric void print(raw_ostream &OS, DIDumpOptions DumpOpts, DWARFUnit *U, 1560b57cec5SDimitry Andric bool IsEH = false) const; 1570b57cec5SDimitry Andric 1585ffd83dbSDimitry Andric /// Print the expression in a format intended to be compact and useful to a 1595ffd83dbSDimitry Andric /// user, but not perfectly unambiguous, or capable of representing every 1605ffd83dbSDimitry Andric /// valid DWARF expression. Returns true if the expression was sucessfully 1615ffd83dbSDimitry Andric /// printed. 162bdd1243dSDimitry Andric bool printCompact(raw_ostream &OS, 163bdd1243dSDimitry Andric std::function<StringRef(uint64_t RegNum, bool IsEH)> 164bdd1243dSDimitry Andric GetNameForDWARFReg = nullptr); 1655ffd83dbSDimitry Andric 1660b57cec5SDimitry Andric bool verify(DWARFUnit *U); 1670b57cec5SDimitry Andric 168fe6060f1SDimitry Andric bool operator==(const DWARFExpression &RHS) const; 169fe6060f1SDimitry Andric getData()170349cc55cSDimitry Andric StringRef getData() const { return Data.getData(); } 171349cc55cSDimitry Andric 172bdd1243dSDimitry Andric static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, 173bdd1243dSDimitry Andric DIDumpOptions DumpOpts, uint8_t Opcode, 17406c3fb27SDimitry Andric const ArrayRef<uint64_t> Operands); 175bdd1243dSDimitry Andric 1760b57cec5SDimitry Andric private: 1770b57cec5SDimitry Andric DataExtractor Data; 1780b57cec5SDimitry Andric uint8_t AddressSize; 179bdd1243dSDimitry Andric std::optional<dwarf::DwarfFormat> Format; 1800b57cec5SDimitry Andric }; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric inline bool operator==(const DWARFExpression::iterator &LHS, 1830b57cec5SDimitry Andric const DWARFExpression::iterator &RHS) { 1840b57cec5SDimitry Andric return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric #endif 188