Author: emaste Date: Mon Dec 9 13:45:33 2013 New Revision: 196808 URL: http://llvm.org/viewvc/llvm-project?rev=196808&view=rev Log: 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 Modified: lldb/trunk/include/lldb/Core/Opcode.h lldb/trunk/source/Core/Disassembler.cpp lldb/trunk/source/Core/Opcode.cpp lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Modified: lldb/trunk/include/lldb/Core/Opcode.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Opcode.h?rev=196808&r1=196807&r2=196808&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Opcode.h (original) +++ lldb/trunk/include/lldb/Core/Opcode.h Mon Dec 9 13:45:33 2013 @@ -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 { Modified: lldb/trunk/source/Core/Disassembler.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Disassembler.cpp?rev=196808&r1=196807&r2=196808&view=diff ============================================================================== --- lldb/trunk/source/Core/Disassembler.cpp (original) +++ lldb/trunk/source/Core/Disassembler.cpp Mon Dec 9 13:45:33 2013 @@ -1236,25 +1236,25 @@ PseudoInstruction::SetOpcode (size_t opc 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: Modified: lldb/trunk/source/Core/Opcode.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Opcode.cpp?rev=196808&r1=196807&r2=196808&view=diff ============================================================================== --- lldb/trunk/source/Core/Opcode.cpp (original) +++ lldb/trunk/source/Core/Opcode.cpp Mon Dec 9 13:45:33 2013 @@ -71,6 +71,10 @@ Opcode::Dump (Stream *s, uint32_t min_by 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; Modified: lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp?rev=196808&r1=196807&r2=196808&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp (original) +++ lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp Mon Dec 9 13:45:33 2013 @@ -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); } Modified: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp?rev=196808&r1=196807&r2=196808&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp (original) +++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp Mon Dec 9 13:45:33 2013 @@ -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 (St 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 _______________________________________________ lldb-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits
