blob: 447ad66b93526a4a8f3172ee6aa4ee86bbb53821 [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"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020013#include "llvm/ADT/Optional.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010014#include "llvm/ADT/iterator.h"
15#include "llvm/ADT/iterator_range.h"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020016#include "llvm/BinaryFormat/Dwarf.h"
17#include "llvm/DebugInfo/DIContext.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010018#include "llvm/Support/DataExtractor.h"
19
20namespace llvm {
21class DWARFUnit;
22class MCRegisterInfo;
23class raw_ostream;
24
25class DWARFExpression {
26public:
27 class iterator;
28
29 /// This class represents an Operation in the Expression. Each operation can
30 /// have up to 2 oprerands.
31 ///
32 /// An Operation can be in Error state (check with isError()). This
33 /// means that it couldn't be decoded successfully and if it is the
34 /// case, all others fields contain undefined values.
35 class Operation {
36 public:
37 /// Size and signedness of expression operations' operands.
38 enum Encoding : uint8_t {
39 Size1 = 0,
40 Size2 = 1,
41 Size4 = 2,
42 Size8 = 3,
43 SizeLEB = 4,
44 SizeAddr = 5,
45 SizeRefAddr = 6,
46 SizeBlock = 7, ///< Preceding operand contains block size
Andrew Walbran3d2c1972020-04-07 12:24:26 +010047 BaseTypeRef = 8,
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020048 WasmLocationArg = 30,
Andrew Walbran3d2c1972020-04-07 12:24:26 +010049 SignBit = 0x80,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010050 SignedSize1 = SignBit | Size1,
51 SignedSize2 = SignBit | Size2,
52 SignedSize4 = SignBit | Size4,
53 SignedSize8 = SignBit | Size8,
54 SignedSizeLEB = SignBit | SizeLEB,
55 SizeNA = 0xFF ///< Unused operands get this encoding.
56 };
57
58 enum DwarfVersion : uint8_t {
59 DwarfNA, ///< Serves as a marker for unused entries
60 Dwarf2 = 2,
61 Dwarf3,
Andrew Walbran3d2c1972020-04-07 12:24:26 +010062 Dwarf4,
63 Dwarf5
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010064 };
65
66 /// Description of the encoding of one expression Op.
67 struct Description {
68 DwarfVersion Version; ///< Dwarf version where the Op was introduced.
69 Encoding Op[2]; ///< Encoding for Op operands, or SizeNA.
70
71 Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
72 Encoding Op2 = SizeNA)
73 : Version(Version) {
74 Op[0] = Op1;
75 Op[1] = Op2;
76 }
77 };
78
79 private:
80 friend class DWARFExpression::iterator;
81 uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
82 Description Desc;
83 bool Error;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020084 uint64_t EndOffset;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010085 uint64_t Operands[2];
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020086 uint64_t OperandEndOffsets[2];
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010087
88 public:
89 Description &getDescription() { return Desc; }
90 uint8_t getCode() { return Opcode; }
91 uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020092 uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
93 uint64_t getEndOffset() { return EndOffset; }
94 bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
95 Optional<dwarf::DwarfFormat> Format);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010096 bool isError() { return Error; }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020097 bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
98 const DWARFExpression *Expr, const MCRegisterInfo *RegInfo,
99 DWARFUnit *U, bool isEH);
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100100 bool verify(DWARFUnit *U);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100101 };
102
103 /// An iterator to go through the expression operations.
104 class iterator
105 : public iterator_facade_base<iterator, std::forward_iterator_tag,
106 Operation> {
107 friend class DWARFExpression;
108 const DWARFExpression *Expr;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200109 uint64_t Offset;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100110 Operation Op;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200111 iterator(const DWARFExpression *Expr, uint64_t Offset)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100112 : Expr(Expr), Offset(Offset) {
113 Op.Error =
114 Offset >= Expr->Data.getData().size() ||
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200115 !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100116 }
117
118 public:
119 class Operation &operator++() {
120 Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
121 Op.Error =
122 Offset >= Expr->Data.getData().size() ||
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200123 !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100124 return Op;
125 }
126
127 class Operation &operator*() {
128 return Op;
129 }
130
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200131 iterator skipBytes(uint64_t Add) {
132 return iterator(Expr, Op.EndOffset + Add);
133 }
134
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100135 // Comparison operators are provided out of line.
136 friend bool operator==(const iterator &, const iterator &);
137 };
138
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200139 DWARFExpression(DataExtractor Data, uint8_t AddressSize,
140 Optional<dwarf::DwarfFormat> Format = None)
141 : Data(Data), AddressSize(AddressSize), Format(Format) {
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100142 assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100143 }
144
145 iterator begin() const { return iterator(this, 0); }
146 iterator end() const { return iterator(this, Data.getData().size()); }
147
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200148 void print(raw_ostream &OS, DIDumpOptions DumpOpts,
149 const MCRegisterInfo *RegInfo, DWARFUnit *U,
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100150 bool IsEH = false) const;
151
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200152 /// Print the expression in a format intended to be compact and useful to a
153 /// user, but not perfectly unambiguous, or capable of representing every
154 /// valid DWARF expression. Returns true if the expression was sucessfully
155 /// printed.
156 bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo);
157
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100158 bool verify(DWARFUnit *U);
159
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100160private:
161 DataExtractor Data;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100162 uint8_t AddressSize;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200163 Optional<dwarf::DwarfFormat> Format;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100164};
165
166inline bool operator==(const DWARFExpression::iterator &LHS,
167 const DWARFExpression::iterator &RHS) {
168 return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
169}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100170}
171#endif