nitesh.jain retitled this revision from "[LLDB][MIPS] Fix register read/write 
for big endian" to "[LLDB][MIPS] Fix register read/write for 32 bit big endian 
system".
nitesh.jain updated the summary for this revision.
nitesh.jain updated this revision to Diff 71360.

https://reviews.llvm.org/D24124

Files:
  include/lldb/Core/DataExtractor.h
  source/Core/DataExtractor.cpp
  source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
  source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp

Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -1936,8 +1936,17 @@
 
   // Build the reginfos response.
   StreamGDBRemote response;
-
-  RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder());
+  uint64_t dst_value;
+  RegisterValue reg_value;
+  lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;
+  // The host will always send data in target byte order
+  // Hence source byte order will be same as destination byte order
+  m_debugged_process_sp->GetByteOrder(byte_order);
+  
+  DataExtractor::CopyByteOrderedData(reg_bytes, reg_size,
+                                     byte_order, &dst_value,
+                                     sizeof(dst_value), byte_order);
+  reg_value.SetUInt(dst_value, reg_size);
   Error error = reg_context_sp->WriteRegister(reg_info, reg_value);
   if (error.Fail()) {
     if (log)
Index: source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
===================================================================
--- source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
+++ source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
@@ -169,7 +169,7 @@
 
   if (error.Success())
     // First cast to an unsigned of the same size to avoid sign extension.
-    value.SetUInt64(static_cast<unsigned long>(data));
+    value.SetUInt(static_cast<unsigned long>(data), size);
 
   if (log)
     log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__,
Index: source/Core/DataExtractor.cpp
===================================================================
--- source/Core/DataExtractor.cpp
+++ source/Core/DataExtractor.cpp
@@ -938,6 +938,87 @@
   return 0;
 }
 
+lldb::offset_t DataExtractor::CopyByteOrderedData(void *src_void_ptr,
+                                                  offset_t src_len,
+                                                  ByteOrder src_byte_order,
+                                                  void *dst_void_ptr,
+                                                  offset_t dst_len,
+                                                  ByteOrder dst_byte_order) {
+
+  // Validate the source and destination info
+  assert(dst_void_ptr != nullptr || src_void_ptr != nullptr);
+  assert(dst_len > 0 || src_len > 0);
+  assert(src_len <= dst_len);
+  assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle);
+  assert(src_byte_order == eByteOrderBig || src_byte_order == eByteOrderLittle);
+
+  // Validate that only a word- or register-sized dst is byte swapped
+  assert(dst_byte_order == src_byte_order || dst_len == 1 || dst_len == 2 ||
+         dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 ||
+         dst_len == 32);
+
+  uint8_t* dst = (uint8_t*)dst_void_ptr;
+  const uint8_t* src = (const uint8_t *)src_void_ptr;
+  if (src) {
+    if (dst_len >= src_len) {
+      // We are copying the entire value from src into dst.
+      // Calculate how many, if any, zeroes we need for the most
+      // significant bytes if "dst_len" is greater than "src_len"...
+      const size_t num_zeroes = dst_len - src_len;
+      if (dst_byte_order == eByteOrderBig) {
+        // Big endian, so we lead with zeroes...
+        if (num_zeroes > 0)
+          ::memset(dst, 0, num_zeroes);
+        // Then either copy or swap the rest
+        if (src_byte_order == eByteOrderBig) {
+          ::memcpy(dst + num_zeroes, src, src_len);
+        } else {
+          for (uint32_t i = 0; i < src_len; ++i)
+            dst[i + num_zeroes] = src[src_len - 1 - i];
+        }
+      } else {
+        // Little endian destination, so we lead the value bytes
+        if (src_byte_order == eByteOrderBig) {
+          for (uint32_t i = 0; i < src_len; ++i)
+            dst[i] = src[src_len - 1 - i];
+        } else {
+          ::memcpy(dst, src, src_len);
+        }
+        // And zero the rest...
+        if (num_zeroes > 0)
+          ::memset(dst + src_len, 0, num_zeroes);
+      }
+      return src_len;
+    } else {
+      // We are only copying some of the value from src into dst..
+
+      if (dst_byte_order == eByteOrderBig) {
+        // Big endian dst
+        if (src_byte_order == eByteOrderBig) {
+          // Big endian dst, with big endian src
+          ::memcpy(dst, src + (src_len - dst_len), dst_len);
+        } else {
+          // Big endian dst, with little endian src
+          for (uint32_t i = 0; i < dst_len; ++i)
+            dst[i] = src[dst_len - 1 - i];
+        }
+      } else {
+        // Little endian dst
+        if (src_byte_order == eByteOrderBig) {
+          // Little endian dst, with big endian src
+          for (uint32_t i = 0; i < dst_len; ++i)
+            dst[i] = src[src_len - 1 - i];
+        } else {
+          // Little endian dst, with big endian src
+          ::memcpy(dst, src, dst_len);
+        }
+      }
+      return dst_len;
+    }
+  }
+  return 0;
+}
+
 // Extract data and swap if needed when doing the copy
 lldb::offset_t
 DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len,
Index: include/lldb/Core/DataExtractor.h
===================================================================
--- include/lldb/Core/DataExtractor.h
+++ include/lldb/Core/DataExtractor.h
@@ -521,6 +521,48 @@
                                      lldb::offset_t dst_len,
                                      lldb::ByteOrder dst_byte_order) const;
 
+  //------------------------------------------------------------------------
+  /// copy a dst_len bytes from a *src_void_ptr and ensure the copied
+  /// data is treated as a value that can be swapped to match the
+  /// specified byte order.
+  ///
+  /// For values that are larger than the supported integer sizes,
+  /// this function can be used to extract data in a specified byte
+  /// order. It can also be used to copy a smaller integer value from
+  /// to a larger value. The extra bytes left over will be padded
+  /// correctly according to src_byte_order and the dst_byte_order.
+  /// This can be very handy when say copying a partial data value
+  /// into a register.
+  /// 
+  /// @param[in] src_void_ptr
+  ///     A pointer to the source buffer from where endian data need to be copy
+  ///
+  /// @param[in] src_len
+  ///     The length of the endian data to copy from source buffer
+  ///
+  /// @param[in] src_byte_order
+  ///     The byte order that the endian value should be in a source buffer
+  ///
+  /// @param[out] dst_void_ptr
+  ///     A pointer to the destination buffer to place endian data
+  ///
+  /// @param[in] dst_len
+  ///     The number of bytes to be copied to the destination buffer
+  ///
+  /// @param[in] dst_byte_order
+  ///     The byte order that the endian value should be in a destination buffer
+  ///
+  /// @return
+  ///     Returns the number of bytes that were copied , or zero if 
+  ///     anything goes wrong
+  //------------------------------------------------------------------------
+  static lldb::offset_t CopyByteOrderedData(void *src_void_ptr,
+                                            lldb::offset_t src_len,
+                                            lldb::ByteOrder src_byte_order,
+                                            void *dst_void_ptr,
+                                            lldb::offset_t dst_len,
+                                            lldb::ByteOrder dst_byte_order);
+
   //------------------------------------------------------------------
   /// Get the data end pointer.
   ///
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to