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. /// 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: 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(data)); + value.SetUInt(static_cast(data), size); if (log) log->Printf("NativeRegisterContextLinux::%s() reg %s: 0x%lx", __FUNCTION__, 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)