1 //===-- Opcode.h ------------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef lldb_Opcode_h 11 #define lldb_Opcode_h 12 13 #include "lldb/Utility/Endian.h" 14 #include "lldb/lldb-enumerations.h" 15 16 #include "llvm/Support/MathExtras.h" 17 18 #include <assert.h> 19 #include <stdint.h> 20 #include <string.h> 21 22 namespace lldb_private { 23 class DataExtractor; 24 } 25 namespace lldb_private { 26 class Stream; 27 } 28 29 namespace lldb { 30 class SBInstruction; 31 } 32 33 namespace lldb_private { 34 35 class Opcode { 36 public: 37 enum Type { 38 eTypeInvalid, 39 eType8, 40 eType16, 41 eType16_2, // a 32-bit Thumb instruction, made up of two words 42 eType32, 43 eType64, 44 eTypeBytes 45 }; 46 Opcode()47 Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {} 48 Opcode(uint8_t inst,lldb::ByteOrder order)49 Opcode(uint8_t inst, lldb::ByteOrder order) 50 : m_byte_order(order), m_type(eType8) { 51 m_data.inst8 = inst; 52 } 53 Opcode(uint16_t inst,lldb::ByteOrder order)54 Opcode(uint16_t inst, lldb::ByteOrder order) 55 : m_byte_order(order), m_type(eType16) { 56 m_data.inst16 = inst; 57 } 58 Opcode(uint32_t inst,lldb::ByteOrder order)59 Opcode(uint32_t inst, lldb::ByteOrder order) 60 : m_byte_order(order), m_type(eType32) { 61 m_data.inst32 = inst; 62 } 63 Opcode(uint64_t inst,lldb::ByteOrder order)64 Opcode(uint64_t inst, lldb::ByteOrder order) 65 : m_byte_order(order), m_type(eType64) { 66 m_data.inst64 = inst; 67 } 68 Opcode(uint8_t * bytes,size_t length)69 Opcode(uint8_t *bytes, size_t length) 70 : m_byte_order(lldb::eByteOrderInvalid) { 71 SetOpcodeBytes(bytes, length); 72 } 73 Clear()74 void Clear() { 75 m_byte_order = lldb::eByteOrderInvalid; 76 m_type = Opcode::eTypeInvalid; 77 } 78 GetType()79 Opcode::Type GetType() const { return m_type; } 80 81 uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const { 82 switch (m_type) { 83 case Opcode::eTypeInvalid: 84 break; 85 case Opcode::eType8: 86 return m_data.inst8; 87 case Opcode::eType16: 88 break; 89 case Opcode::eType16_2: 90 break; 91 case Opcode::eType32: 92 break; 93 case Opcode::eType64: 94 break; 95 case Opcode::eTypeBytes: 96 break; 97 } 98 return invalid_opcode; 99 } 100 101 uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const { 102 switch (m_type) { 103 case Opcode::eTypeInvalid: 104 break; 105 case Opcode::eType8: 106 return m_data.inst8; 107 case Opcode::eType16: 108 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 109 case Opcode::eType16_2: 110 break; 111 case Opcode::eType32: 112 break; 113 case Opcode::eType64: 114 break; 115 case Opcode::eTypeBytes: 116 break; 117 } 118 return invalid_opcode; 119 } 120 121 uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const { 122 switch (m_type) { 123 case Opcode::eTypeInvalid: 124 break; 125 case Opcode::eType8: 126 return m_data.inst8; 127 case Opcode::eType16: 128 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 129 case Opcode::eType16_2: // passthrough 130 case Opcode::eType32: 131 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; 132 case Opcode::eType64: 133 break; 134 case Opcode::eTypeBytes: 135 break; 136 } 137 return invalid_opcode; 138 } 139 140 uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const { 141 switch (m_type) { 142 case Opcode::eTypeInvalid: 143 break; 144 case Opcode::eType8: 145 return m_data.inst8; 146 case Opcode::eType16: 147 return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; 148 case Opcode::eType16_2: // passthrough 149 case Opcode::eType32: 150 return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; 151 case Opcode::eType64: 152 return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64; 153 case Opcode::eTypeBytes: 154 break; 155 } 156 return invalid_opcode; 157 } 158 SetOpcode8(uint8_t inst,lldb::ByteOrder order)159 void SetOpcode8(uint8_t inst, lldb::ByteOrder order) { 160 m_type = eType8; 161 m_data.inst8 = inst; 162 m_byte_order = order; 163 } 164 SetOpcode16(uint16_t inst,lldb::ByteOrder order)165 void SetOpcode16(uint16_t inst, lldb::ByteOrder order) { 166 m_type = eType16; 167 m_data.inst16 = inst; 168 m_byte_order = order; 169 } 170 SetOpcode16_2(uint32_t inst,lldb::ByteOrder order)171 void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) { 172 m_type = eType16_2; 173 m_data.inst32 = inst; 174 m_byte_order = order; 175 } 176 SetOpcode32(uint32_t inst,lldb::ByteOrder order)177 void SetOpcode32(uint32_t inst, lldb::ByteOrder order) { 178 m_type = eType32; 179 m_data.inst32 = inst; 180 m_byte_order = order; 181 } 182 SetOpcode64(uint64_t inst,lldb::ByteOrder order)183 void SetOpcode64(uint64_t inst, lldb::ByteOrder order) { 184 m_type = eType64; 185 m_data.inst64 = inst; 186 m_byte_order = order; 187 } 188 SetOpcodeBytes(const void * bytes,size_t length)189 void SetOpcodeBytes(const void *bytes, size_t length) { 190 if (bytes != nullptr && length > 0) { 191 m_type = eTypeBytes; 192 m_data.inst.length = length; 193 assert(length < sizeof(m_data.inst.bytes)); 194 memcpy(m_data.inst.bytes, bytes, length); 195 m_byte_order = lldb::eByteOrderInvalid; 196 } else { 197 m_type = eTypeInvalid; 198 m_data.inst.length = 0; 199 } 200 } 201 202 int Dump(Stream *s, uint32_t min_byte_width); 203 GetOpcodeBytes()204 const void *GetOpcodeBytes() const { 205 return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr); 206 } 207 GetByteSize()208 uint32_t GetByteSize() const { 209 switch (m_type) { 210 case Opcode::eTypeInvalid: 211 break; 212 case Opcode::eType8: 213 return sizeof(m_data.inst8); 214 case Opcode::eType16: 215 return sizeof(m_data.inst16); 216 case Opcode::eType16_2: // passthrough 217 case Opcode::eType32: 218 return sizeof(m_data.inst32); 219 case Opcode::eType64: 220 return sizeof(m_data.inst64); 221 case Opcode::eTypeBytes: 222 return m_data.inst.length; 223 } 224 return 0; 225 } 226 227 // Get the opcode exactly as it would be laid out in memory. 228 uint32_t GetData(DataExtractor &data) const; 229 230 protected: 231 friend class lldb::SBInstruction; 232 GetOpcodeDataBytes()233 const void *GetOpcodeDataBytes() const { 234 switch (m_type) { 235 case Opcode::eTypeInvalid: 236 break; 237 case Opcode::eType8: 238 return &m_data.inst8; 239 case Opcode::eType16: 240 return &m_data.inst16; 241 case Opcode::eType16_2: // passthrough 242 case Opcode::eType32: 243 return &m_data.inst32; 244 case Opcode::eType64: 245 return &m_data.inst64; 246 case Opcode::eTypeBytes: 247 return m_data.inst.bytes; 248 } 249 return nullptr; 250 } 251 252 lldb::ByteOrder GetDataByteOrder() const; 253 GetEndianSwap()254 bool GetEndianSwap() const { 255 return (m_byte_order == lldb::eByteOrderBig && 256 endian::InlHostByteOrder() == lldb::eByteOrderLittle) || 257 (m_byte_order == lldb::eByteOrderLittle && 258 endian::InlHostByteOrder() == lldb::eByteOrderBig); 259 } 260 261 lldb::ByteOrder m_byte_order; 262 263 Opcode::Type m_type; 264 union { 265 uint8_t inst8; 266 uint16_t inst16; 267 uint32_t inst32; 268 uint64_t inst64; 269 struct { 270 uint8_t bytes[16]; // This must be big enough to handle any opcode for any 271 // supported target. 272 uint8_t length; 273 } inst; 274 } m_data; 275 }; 276 277 } // namespace lldb_private 278 279 #endif // lldb_Opcode_h 280