File indexing completed on 2026-05-10 08:42:45
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLDB_CORE_OPCODE_H
0010 #define LLDB_CORE_OPCODE_H
0011
0012 #include "lldb/Utility/Endian.h"
0013 #include "lldb/lldb-enumerations.h"
0014
0015 #include "llvm/Support/SwapByteOrder.h"
0016
0017 #include <cassert>
0018 #include <cstdint>
0019 #include <cstring>
0020
0021 namespace lldb {
0022 class SBInstruction;
0023 }
0024
0025 namespace lldb_private {
0026 class DataExtractor;
0027 class Stream;
0028
0029 class Opcode {
0030 public:
0031 enum Type {
0032 eTypeInvalid,
0033 eType8,
0034 eType16,
0035 eType16_2,
0036 eType32,
0037 eType64,
0038 eTypeBytes
0039 };
0040
0041 Opcode() = default;
0042
0043 Opcode(uint8_t inst, lldb::ByteOrder order)
0044 : m_byte_order(order), m_type(eType8) {
0045 m_data.inst8 = inst;
0046 }
0047
0048 Opcode(uint16_t inst, lldb::ByteOrder order)
0049 : m_byte_order(order), m_type(eType16) {
0050 m_data.inst16 = inst;
0051 }
0052
0053 Opcode(uint32_t inst, lldb::ByteOrder order)
0054 : m_byte_order(order), m_type(eType32) {
0055 m_data.inst32 = inst;
0056 }
0057
0058 Opcode(uint64_t inst, lldb::ByteOrder order)
0059 : m_byte_order(order), m_type(eType64) {
0060 m_data.inst64 = inst;
0061 }
0062
0063 Opcode(uint8_t *bytes, size_t length)
0064 : m_byte_order(lldb::eByteOrderInvalid) {
0065 SetOpcodeBytes(bytes, length);
0066 }
0067
0068 void Clear() {
0069 m_byte_order = lldb::eByteOrderInvalid;
0070 m_type = Opcode::eTypeInvalid;
0071 }
0072
0073 Opcode::Type GetType() const { return m_type; }
0074
0075 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const {
0076 switch (m_type) {
0077 case Opcode::eTypeInvalid:
0078 break;
0079 case Opcode::eType8:
0080 return m_data.inst8;
0081 case Opcode::eType16:
0082 break;
0083 case Opcode::eType16_2:
0084 break;
0085 case Opcode::eType32:
0086 break;
0087 case Opcode::eType64:
0088 break;
0089 case Opcode::eTypeBytes:
0090 break;
0091 }
0092 return invalid_opcode;
0093 }
0094
0095 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const {
0096 switch (m_type) {
0097 case Opcode::eTypeInvalid:
0098 break;
0099 case Opcode::eType8:
0100 return m_data.inst8;
0101 case Opcode::eType16:
0102 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0103 : m_data.inst16;
0104 case Opcode::eType16_2:
0105 break;
0106 case Opcode::eType32:
0107 break;
0108 case Opcode::eType64:
0109 break;
0110 case Opcode::eTypeBytes:
0111 break;
0112 }
0113 return invalid_opcode;
0114 }
0115
0116 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const {
0117 switch (m_type) {
0118 case Opcode::eTypeInvalid:
0119 break;
0120 case Opcode::eType8:
0121 return m_data.inst8;
0122 case Opcode::eType16:
0123 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0124 : m_data.inst16;
0125 case Opcode::eType16_2:
0126 case Opcode::eType32:
0127 return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
0128 : m_data.inst32;
0129 case Opcode::eType64:
0130 break;
0131 case Opcode::eTypeBytes:
0132 break;
0133 }
0134 return invalid_opcode;
0135 }
0136
0137 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const {
0138 switch (m_type) {
0139 case Opcode::eTypeInvalid:
0140 break;
0141 case Opcode::eType8:
0142 return m_data.inst8;
0143 case Opcode::eType16:
0144 return GetEndianSwap() ? llvm::byteswap<uint16_t>(m_data.inst16)
0145 : m_data.inst16;
0146 case Opcode::eType16_2:
0147 case Opcode::eType32:
0148 return GetEndianSwap() ? llvm::byteswap<uint32_t>(m_data.inst32)
0149 : m_data.inst32;
0150 case Opcode::eType64:
0151 return GetEndianSwap() ? llvm::byteswap<uint64_t>(m_data.inst64)
0152 : m_data.inst64;
0153 case Opcode::eTypeBytes:
0154 break;
0155 }
0156 return invalid_opcode;
0157 }
0158
0159 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) {
0160 m_type = eType8;
0161 m_data.inst8 = inst;
0162 m_byte_order = order;
0163 }
0164
0165 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) {
0166 m_type = eType16;
0167 m_data.inst16 = inst;
0168 m_byte_order = order;
0169 }
0170
0171 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) {
0172 m_type = eType16_2;
0173 m_data.inst32 = inst;
0174 m_byte_order = order;
0175 }
0176
0177 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) {
0178 m_type = eType32;
0179 m_data.inst32 = inst;
0180 m_byte_order = order;
0181 }
0182
0183 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) {
0184 m_type = eType64;
0185 m_data.inst64 = inst;
0186 m_byte_order = order;
0187 }
0188
0189 void SetOpcodeBytes(const void *bytes, size_t length) {
0190 if (bytes != nullptr && length > 0) {
0191 m_type = eTypeBytes;
0192 m_data.inst.length = length;
0193 assert(length < sizeof(m_data.inst.bytes));
0194 memcpy(m_data.inst.bytes, bytes, length);
0195 m_byte_order = lldb::eByteOrderInvalid;
0196 } else {
0197 m_type = eTypeInvalid;
0198 m_data.inst.length = 0;
0199 }
0200 }
0201
0202 int Dump(Stream *s, uint32_t min_byte_width);
0203
0204 const void *GetOpcodeBytes() const {
0205 return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr);
0206 }
0207
0208 uint32_t GetByteSize() const {
0209 switch (m_type) {
0210 case Opcode::eTypeInvalid:
0211 break;
0212 case Opcode::eType8:
0213 return sizeof(m_data.inst8);
0214 case Opcode::eType16:
0215 return sizeof(m_data.inst16);
0216 case Opcode::eType16_2:
0217 case Opcode::eType32:
0218 return sizeof(m_data.inst32);
0219 case Opcode::eType64:
0220 return sizeof(m_data.inst64);
0221 case Opcode::eTypeBytes:
0222 return m_data.inst.length;
0223 }
0224 return 0;
0225 }
0226
0227
0228 uint32_t GetData(DataExtractor &data) const;
0229
0230 protected:
0231 friend class lldb::SBInstruction;
0232
0233 const void *GetOpcodeDataBytes() const {
0234 switch (m_type) {
0235 case Opcode::eTypeInvalid:
0236 break;
0237 case Opcode::eType8:
0238 return &m_data.inst8;
0239 case Opcode::eType16:
0240 return &m_data.inst16;
0241 case Opcode::eType16_2:
0242 case Opcode::eType32:
0243 return &m_data.inst32;
0244 case Opcode::eType64:
0245 return &m_data.inst64;
0246 case Opcode::eTypeBytes:
0247 return m_data.inst.bytes;
0248 }
0249 return nullptr;
0250 }
0251
0252 lldb::ByteOrder GetDataByteOrder() const;
0253
0254 bool GetEndianSwap() const {
0255 return (m_byte_order == lldb::eByteOrderBig &&
0256 endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
0257 (m_byte_order == lldb::eByteOrderLittle &&
0258 endian::InlHostByteOrder() == lldb::eByteOrderBig);
0259 }
0260
0261 lldb::ByteOrder m_byte_order = lldb::eByteOrderInvalid;
0262
0263 Opcode::Type m_type = eTypeInvalid;
0264 union {
0265 uint8_t inst8;
0266 uint16_t inst16;
0267 uint32_t inst32;
0268 uint64_t inst64;
0269 struct {
0270 uint8_t bytes[16];
0271
0272 uint8_t length;
0273 } inst;
0274 } m_data;
0275 };
0276
0277 }
0278
0279 #endif