forked from OSchip/llvm-project
Handle endianness in the Opcode class
Previously, an opcode set via SetOpcode32 (for example) was later extracted via GetData() as a byte sequence in host order rather than target order. Review: http://llvm-reviews.chandlerc.com/D1838 llvm-svn: 196808
This commit is contained in:
parent
e2a1418e68
commit
90359963ab
|
@ -15,7 +15,9 @@
|
|||
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
// Project includes
|
||||
#include "lldb/Host/Endian.h"
|
||||
#include "lldb/lldb-public.h"
|
||||
|
||||
namespace lldb
|
||||
|
@ -39,31 +41,31 @@ namespace lldb_private {
|
|||
eTypeBytes
|
||||
};
|
||||
|
||||
Opcode () : m_type (eTypeInvalid)
|
||||
Opcode () : m_byte_order (lldb::eByteOrderInvalid), m_type (eTypeInvalid)
|
||||
{
|
||||
}
|
||||
|
||||
Opcode (uint8_t inst) : m_type (eType8)
|
||||
Opcode (uint8_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType8)
|
||||
{
|
||||
m_data.inst8 = inst;
|
||||
}
|
||||
|
||||
Opcode (uint16_t inst) : m_type (eType16)
|
||||
Opcode (uint16_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType16)
|
||||
{
|
||||
m_data.inst16 = inst;
|
||||
}
|
||||
|
||||
Opcode (uint32_t inst) : m_type (eType32)
|
||||
Opcode (uint32_t inst, lldb::ByteOrder order) : m_byte_order (order), m_type (eType32)
|
||||
{
|
||||
m_data.inst32 = inst;
|
||||
}
|
||||
|
||||
Opcode (uint64_t inst) : m_type (eType64)
|
||||
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)
|
||||
Opcode (uint8_t *bytes, size_t length) : m_byte_order (lldb::eByteOrderInvalid)
|
||||
{
|
||||
SetOpcodeBytes (bytes, length);
|
||||
}
|
||||
|
@ -71,6 +73,7 @@ namespace lldb_private {
|
|||
void
|
||||
Clear()
|
||||
{
|
||||
m_byte_order = lldb::eByteOrderInvalid;
|
||||
m_type = Opcode::eTypeInvalid;
|
||||
}
|
||||
Opcode::Type
|
||||
|
@ -102,7 +105,7 @@ namespace lldb_private {
|
|||
{
|
||||
case Opcode::eTypeInvalid: break;
|
||||
case Opcode::eType8: return m_data.inst8;
|
||||
case Opcode::eType16: return m_data.inst16;
|
||||
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;
|
||||
|
@ -118,9 +121,9 @@ namespace lldb_private {
|
|||
{
|
||||
case Opcode::eTypeInvalid: break;
|
||||
case Opcode::eType8: return m_data.inst8;
|
||||
case Opcode::eType16: return m_data.inst16;
|
||||
case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
|
||||
case Opcode::eType16_2: // passthrough
|
||||
case Opcode::eType32: return m_data.inst32;
|
||||
case Opcode::eType32: return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32;
|
||||
case Opcode::eType64: break;
|
||||
case Opcode::eTypeBytes: break;
|
||||
}
|
||||
|
@ -134,48 +137,53 @@ namespace lldb_private {
|
|||
{
|
||||
case Opcode::eTypeInvalid: break;
|
||||
case Opcode::eType8: return m_data.inst8;
|
||||
case Opcode::eType16: return m_data.inst16;
|
||||
case Opcode::eType16: return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16;
|
||||
case Opcode::eType16_2: // passthrough
|
||||
case Opcode::eType32: return m_data.inst32;
|
||||
case Opcode::eType64: return m_data.inst64;
|
||||
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)
|
||||
SetOpcode8 (uint8_t inst, lldb::ByteOrder order)
|
||||
{
|
||||
m_type = eType8;
|
||||
m_data.inst8 = inst;
|
||||
m_byte_order = order;
|
||||
}
|
||||
|
||||
void
|
||||
SetOpcode16 (uint16_t inst)
|
||||
SetOpcode16 (uint16_t inst, lldb::ByteOrder order)
|
||||
{
|
||||
m_type = eType16;
|
||||
m_data.inst16 = inst;
|
||||
m_byte_order = order;
|
||||
}
|
||||
|
||||
void
|
||||
SetOpcode16_2 (uint32_t inst)
|
||||
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)
|
||||
SetOpcode32 (uint32_t inst, lldb::ByteOrder order)
|
||||
{
|
||||
m_type = eType32;
|
||||
m_data.inst32 = inst;
|
||||
m_byte_order = order;
|
||||
}
|
||||
|
||||
void
|
||||
SetOpcode64 (uint64_t inst)
|
||||
SetOpcode64 (uint64_t inst, lldb::ByteOrder order)
|
||||
{
|
||||
m_type = eType64;
|
||||
m_data.inst64 = inst;
|
||||
m_byte_order = order;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -187,6 +195,7 @@ namespace lldb_private {
|
|||
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
|
||||
{
|
||||
|
@ -249,6 +258,15 @@ namespace lldb_private {
|
|||
lldb::ByteOrder
|
||||
GetDataByteOrder () const;
|
||||
|
||||
bool
|
||||
GetEndianSwap() const
|
||||
{
|
||||
return (m_byte_order == lldb::eByteOrderBig && lldb::endian::InlHostByteOrder() == lldb::eByteOrderLittle) ||
|
||||
(m_byte_order == lldb::eByteOrderLittle && lldb::endian::InlHostByteOrder() == lldb::eByteOrderBig);
|
||||
}
|
||||
|
||||
lldb::ByteOrder m_byte_order;
|
||||
|
||||
Opcode::Type m_type;
|
||||
union
|
||||
{
|
||||
|
|
|
@ -1236,25 +1236,25 @@ PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
|
|||
case 8:
|
||||
{
|
||||
uint8_t value8 = *((uint8_t *) opcode_data);
|
||||
m_opcode.SetOpcode8 (value8);
|
||||
m_opcode.SetOpcode8 (value8, eByteOrderInvalid);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
uint16_t value16 = *((uint16_t *) opcode_data);
|
||||
m_opcode.SetOpcode16 (value16);
|
||||
m_opcode.SetOpcode16 (value16, eByteOrderInvalid);
|
||||
break;
|
||||
}
|
||||
case 32:
|
||||
{
|
||||
uint32_t value32 = *((uint32_t *) opcode_data);
|
||||
m_opcode.SetOpcode32 (value32);
|
||||
m_opcode.SetOpcode32 (value32, eByteOrderInvalid);
|
||||
break;
|
||||
}
|
||||
case 64:
|
||||
{
|
||||
uint64_t value64 = *((uint64_t *) opcode_data);
|
||||
m_opcode.SetOpcode64 (value64);
|
||||
m_opcode.SetOpcode64 (value64, eByteOrderInvalid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -71,6 +71,10 @@ Opcode::Dump (Stream *s, uint32_t min_byte_width)
|
|||
lldb::ByteOrder
|
||||
Opcode::GetDataByteOrder () const
|
||||
{
|
||||
if (m_byte_order != eByteOrderInvalid)
|
||||
{
|
||||
return m_byte_order;
|
||||
}
|
||||
switch (m_type)
|
||||
{
|
||||
case Opcode::eTypeInvalid: break;
|
||||
|
@ -89,39 +93,66 @@ uint32_t
|
|||
Opcode::GetData (DataExtractor &data) const
|
||||
{
|
||||
uint32_t byte_size = GetByteSize ();
|
||||
uint8_t swap_buf[8];
|
||||
const void *buf = NULL;
|
||||
|
||||
DataBufferSP buffer_sp;
|
||||
if (byte_size > 0)
|
||||
{
|
||||
switch (m_type)
|
||||
if (!GetEndianSwap())
|
||||
{
|
||||
case Opcode::eTypeInvalid:
|
||||
break;
|
||||
|
||||
case Opcode::eType8: buffer_sp.reset (new DataBufferHeap (&m_data.inst8, byte_size)); break;
|
||||
case Opcode::eType16: buffer_sp.reset (new DataBufferHeap (&m_data.inst16, byte_size)); break;
|
||||
case Opcode::eType16_2:
|
||||
{
|
||||
// 32 bit thumb instruction, we need to sizzle this a bit
|
||||
uint8_t buf[4];
|
||||
buf[0] = m_data.inst.bytes[2];
|
||||
buf[1] = m_data.inst.bytes[3];
|
||||
buf[2] = m_data.inst.bytes[0];
|
||||
buf[3] = m_data.inst.bytes[1];
|
||||
buffer_sp.reset (new DataBufferHeap (buf, byte_size));
|
||||
}
|
||||
break;
|
||||
case Opcode::eType32:
|
||||
buffer_sp.reset (new DataBufferHeap (&m_data.inst32, byte_size));
|
||||
break;
|
||||
case Opcode::eType64: buffer_sp.reset (new DataBufferHeap (&m_data.inst64, byte_size)); break;
|
||||
case Opcode::eTypeBytes:buffer_sp.reset (new DataBufferHeap (GetOpcodeBytes(), byte_size)); break;
|
||||
break;
|
||||
if (m_type == Opcode::eType16_2)
|
||||
{
|
||||
// 32 bit thumb instruction, we need to sizzle this a bit
|
||||
swap_buf[0] = m_data.inst.bytes[2];
|
||||
swap_buf[1] = m_data.inst.bytes[3];
|
||||
swap_buf[2] = m_data.inst.bytes[0];
|
||||
swap_buf[3] = m_data.inst.bytes[1];
|
||||
buf = swap_buf;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = GetOpcodeDataBytes();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case Opcode::eTypeInvalid:
|
||||
break;
|
||||
case Opcode::eType8:
|
||||
buf = GetOpcodeDataBytes();
|
||||
break;
|
||||
case Opcode::eType16:
|
||||
*(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16);
|
||||
buf = swap_buf;
|
||||
break;
|
||||
case Opcode::eType16_2:
|
||||
swap_buf[0] = m_data.inst.bytes[1];
|
||||
swap_buf[1] = m_data.inst.bytes[0];
|
||||
swap_buf[2] = m_data.inst.bytes[3];
|
||||
swap_buf[3] = m_data.inst.bytes[2];
|
||||
buf = swap_buf;
|
||||
break;
|
||||
case Opcode::eType32:
|
||||
*(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32);
|
||||
buf = swap_buf;
|
||||
break;
|
||||
case Opcode::eType64:
|
||||
*(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64);
|
||||
buf = swap_buf;
|
||||
break;
|
||||
case Opcode::eTypeBytes:
|
||||
buf = GetOpcodeDataBytes();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer_sp)
|
||||
if (buf)
|
||||
{
|
||||
DataBufferSP buffer_sp;
|
||||
|
||||
buffer_sp.reset (new DataBufferHeap (buf, byte_size));
|
||||
data.SetByteOrder(GetDataByteOrder());
|
||||
data.SetData (buffer_sp);
|
||||
return byte_size;
|
||||
|
|
|
@ -128,6 +128,7 @@ public:
|
|||
bool got_op = false;
|
||||
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
|
||||
const ArchSpec &arch = llvm_disasm.GetArchitecture();
|
||||
const lldb::ByteOrder byte_order = data.GetByteOrder();
|
||||
|
||||
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
|
||||
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
|
||||
|
@ -136,26 +137,26 @@ public:
|
|||
// Fixed size instructions, just read that amount of data.
|
||||
if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
|
||||
return false;
|
||||
|
||||
|
||||
switch (min_op_byte_size)
|
||||
{
|
||||
case 1:
|
||||
m_opcode.SetOpcode8 (data.GetU8 (&data_offset));
|
||||
m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order);
|
||||
got_op = true;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
m_opcode.SetOpcode16 (data.GetU16 (&data_offset));
|
||||
m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order);
|
||||
got_op = true;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
m_opcode.SetOpcode32 (data.GetU32 (&data_offset));
|
||||
m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order);
|
||||
got_op = true;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
m_opcode.SetOpcode64 (data.GetU64 (&data_offset));
|
||||
m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order);
|
||||
got_op = true;
|
||||
break;
|
||||
|
||||
|
@ -178,20 +179,20 @@ public:
|
|||
uint32_t thumb_opcode = data.GetU16(&data_offset);
|
||||
if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
|
||||
{
|
||||
m_opcode.SetOpcode16 (thumb_opcode);
|
||||
m_opcode.SetOpcode16 (thumb_opcode, byte_order);
|
||||
m_is_valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
thumb_opcode <<= 16;
|
||||
thumb_opcode |= data.GetU16(&data_offset);
|
||||
m_opcode.SetOpcode16_2 (thumb_opcode);
|
||||
m_opcode.SetOpcode16_2 (thumb_opcode, byte_order);
|
||||
m_is_valid = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_opcode.SetOpcode32 (data.GetU32(&data_offset));
|
||||
m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order);
|
||||
m_is_valid = true;
|
||||
}
|
||||
}
|
||||
|
@ -304,12 +305,13 @@ public:
|
|||
inst_size = m_opcode.GetByteSize();
|
||||
StreamString mnemonic_strm;
|
||||
lldb::offset_t offset = 0;
|
||||
lldb::ByteOrder byte_order = data.GetByteOrder();
|
||||
switch (inst_size)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
const uint8_t uval8 = data.GetU8 (&offset);
|
||||
m_opcode.SetOpcode8 (uval8);
|
||||
m_opcode.SetOpcode8 (uval8, byte_order);
|
||||
m_opcode_name.assign (".byte");
|
||||
mnemonic_strm.Printf("0x%2.2x", uval8);
|
||||
}
|
||||
|
@ -317,7 +319,7 @@ public:
|
|||
case 2:
|
||||
{
|
||||
const uint16_t uval16 = data.GetU16(&offset);
|
||||
m_opcode.SetOpcode16(uval16);
|
||||
m_opcode.SetOpcode16(uval16, byte_order);
|
||||
m_opcode_name.assign (".short");
|
||||
mnemonic_strm.Printf("0x%4.4x", uval16);
|
||||
}
|
||||
|
@ -325,7 +327,7 @@ public:
|
|||
case 4:
|
||||
{
|
||||
const uint32_t uval32 = data.GetU32(&offset);
|
||||
m_opcode.SetOpcode32(uval32);
|
||||
m_opcode.SetOpcode32(uval32, byte_order);
|
||||
m_opcode_name.assign (".long");
|
||||
mnemonic_strm.Printf("0x%8.8x", uval32);
|
||||
}
|
||||
|
@ -333,7 +335,7 @@ public:
|
|||
case 8:
|
||||
{
|
||||
const uint64_t uval64 = data.GetU64(&offset);
|
||||
m_opcode.SetOpcode64(uval64);
|
||||
m_opcode.SetOpcode64(uval64, byte_order);
|
||||
m_opcode_name.assign (".quad");
|
||||
mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
|
||||
}
|
||||
|
|
|
@ -12889,18 +12889,18 @@ EmulateInstructionARM::ReadInstruction ()
|
|||
{
|
||||
if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
|
||||
{
|
||||
m_opcode.SetOpcode16 (thumb_opcode);
|
||||
m_opcode.SetOpcode16 (thumb_opcode, GetByteOrder());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
|
||||
m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success), GetByteOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_opcode_mode = eModeARM;
|
||||
m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
|
||||
m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13510,15 +13510,15 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
|
|||
if (arch.GetTriple().getArch() == llvm::Triple::arm)
|
||||
{
|
||||
m_opcode_mode = eModeARM;
|
||||
m_opcode.SetOpcode32 (test_opcode);
|
||||
m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
|
||||
}
|
||||
else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
|
||||
{
|
||||
m_opcode_mode = eModeThumb;
|
||||
if (test_opcode < 0x10000)
|
||||
m_opcode.SetOpcode16 (test_opcode);
|
||||
m_opcode.SetOpcode16 (test_opcode, GetByteOrder());
|
||||
else
|
||||
m_opcode.SetOpcode32 (test_opcode);
|
||||
m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
|
||||
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue