blob: f066dd58d606910dbef2f086c0553d36dbdbf074 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
Andrew Walbran3d2c1972020-04-07 12:24:26 +010044 BaseTypeRef = 8,
45 SignBit = 0x80,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010046 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,
Andrew Walbran3d2c1972020-04-07 12:24:26 +010058 Dwarf4,
59 Dwarf5
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010060 };
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 uint32_t EndOffset;
81 uint64_t Operands[2];
Andrew Walbran3d2c1972020-04-07 12:24:26 +010082 uint32_t OperandEndOffsets[2];
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010083
84 public:
85 Description &getDescription() { return Desc; }
86 uint8_t getCode() { return Opcode; }
87 uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
Andrew Walbran3d2c1972020-04-07 12:24:26 +010088 uint32_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010089 uint32_t getEndOffset() { return EndOffset; }
90 bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
91 uint32_t Offset);
92 bool isError() { return Error; }
Andrew Walbran3d2c1972020-04-07 12:24:26 +010093 bool print(raw_ostream &OS, const DWARFExpression *Expr,
94 const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
95 bool verify(DWARFUnit *U);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010096 };
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 uint32_t Offset;
105 Operation Op;
106 iterator(const DWARFExpression *Expr, uint32_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) {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100132 assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100133 }
134
135 iterator begin() const { return iterator(this, 0); }
136 iterator end() const { return iterator(this, Data.getData().size()); }
137
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100138 void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100139 bool IsEH = false) const;
140
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100141 bool verify(DWARFUnit *U);
142
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100143private:
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