diff options
Diffstat (limited to 'include/lldb/Core/Opcode.h')
-rw-r--r-- | include/lldb/Core/Opcode.h | 499 |
1 files changed, 243 insertions, 256 deletions
diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h index eac0746baba1..d5376d44b814 100644 --- a/include/lldb/Core/Opcode.h +++ b/include/lldb/Core/Opcode.h @@ -21,266 +21,253 @@ #include "lldb/Host/Endian.h" #include "lldb/lldb-public.h" -namespace lldb -{ - class SBInstruction; +namespace lldb { +class SBInstruction; } // namespace lldb namespace lldb_private { - class Opcode - { - public: - enum Type - { - eTypeInvalid, - eType8, - eType16, - eType16_2, // a 32-bit Thumb instruction, made up of two words - eType32, - eType64, - eTypeBytes - }; - - Opcode () : m_byte_order (lldb::eByteOrderInvalid), m_type (eTypeInvalid) - { - } - - Opcode (uint8_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType8) - { - m_data.inst8 = inst; - } - - Opcode (uint16_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType16) - { - m_data.inst16 = inst; - } - - Opcode (uint32_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType32) - { - m_data.inst32 = inst; - } - - Opcode (uint64_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType64) - { - m_data.inst64 = inst; - } - - Opcode (uint8_t *bytes, size_t length) : m_byte_order (lldb::eByteOrderInvalid) - { - SetOpcodeBytes (bytes, length); - } - - void - Clear() - { - m_byte_order = lldb::eByteOrderInvalid; - m_type = Opcode::eTypeInvalid; - } - - Opcode::Type - GetType () const - { - return m_type; - } - - uint8_t - GetOpcode8 (uint8_t invalid_opcode = UINT8_MAX) const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return m_data.inst8; - case Opcode::eType16: break; - case Opcode::eType16_2: break; - case Opcode::eType32: break; - case Opcode::eType64: break; - case Opcode::eTypeBytes: break; - } - return invalid_opcode; - } - - uint16_t - GetOpcode16 (uint16_t invalid_opcode = UINT16_MAX) const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return m_data.inst8; - case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; - case Opcode::eType16_2: break; - case Opcode::eType32: break; - case Opcode::eType64: break; - case Opcode::eTypeBytes: break; - } - return invalid_opcode; - } - - uint32_t - GetOpcode32 (uint32_t invalid_opcode = UINT32_MAX) const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return m_data.inst8; - case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; - case Opcode::eType16_2: // passthrough - case Opcode::eType32: return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; - case Opcode::eType64: break; - case Opcode::eTypeBytes: break; - } - return invalid_opcode; - } - - uint64_t - GetOpcode64 (uint64_t invalid_opcode = UINT64_MAX) const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return m_data.inst8; - case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; - case Opcode::eType16_2: // passthrough - case Opcode::eType32: return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; - case Opcode::eType64: return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64; - case Opcode::eTypeBytes: break; - } - return invalid_opcode; - } - - void - SetOpcode8 (uint8_t inst, lldb::ByteOrder order) - { - m_type = eType8; - m_data.inst8 = inst; - m_byte_order = order; - } - - void - SetOpcode16 (uint16_t inst, lldb::ByteOrder order) - { - m_type = eType16; - m_data.inst16 = inst; - m_byte_order = order; - } - - void - SetOpcode16_2 (uint32_t inst, lldb::ByteOrder order) - { - m_type = eType16_2; - m_data.inst32 = inst; - m_byte_order = order; - } - - void - SetOpcode32 (uint32_t inst, lldb::ByteOrder order) - { - m_type = eType32; - m_data.inst32 = inst; - m_byte_order = order; - } - - void - SetOpcode64 (uint64_t inst, lldb::ByteOrder order) - { - m_type = eType64; - m_data.inst64 = inst; - m_byte_order = order; - } - - void - SetOpcodeBytes (const void *bytes, size_t length) - { - if (bytes != nullptr && length > 0) - { - m_type = eTypeBytes; - m_data.inst.length = length; - assert (length < sizeof (m_data.inst.bytes)); - memcpy (m_data.inst.bytes, bytes, length); - m_byte_order = lldb::eByteOrderInvalid; - } - else - { - m_type = eTypeInvalid; - m_data.inst.length = 0; - } - } - - int - Dump (Stream *s, uint32_t min_byte_width); - - const void * - GetOpcodeBytes () const - { - return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr); - } - - uint32_t - GetByteSize () const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return sizeof(m_data.inst8); - case Opcode::eType16: return sizeof(m_data.inst16); - case Opcode::eType16_2: // passthrough - case Opcode::eType32: return sizeof(m_data.inst32); - case Opcode::eType64: return sizeof(m_data.inst64); - case Opcode::eTypeBytes: return m_data.inst.length; - } - return 0; - } - - // Get the opcode exactly as it would be laid out in memory. - uint32_t - GetData (DataExtractor &data) const; - - protected: - - friend class lldb::SBInstruction; - - const void * - GetOpcodeDataBytes () const - { - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: return &m_data.inst8; - case Opcode::eType16: return &m_data.inst16; - case Opcode::eType16_2: // passthrough - case Opcode::eType32: return &m_data.inst32; - case Opcode::eType64: return &m_data.inst64; - case Opcode::eTypeBytes: return m_data.inst.bytes; - } - return nullptr; - } - - lldb::ByteOrder - GetDataByteOrder () const; - - bool - GetEndianSwap() const - { - return (m_byte_order == lldb::eByteOrderBig && endian::InlHostByteOrder() == lldb::eByteOrderLittle) || - (m_byte_order == lldb::eByteOrderLittle && endian::InlHostByteOrder() == lldb::eByteOrderBig); - } - - lldb::ByteOrder m_byte_order; - - Opcode::Type m_type; - union - { - uint8_t inst8; - uint16_t inst16; - uint32_t inst32; - uint64_t inst64; - struct - { - uint8_t bytes[16]; // This must be big enough to handle any opcode for any supported target. - uint8_t length; - } inst; - } m_data; - }; +class Opcode { +public: + enum Type { + eTypeInvalid, + eType8, + eType16, + eType16_2, // a 32-bit Thumb instruction, made up of two words + eType32, + eType64, + eTypeBytes + }; + + Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {} + + Opcode(uint8_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType8) { + m_data.inst8 = inst; + } + + Opcode(uint16_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType16) { + m_data.inst16 = inst; + } + + Opcode(uint32_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType32) { + m_data.inst32 = inst; + } + + Opcode(uint64_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType64) { + m_data.inst64 = inst; + } + + Opcode(uint8_t *bytes, size_t length) + : m_byte_order(lldb::eByteOrderInvalid) { + SetOpcodeBytes(bytes, length); + } + + void Clear() { + m_byte_order = lldb::eByteOrderInvalid; + m_type = Opcode::eTypeInvalid; + } + + Opcode::Type GetType() const { return m_type; } + + uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + break; + case Opcode::eType16_2: + break; + case Opcode::eType32: + break; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: + break; + case Opcode::eType32: + break; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; + case Opcode::eType64: + return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + void SetOpcode8(uint8_t inst, lldb::ByteOrder order) { + m_type = eType8; + m_data.inst8 = inst; + m_byte_order = order; + } + + void SetOpcode16(uint16_t inst, lldb::ByteOrder order) { + m_type = eType16; + m_data.inst16 = inst; + m_byte_order = order; + } + + void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) { + m_type = eType16_2; + m_data.inst32 = inst; + m_byte_order = order; + } + + void SetOpcode32(uint32_t inst, lldb::ByteOrder order) { + m_type = eType32; + m_data.inst32 = inst; + m_byte_order = order; + } + + void SetOpcode64(uint64_t inst, lldb::ByteOrder order) { + m_type = eType64; + m_data.inst64 = inst; + m_byte_order = order; + } + + void SetOpcodeBytes(const void *bytes, size_t length) { + if (bytes != nullptr && length > 0) { + m_type = eTypeBytes; + m_data.inst.length = length; + assert(length < sizeof(m_data.inst.bytes)); + memcpy(m_data.inst.bytes, bytes, length); + m_byte_order = lldb::eByteOrderInvalid; + } else { + m_type = eTypeInvalid; + m_data.inst.length = 0; + } + } + + int Dump(Stream *s, uint32_t min_byte_width); + + const void *GetOpcodeBytes() const { + return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr); + } + + uint32_t GetByteSize() const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return sizeof(m_data.inst8); + case Opcode::eType16: + return sizeof(m_data.inst16); + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return sizeof(m_data.inst32); + case Opcode::eType64: + return sizeof(m_data.inst64); + case Opcode::eTypeBytes: + return m_data.inst.length; + } + return 0; + } + + // Get the opcode exactly as it would be laid out in memory. + uint32_t GetData(DataExtractor &data) const; + +protected: + friend class lldb::SBInstruction; + + const void *GetOpcodeDataBytes() const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return &m_data.inst8; + case Opcode::eType16: + return &m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return &m_data.inst32; + case Opcode::eType64: + return &m_data.inst64; + case Opcode::eTypeBytes: + return m_data.inst.bytes; + } + return nullptr; + } + + lldb::ByteOrder GetDataByteOrder() const; + + bool GetEndianSwap() const { + return (m_byte_order == lldb::eByteOrderBig && + endian::InlHostByteOrder() == lldb::eByteOrderLittle) || + (m_byte_order == lldb::eByteOrderLittle && + endian::InlHostByteOrder() == lldb::eByteOrderBig); + } + + lldb::ByteOrder m_byte_order; + + Opcode::Type m_type; + union { + uint8_t inst8; + uint16_t inst16; + uint32_t inst32; + uint64_t inst64; + struct { + uint8_t bytes[16]; // This must be big enough to handle any opcode for any + // supported target. + uint8_t length; + } inst; + } m_data; +}; } // namespace lldb_private |