diff options
| author | Nitesh Jain <nitesh.jain@imgtec.com> | 2016-10-12 10:53:57 +0000 |
|---|---|---|
| committer | Nitesh Jain <nitesh.jain@imgtec.com> | 2016-10-12 10:53:57 +0000 |
| commit | 47a2c55447106a55d5bd7a9172548571fc6f6c83 (patch) | |
| tree | 00993ce02cd93fae275e2f7cd8fc03812148d9bc /lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp | |
| parent | 6b42540756262beb65fda7e4b844376ff70499bd (diff) | |
| download | bcm5719-llvm-47a2c55447106a55d5bd7a9172548571fc6f6c83.tar.gz bcm5719-llvm-47a2c55447106a55d5bd7a9172548571fc6f6c83.zip | |
[LLDB][MIPS] fix Floating point register read/write for big endian
Reviewers: clayborg, labath, jaydeep
Subscribers: bhushan, slthakur, lldb-commits
Differential Revision: https://reviews.llvm.org/D24603
llvm-svn: 284003
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp | 163 |
1 files changed, 86 insertions, 77 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp index 6c79537892b..c050a2ec0cc 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp @@ -26,6 +26,7 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Utility/LLDBAssert.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" #define NT_MIPS_MSA 0x600 @@ -392,6 +393,7 @@ NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info, } const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + uint8_t byte_size = reg_info->byte_size; if (reg == LLDB_INVALID_REGNUM) { // This is likely an internal register for lldb use only and should not be // directly queried. @@ -407,7 +409,8 @@ NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info, } if (IsMSA(reg) || IsFPR(reg)) { - uint8_t *src; + uint8_t *src = nullptr; + lldbassert(reg_info->byte_offset < sizeof(UserArea)); error = ReadCP1(); @@ -417,14 +420,17 @@ NativeRegisterContextLinux_mips64::ReadRegister(const RegisterInfo *reg_info, } if (IsFPR(reg)) { - assert(reg_info->byte_offset < sizeof(UserArea)); - src = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); - } else { - assert(reg_info->byte_offset < sizeof(UserArea)); + if (IsFR0() && (byte_size != 4)) { + byte_size = 4; + uint8_t ptrace_index; + ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; + src = ReturnFPOffset(ptrace_index, reg_info->byte_offset); + } else + src = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr); + } else src = (uint8_t *)&m_msa + reg_info->byte_offset - (sizeof(m_gpr) + sizeof(m_fpr)); - } - switch (reg_info->byte_size) { + switch (byte_size) { case 4: reg_value.SetUInt32(*(uint32_t *)src); break; @@ -466,21 +472,26 @@ lldb_private::Error NativeRegisterContextLinux_mips64::WriteRegister( } if (IsFPR(reg_index) || IsMSA(reg_index)) { - uint8_t *dst; - uint64_t *src; + uint8_t *dst = nullptr; + uint64_t *src = nullptr; + uint8_t byte_size = reg_info->byte_size; + lldbassert(reg_info->byte_offset < sizeof(UserArea)); // Initialise the FP and MSA buffers by reading all co-processor 1 registers ReadCP1(); if (IsFPR(reg_index)) { - assert(reg_info->byte_offset < sizeof(UserArea)); - dst = (uint8_t *)&m_fpr + reg_info->byte_offset - (sizeof(m_gpr)); - } else { - assert(reg_info->byte_offset < sizeof(UserArea)); + if (IsFR0() && (byte_size != 4)) { + byte_size = 4; + uint8_t ptrace_index; + ptrace_index = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; + dst = ReturnFPOffset(ptrace_index, reg_info->byte_offset); + } else + dst = (uint8_t *)&m_fpr + reg_info->byte_offset - sizeof(m_gpr); + } else 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(); break; @@ -611,11 +622,12 @@ Error NativeRegisterContextLinux_mips64::WriteAllRegisterValues( Error NativeRegisterContextLinux_mips64::ReadCP1() { Error error; - uint8_t *src, *dst; + uint8_t *src = nullptr; + uint8_t *dst = nullptr; lldb::ByteOrder byte_order = GetByteOrder(); - uint32_t IsBigEndian = (byte_order == lldb::eByteOrderBig); + bool IsBigEndian = (byte_order == lldb::eByteOrderBig); if (IsMSAAvailable()) { error = NativeRegisterContextLinux::ReadRegisterSet( @@ -634,42 +646,36 @@ Error NativeRegisterContextLinux_mips64::ReadCP1() { } else { error = NativeRegisterContextLinux::ReadFPR(); } + return error; +} - // TODO: Add support for FRE - if (IsFR0()) { - src = (uint8_t *)&m_fpr + 4 + (IsBigEndian * 4); - dst = (uint8_t *)&m_fpr + 8 + (IsBigEndian * 4); - for (int i = 0; i < (NUM_REGISTERS / 2); i++) { - // copy odd single from top of neighbouring even double - *(uint32_t *)dst = *(uint32_t *)src; - src = src + 16; - dst = dst + 16; - } - } +uint8_t * +NativeRegisterContextLinux_mips64::ReturnFPOffset(uint8_t reg_index, + uint32_t byte_offset) { - return error; + uint8_t *fp_buffer_ptr = nullptr; + lldb::ByteOrder byte_order = GetByteOrder(); + bool IsBigEndian = (byte_order == lldb::eByteOrderBig); + if (reg_index % 2) { + uint8_t offset_diff = (IsBigEndian) ? 8 : 4; + fp_buffer_ptr = + (uint8_t *)&m_fpr + byte_offset - offset_diff - sizeof(m_gpr); + } else { + fp_buffer_ptr = + (uint8_t *)&m_fpr + byte_offset + 4 * (IsBigEndian) - sizeof(m_gpr); + } + return fp_buffer_ptr; } Error NativeRegisterContextLinux_mips64::WriteCP1() { Error error; - uint8_t *src, *dst; + uint8_t *src = nullptr; + uint8_t *dst = nullptr; lldb::ByteOrder byte_order = GetByteOrder(); - uint32_t 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); - for (int i = 0; i < (NUM_REGISTERS / 2); i++) { - // copy odd single to top of neighbouring even double - *(uint32_t *)dst = *(uint32_t *)src; - src = src + 16; - dst = dst + 16; - } - } + bool IsBigEndian = (byte_order == lldb::eByteOrderBig); if (IsMSAAvailable()) { dst = (uint8_t *)&m_msa + (IsBigEndian * 8); @@ -1132,16 +1138,45 @@ uint32_t NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints() { } return num_valid; } -Error NativeRegisterContextLinux_mips64::DoReadRegisterValue( - uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) { + +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 = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; + + if ((offset == ptrace_sr_mips) || (offset == ptrace_config5_mips)) + return Read_SR_Config(reg_info->byte_offset, reg_info->name, + reg_info->byte_size, value); + + return DoReadRegisterValue(offset, reg_info->name, reg_info->byte_size, + value); +} + +Error 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) + lldbassert(false && "reg_info->invalidate_regs is unhandled"); + + uint32_t offset = reg_info->kinds[lldb::eRegisterKindProcessPlugin]; + return DoWriteRegisterValue(offset, reg_info->name, value); +} + +Error NativeRegisterContextLinux_mips64::Read_SR_Config(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()) { @@ -1149,33 +1184,7 @@ Error NativeRegisterContextLinux_mips64::DoReadRegisterValue( 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"); - } - return error; -} - -Error NativeRegisterContextLinux_mips64::DoWriteRegisterValue( - uint32_t offset, const char *reg_name, const RegisterValue &value) { - GPR_linux_mips regs; - 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); + value.SetUInt(*(uint32_t *)target_address, size); } else error.SetErrorString("failed to get architecture"); } |

