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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits