Index: source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp @@ -181,7 +181,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__, reg_name, data); Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.h @@ -94,15 +94,22 @@ protected: Error - DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) override; + DoReadRegister_SR_Config (uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value); + + uint32_t + GetPtraceRegisterOffset (uint32_t reg_index, + const RegisterInfo *const reg_info); + + Error + ReadRegisterRaw (uint32_t reg_index, + RegisterValue &value) override; Error - DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) override; + WriteRegisterRaw (uint32_t reg_index, + const RegisterValue &value) override; Error DoReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback); Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -28,9 +28,16 @@ #include "Plugins/Process/Linux/Procfs.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips64.h" #include "Plugins/Process/Utility/RegisterContextLinux_mips.h" + #define NT_MIPS_MSA 0x600 #define CONFIG5_FRE (1 << 8) #define SR_FR (1 << 26) +#define FPR_BASE 32 +#define PC 64 +#define CAUSE 65 +#define BADVADDR 66 +#define MMHI 67 +#define MMLO 68 #define NUM_REGISTERS 32 #include @@ -649,7 +656,7 @@ if (IsFPR(reg_index) || IsMSA(reg_index)) { - uint8_t *dst; + uint8_t *dst, byte_size; uint64_t *src; // Initialise the FP and MSA buffers by reading all co-processor 1 registers @@ -659,13 +666,14 @@ { assert (reg_info->byte_offset < sizeof(UserArea)); dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); + byte_size = IsFR0 () ? 4 : 8; } else { assert (reg_info->byte_offset < sizeof(UserArea)); dst = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr)); } - switch (reg_info->byte_size) + switch (byte_size) { case 4: *(uint32_t *)dst = reg_value.GetAsUInt32(); @@ -801,7 +809,7 @@ lldb::ByteOrder byte_order = GetByteOrder(); - uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); + bool IsBigEndian = (byte_order == lldb::eByteOrderBig); if (IsMSAAvailable()) { @@ -827,12 +835,20 @@ // TODO: Add support for FRE if (IsFR0()) { - src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); - dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); + src = (uint8_t *)&m_fpr + (!IsBigEndian) * 4; + dst = (uint8_t *)&m_fpr + 8; for (int i = 0; i < (NUM_REGISTERS / 2); i++) { // copy odd single from top of neighbouring even double - *(uint32_t *) dst = *(uint32_t *) src; + // In case of little endian, 32 bit LSB contain even floating point register + // and 32 bit MSB contain odd floating point register + // vice-versa for big endian + *(uint32_t *) dst = *(uint32_t *) src; + + if (IsBigEndian) + // Copy 32 bit MSB to 32 bit LSB + *(uint32_t *) src = *(uint32_t *)(src + 4); + src = src + 16; dst = dst + 16; } @@ -850,19 +866,24 @@ lldb::ByteOrder byte_order = GetByteOrder(); - uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); + bool IsBigEndian = (byte_order == lldb::eByteOrderBig); // TODO: Add support for FRE if (IsFR0()) { - src = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); - dst = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); + dst = (uint8_t *)&m_fpr + (!IsBigEndian) * 4; + src = dst + 8 - (!IsBigEndian) * 4; for (int i = 0; i < (NUM_REGISTERS / 2); i++) { // copy odd single to top of neighbouring even double - *(uint32_t *) dst = *(uint32_t *) src; + if (IsBigEndian) + // Copy 32 bit LSB to 32 bit MSB + *(uint32_t *) (dst + 4) = *(uint32_t *) dst; + + *(uint32_t *)dst = *(uint32_t *)src; + src = src + 16; - dst = dst + 16; + dst = src + 16; } } @@ -1374,51 +1395,105 @@ } return num_valid; } -Error -NativeRegisterContextLinux_mips64::DoReadRegisterValue(uint32_t offset, - const char* reg_name, - uint32_t size, - RegisterValue &value) -{ - GPR_linux_mips regs; - ::memset(®s, 0, sizeof(GPR_linux_mips)); - // Clear all bits in RegisterValue before writing actual value read from ptrace to avoid garbage value in 32-bit MSB - value.SetBytes((void *)(((unsigned char *)®s) + offset), 8, GetByteOrder()); - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); - if (error.Success()) +uint32_t +NativeRegisterContextLinux_mips64::GetPtraceRegisterOffset (uint32_t reg_index, + const RegisterInfo *const reg_info) +{ + // In case of MIPS, the PTRACE_PEEKUSER/PTRACE_POKEUSER + // take register number has an offset + // Apart from GPR registers , the offset for other registers are + // FPR_BASE 32 + // PC 64 + // CAUSE 65 + // BADVADDR 66 + // MMHI 67 + // MMLO 68 + + static_assert (dwarf_zero_mips == dwarf_zero_mips64 && + dwarf_pc_mips == dwarf_pc_mips64, + "MIPS and MIPS64 dwarf no. mismatch"); + + if (reg_index < dwarf_sr_mips) + return reg_index; + + switch (reg_info->kinds[lldb::eRegisterKindDWARF]) { - lldb_private::ArchSpec arch; - if (m_thread.GetProcess()->GetArchitecture(arch)) - { - void* target_address = ((uint8_t*)®s) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips); - uint32_t target_size; - if ((::strcmp(reg_name, "sr") == 0) || (::strcmp(reg_name, "cause") == 0) || (::strcmp(reg_name, "config5") == 0)) - target_size = 4; - else - target_size = arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8; - value.SetBytes(target_address, target_size, arch.GetByteOrder()); - } - else - error.SetErrorString("failed to get architecture"); + case dwarf_pc_mips: + return PC; + case dwarf_sr_mips: + case dwarf_config5_mips: + case dwarf_config5_mips64: + return reg_info->byte_offset; + case dwarf_cause_mips: + return CAUSE; + case dwarf_bad_mips: + return BADVADDR; + case dwarf_hi_mips: + return MMHI; + case dwarf_lo_mips: + return MMLO; + default: + assert (false && "Invalid Register Kinds"); } - return error; + return 0; +} + +Error +NativeRegisterContextLinux_mips64::ReadRegisterRaw (uint32_t reg_index, + RegisterValue &value) +{ + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); + + if (!reg_info) + return Error ("register %" PRIu32 " not found", reg_index); + + uint32_t offset = GetPtraceRegisterOffset (reg_index, reg_info); + + if ((reg_index == dwarf_sr_mips) || (strcmp(reg_info->name, "config5") == 0)) + return DoReadRegister_SR_Config (offset, reg_info->name, + reg_info->byte_size, value); + + return DoReadRegisterValue (offset, reg_info->name, + reg_info->byte_size, value); } Error -NativeRegisterContextLinux_mips64::DoWriteRegisterValue(uint32_t offset, - const char* reg_name, - const RegisterValue &value) +NativeRegisterContextLinux_mips64::WriteRegisterRaw (uint32_t reg_index, + const RegisterValue &value) +{ + const RegisterInfo *const reg_info = GetRegisterInfoAtIndex (reg_index); + + if (!reg_info) + return Error ("register %" PRIu32 " not found", reg_index); + + if (reg_info->invalidate_regs) + assert (false && "In MIPS, reg_info->invalidate_regs is unhandled"); + + uint32_t offset = GetPtraceRegisterOffset (reg_index, reg_info); + return DoWriteRegisterValue (offset, reg_info->name, value); +} + +Error +NativeRegisterContextLinux_mips64::DoReadRegister_SR_Config (uint32_t offset, + const char* reg_name, + uint32_t size, + RegisterValue &value) { GPR_linux_mips regs; - Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + ::memset(®s, 0, sizeof(GPR_linux_mips)); + + Error error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGS, + m_thread.GetID(), NULL, + ®s, sizeof regs); if (error.Success()) { lldb_private::ArchSpec arch; if (m_thread.GetProcess()->GetArchitecture(arch)) { - ::memcpy((void *)(((unsigned char *)(®s)) + offset), value.GetBytes(), arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8); - error = NativeProcessLinux::PtraceWrapper(PTRACE_SETREGS, m_thread.GetID(), NULL, ®s, sizeof regs); + void* target_address = ((uint8_t*)®s) + offset + + 4 * (arch.GetMachine() == llvm::Triple::mips); + value.SetUInt (*(uint32_t *)target_address, size); } else error.SetErrorString("failed to get architecture"); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1840,8 +1840,12 @@ // Build the reginfos response. StreamGDBRemote response; + + uint64_t value; + value = reg_size == 4 ? *(uint32_t *)reg_bytes : *(uint64_t *)reg_bytes; - RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ()); + RegisterValue reg_value; + reg_value.SetUInt (value, reg_size); Error error = reg_context_sp->WriteRegister (reg_info, reg_value); if (error.Fail ()) {