The Opcode class does not handle the case where the target and host have 
different endianness.

An opcode set via SetOpcode32 for example is later extracted via GetData() as a 
byte sequence in host order rather than target order.


http://llvm-reviews.chandlerc.com/D1838

Files:
  include/lldb/Core/Opcode.h
  source/Core/Opcode.cpp
Index: include/lldb/Core/Opcode.h
===================================================================
--- include/lldb/Core/Opcode.h
+++ include/lldb/Core/Opcode.h
@@ -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 @@
             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) : m_byte_order (lldb::eByteOrderInvalid), m_type (eType8)
         {
             m_data.inst8 = inst;
         }
 
-        Opcode (uint16_t inst) : m_type (eType16)
+        Opcode (uint16_t inst) : m_byte_order (lldb::eByteOrderInvalid), m_type (eType16)
         {
             m_data.inst16 = inst;
         }
 
-        Opcode (uint32_t inst) : m_type (eType32)
+        Opcode (uint32_t inst) : m_byte_order (lldb::eByteOrderInvalid), m_type (eType32)
         {
             m_data.inst32 = inst;
         }
 
-        Opcode (uint64_t inst) : m_type (eType64)
+        Opcode (uint64_t inst) : m_byte_order (lldb::eByteOrderInvalid), 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 @@
         void
         Clear()
         {
+            m_byte_order = lldb::eByteOrderInvalid;
             m_type = Opcode::eTypeInvalid;
         }
         Opcode::Type
@@ -102,7 +105,7 @@
             {
             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 @@
             {
             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,10 +137,10 @@
             {
             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;
@@ -187,6 +190,7 @@
                 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
             {
@@ -195,6 +199,12 @@
             }
         }
 
+        void
+        SetByteOrder (lldb::ByteOrder byte_order)
+        {
+            m_byte_order = byte_order;
+        }
+
         int
         Dump (Stream *s, uint32_t min_byte_width);
 
@@ -249,6 +259,15 @@
         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
         {
Index: source/Core/Opcode.cpp
===================================================================
--- source/Core/Opcode.cpp
+++ source/Core/Opcode.cpp
@@ -71,6 +71,10 @@
 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 @@
 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)
     {
+        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
+        {
             switch (m_type)
             {
                 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::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:
-                {
-                    // 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));
-                }
+                    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:
-                buffer_sp.reset (new DataBufferHeap (&m_data.inst32, byte_size));
+                    *(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::eType64:   buffer_sp.reset (new DataBufferHeap (&m_data.inst64, byte_size)); break;
-            case Opcode::eTypeBytes:buffer_sp.reset (new DataBufferHeap (GetOpcodeBytes(), byte_size)); 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;
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to