LLDB mainline
Opcode.h
Go to the documentation of this file.
1//===-- Opcode.h ------------------------------------------------*- 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 LLDB_CORE_OPCODE_H
10#define LLDB_CORE_OPCODE_H
11
12#include "lldb/Utility/Endian.h"
14
15#include "llvm/ADT/bit.h"
16
17#include <cassert>
18#include <cstdint>
19#include <cstring>
20
21namespace lldb {
22class SBInstruction;
23}
24
25namespace lldb_private {
26class DataExtractor;
27class Stream;
28
29class Opcode {
30public:
31 enum Type {
35 eType16_2, // a 32-bit Thumb instruction, made up of two words
36 eType16_32Tuples, // RISC-V that can have 2, 4, 6, 8 etc byte long
37 // instructions which will be printed in combinations of
38 // 16 & 32-bit words.
42 };
43
44 Opcode() = default;
45
46 /// The size in bytes of the fixed buffer used to store opcode bytes. It must
47 /// be big enough to hold the longest opcode of any supported target (x86
48 /// caps instructions at 15 bytes).
49 static constexpr size_t kMaxByteSize = 16;
50
51 Opcode(uint8_t inst, lldb::ByteOrder order)
52 : m_byte_order(order), m_type(eType8) {
53 m_data.inst8 = inst;
54 }
55
56 Opcode(uint16_t inst, lldb::ByteOrder order)
57 : m_byte_order(order), m_type(eType16) {
58 m_data.inst16 = inst;
59 }
60
61 Opcode(uint32_t inst, lldb::ByteOrder order)
62 : m_byte_order(order), m_type(eType32) {
63 m_data.inst32 = inst;
64 }
65
66 Opcode(uint64_t inst, lldb::ByteOrder order)
67 : m_byte_order(order), m_type(eType64) {
68 m_data.inst64 = inst;
69 }
70
71 Opcode(uint8_t *bytes, size_t length, Opcode::Type type,
72 lldb::ByteOrder order) {
73 DoSetOpcodeBytes(bytes, length, type, order);
74 }
75
80
81 Opcode::Type GetType() const { return m_type; }
82
83 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
84 switch (m_type) {
86 break;
87 case Opcode::eType8:
88 return m_data.inst8;
89 case Opcode::eType16:
90 break;
92 break;
94 break;
95 case Opcode::eType32:
96 break;
97 case Opcode::eType64:
98 break;
100 break;
101 }
102 return invalid_opcode;
103 }
104
105 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
106 switch (m_type) {
108 break;
109 case Opcode::eType8:
110 return m_data.inst8;
111 case Opcode::eType16:
112 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
113 : m_data.inst16;
115 break;
117 break;
118 case Opcode::eType32:
119 break;
120 case Opcode::eType64:
121 break;
123 break;
124 }
125 return invalid_opcode;
126 }
127
128 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
129 switch (m_type) {
131 break;
132 case Opcode::eType8:
133 return m_data.inst8;
134 case Opcode::eType16:
135 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
136 : m_data.inst16;
138 break;
139 case Opcode::eType16_2: // passthrough
140 case Opcode::eType32:
141 return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
142 : m_data.inst32;
143 case Opcode::eType64:
144 break;
146 break;
147 }
148 return invalid_opcode;
149 }
150
151 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
152 switch (m_type) {
154 break;
155 case Opcode::eType8:
156 return m_data.inst8;
157 case Opcode::eType16:
158 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
159 : m_data.inst16;
161 break;
162 case Opcode::eType16_2: // passthrough
163 case Opcode::eType32:
164 return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
165 : m_data.inst32;
166 case Opcode::eType64:
167 return GetEndianSwap() ? llvm::byteswap<uint64_t>(m_data.inst64)
168 : m_data.inst64;
170 break;
171 }
172 return invalid_opcode;
173 }
174
175 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
176 m_type = eType8;
177 m_data.inst8 = inst;
178 m_byte_order = order;
179 }
180
181 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
182 m_type = eType16;
183 m_data.inst16 = inst;
184 m_byte_order = order;
185 }
186
187 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
189 m_data.inst32 = inst;
190 m_byte_order = order;
191 }
192
193 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
194 m_type = eType32;
195 m_data.inst32 = inst;
196 m_byte_order = order;
197 }
198
199 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
200 m_type = eType64;
201 m_data.inst64 = inst;
202 m_byte_order = order;
203 }
204
205 void SetOpcode16_32TupleBytes(const void *bytes, size_t length,
206 lldb::ByteOrder order) {
208 }
209
213
214 void DoSetOpcodeBytes(const void *bytes, size_t length, Opcode::Type type,
215 lldb::ByteOrder order) {
216 if (bytes != nullptr && length > 0) {
217 m_type = type;
218 m_data.inst.length = length;
219 assert(length <= sizeof(m_data.inst.bytes));
220 memcpy(m_data.inst.bytes, bytes, length);
221 m_byte_order = order;
222 } else {
224 m_data.inst.length = 0;
225 }
226 }
227
228 int Dump(Stream *s, uint32_t min_byte_width) const;
229
230 const void *GetOpcodeBytes() const {
232 ? m_data.inst.bytes
233 : nullptr);
234 }
235
236 uint32_t GetByteSize() const {
237 switch (m_type) {
239 break;
240 case Opcode::eType8:
241 return sizeof(m_data.inst8);
242 case Opcode::eType16:
243 return sizeof(m_data.inst16);
245 return m_data.inst.length;
246 case Opcode::eType16_2: // passthrough
247 case Opcode::eType32:
248 return sizeof(m_data.inst32);
249 case Opcode::eType64:
250 return sizeof(m_data.inst64);
252 return m_data.inst.length;
253 }
254 return 0;
255 }
256
257 // Get the opcode exactly as it would be laid out in memory.
258 uint32_t GetData(DataExtractor &data) const;
259
260protected:
262
263 const void *GetOpcodeDataBytes() const {
264 switch (m_type) {
266 break;
267 case Opcode::eType8:
268 return &m_data.inst8;
269 case Opcode::eType16:
270 return &m_data.inst16;
272 return m_data.inst.bytes;
273 case Opcode::eType16_2: // passthrough
274 case Opcode::eType32:
275 return &m_data.inst32;
276 case Opcode::eType64:
277 return &m_data.inst64;
279 return m_data.inst.bytes;
280 }
281 return nullptr;
282 }
283
285
292
294
296 union {
297 uint8_t inst8;
298 uint16_t inst16;
299 uint32_t inst32;
300 uint64_t inst64;
301 struct {
302 uint8_t bytes[kMaxByteSize]; // This must be big enough to handle any
303 // opcode for any supported target.
304 uint8_t length;
305 } inst;
307};
308
309} // namespace lldb_private
310
311#endif // LLDB_CORE_OPCODE_H
An data extractor class.
void SetOpcode16(uint16_t inst, lldb::ByteOrder order)
Definition Opcode.h:181
void SetOpcodeBytes(const void *bytes, size_t length)
Definition Opcode.h:210
Opcode(uint16_t inst, lldb::ByteOrder order)
Definition Opcode.h:56
void DoSetOpcodeBytes(const void *bytes, size_t length, Opcode::Type type, lldb::ByteOrder order)
Definition Opcode.h:214
uint8_t GetOpcode8(uint8_t invalid_opcode=UINT8_MAX) const
Definition Opcode.h:83
void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order)
Definition Opcode.h:187
static constexpr size_t kMaxByteSize
The size in bytes of the fixed buffer used to store opcode bytes.
Definition Opcode.h:49
Opcode(uint8_t inst, lldb::ByteOrder order)
Definition Opcode.h:51
uint32_t GetByteSize() const
Definition Opcode.h:236
bool GetEndianSwap() const
Definition Opcode.h:286
void SetOpcode64(uint64_t inst, lldb::ByteOrder order)
Definition Opcode.h:199
lldb::ByteOrder m_byte_order
Definition Opcode.h:293
struct lldb_private::Opcode::@117017165353344322347136027142074320135273153214::@067256214025177322235123266021137222221234113202 inst
Opcode::Type m_type
Definition Opcode.h:295
const void * GetOpcodeDataBytes() const
Definition Opcode.h:263
uint8_t bytes[kMaxByteSize]
Definition Opcode.h:302
Opcode::Type GetType() const
Definition Opcode.h:81
union lldb_private::Opcode::@117017165353344322347136027142074320135273153214 m_data
int Dump(Stream *s, uint32_t min_byte_width) const
Definition Opcode.cpp:24
const void * GetOpcodeBytes() const
Definition Opcode.h:230
Opcode(uint32_t inst, lldb::ByteOrder order)
Definition Opcode.h:61
Opcode(uint64_t inst, lldb::ByteOrder order)
Definition Opcode.h:66
lldb::ByteOrder GetDataByteOrder() const
Definition Opcode.cpp:83
void SetOpcode8(uint8_t inst, lldb::ByteOrder order)
Definition Opcode.h:175
void SetOpcode16_32TupleBytes(const void *bytes, size_t length, lldb::ByteOrder order)
Definition Opcode.h:205
uint32_t GetData(DataExtractor &data) const
Definition Opcode.cpp:103
uint32_t GetOpcode32(uint32_t invalid_opcode=UINT32_MAX) const
Definition Opcode.h:128
uint16_t GetOpcode16(uint16_t invalid_opcode=UINT16_MAX) const
Definition Opcode.h:105
void SetOpcode32(uint32_t inst, lldb::ByteOrder order)
Definition Opcode.h:193
uint64_t GetOpcode64(uint64_t invalid_opcode=UINT64_MAX) const
Definition Opcode.h:151
Opcode(uint8_t *bytes, size_t length, Opcode::Type type, lldb::ByteOrder order)
Definition Opcode.h:71
A stream class that can stream formatted output to a file.
Definition Stream.h:28
#define UINT64_MAX
#define UINT32_MAX
lldb::ByteOrder InlHostByteOrder()
Definition Endian.h:25
A class that represents a running process on the host machine.
ByteOrder
Byte ordering definitions.