DWARFExpression.h revision 360784
1//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H
10#define LLVM_DEBUGINFO_DWARFEXPRESSION_H
11
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/iterator.h"
14#include "llvm/ADT/iterator_range.h"
15#include "llvm/Support/DataExtractor.h"
16
17namespace llvm {
18class DWARFUnit;
19class MCRegisterInfo;
20class raw_ostream;
21
22class DWARFExpression {
23public:
24  class iterator;
25
26  /// This class represents an Operation in the Expression. Each operation can
27  /// have up to 2 oprerands.
28  ///
29  /// An Operation can be in Error state (check with isError()). This
30  /// means that it couldn't be decoded successfully and if it is the
31  /// case, all others fields contain undefined values.
32  class Operation {
33  public:
34    /// Size and signedness of expression operations' operands.
35    enum Encoding : uint8_t {
36      Size1 = 0,
37      Size2 = 1,
38      Size4 = 2,
39      Size8 = 3,
40      SizeLEB = 4,
41      SizeAddr = 5,
42      SizeRefAddr = 6,
43      SizeBlock = 7, ///< Preceding operand contains block size
44      BaseTypeRef = 8,
45      SignBit = 0x80,
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      Dwarf5
60    };
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
67      Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
68                  Encoding Op2 = SizeNA)
69          : Version(Version) {
70        Op[0] = Op1;
71        Op[1] = Op2;
72      }
73    };
74
75  private:
76    friend class DWARFExpression::iterator;
77    uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
78    Description Desc;
79    bool Error;
80    uint64_t EndOffset;
81    uint64_t Operands[2];
82    uint64_t OperandEndOffsets[2];
83
84  public:
85    Description &getDescription() { return Desc; }
86    uint8_t getCode() { return Opcode; }
87    uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
88    uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
89    uint64_t getEndOffset() { return EndOffset; }
90    bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
91                 uint64_t Offset);
92    bool isError() { return Error; }
93    bool print(raw_ostream &OS, const DWARFExpression *Expr,
94               const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
95    bool verify(DWARFUnit *U);
96  };
97
98  /// An iterator to go through the expression operations.
99  class iterator
100      : public iterator_facade_base<iterator, std::forward_iterator_tag,
101                                    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->Version, Expr->AddressSize, Offset);
111    }
112
113  public:
114    class Operation &operator++() {
115      Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
116      Op.Error =
117          Offset >= Expr->Data.getData().size() ||
118          !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
119      return Op;
120    }
121
122    class Operation &operator*() {
123      return Op;
124    }
125
126    // Comparison operators are provided out of line.
127    friend bool operator==(const iterator &, const iterator &);
128  };
129
130  DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize)
131      : Data(Data), Version(Version), AddressSize(AddressSize) {
132    assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
133  }
134
135  iterator begin() const { return iterator(this, 0); }
136  iterator end() const { return iterator(this, Data.getData().size()); }
137
138  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
139             bool IsEH = false) const;
140
141  bool verify(DWARFUnit *U);
142
143private:
144  DataExtractor Data;
145  uint16_t Version;
146  uint8_t AddressSize;
147};
148
149inline bool operator==(const DWARFExpression::iterator &LHS,
150                       const DWARFExpression::iterator &RHS) {
151  return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
152}
153
154inline bool operator!=(const DWARFExpression::iterator &LHS,
155                       const DWARFExpression::iterator &RHS) {
156  return !(LHS == RHS);
157}
158}
159#endif
160