diff options
author | Ed Maste <emaste@freebsd.org> | 2013-12-09 19:45:33 +0000 |
---|---|---|
committer | Ed Maste <emaste@freebsd.org> | 2013-12-09 19:45:33 +0000 |
commit | 90359963ab28ed454d933e33511aa05808444f33 (patch) | |
tree | 5a9b481289e60ebbd6ccf37088b4e52b86131df2 /lldb/source/Core/Opcode.cpp | |
parent | e2a1418e68d3ed091d6c902e82c8504a8dea1503 (diff) | |
download | bcm5719-llvm-90359963ab28ed454d933e33511aa05808444f33.tar.gz bcm5719-llvm-90359963ab28ed454d933e33511aa05808444f33.zip |
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
Diffstat (limited to 'lldb/source/Core/Opcode.cpp')
-rw-r--r-- | lldb/source/Core/Opcode.cpp | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/lldb/source/Core/Opcode.cpp b/lldb/source/Core/Opcode.cpp index 978a110150f..2bf7f5eae9b 100644 --- a/lldb/source/Core/Opcode.cpp +++ b/lldb/source/Core/Opcode.cpp @@ -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()) + { + 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 { - 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; + 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; |