diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp | 1050 |
1 files changed, 485 insertions, 565 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp index b09ad400d90..7ec4dc551fa 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp @@ -30,99 +30,62 @@ using namespace lldb_private::process_linux; // Private namespace. // ---------------------------------------------------------------------------- -namespace -{ - // s390x 64-bit general purpose registers. - static const uint32_t g_gpr_regnums_s390x[] = - { - lldb_r0_s390x, - lldb_r1_s390x, - lldb_r2_s390x, - lldb_r3_s390x, - lldb_r4_s390x, - lldb_r5_s390x, - lldb_r6_s390x, - lldb_r7_s390x, - lldb_r8_s390x, - lldb_r9_s390x, - lldb_r10_s390x, - lldb_r11_s390x, - lldb_r12_s390x, - lldb_r13_s390x, - lldb_r14_s390x, - lldb_r15_s390x, - lldb_acr0_s390x, - lldb_acr1_s390x, - lldb_acr2_s390x, - lldb_acr3_s390x, - lldb_acr4_s390x, - lldb_acr5_s390x, - lldb_acr6_s390x, - lldb_acr7_s390x, - lldb_acr8_s390x, - lldb_acr9_s390x, - lldb_acr10_s390x, - lldb_acr11_s390x, - lldb_acr12_s390x, - lldb_acr13_s390x, - lldb_acr14_s390x, - lldb_acr15_s390x, - lldb_pswm_s390x, - lldb_pswa_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x, - "g_gpr_regnums_s390x has wrong number of register infos"); - - // s390x 64-bit floating point registers. - static const uint32_t g_fpu_regnums_s390x[] = - { - lldb_f0_s390x, - lldb_f1_s390x, - lldb_f2_s390x, - lldb_f3_s390x, - lldb_f4_s390x, - lldb_f5_s390x, - lldb_f6_s390x, - lldb_f7_s390x, - lldb_f8_s390x, - lldb_f9_s390x, - lldb_f10_s390x, - lldb_f11_s390x, - lldb_f12_s390x, - lldb_f13_s390x, - lldb_f14_s390x, - lldb_f15_s390x, - lldb_fpc_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x, - "g_fpu_regnums_s390x has wrong number of register infos"); - - // s390x Linux operating-system information. - static const uint32_t g_linux_regnums_s390x[] = - { - lldb_orig_r2_s390x, - lldb_last_break_s390x, - lldb_system_call_s390x, - LLDB_INVALID_REGNUM // register sets need to end with this flag - }; - static_assert((sizeof(g_linux_regnums_s390x) / sizeof(g_linux_regnums_s390x[0])) - 1 == k_num_linux_registers_s390x, - "g_linux_regnums_s390x has wrong number of register infos"); - - // Number of register sets provided by this context. - enum - { - k_num_register_sets = 3 - }; - - // Register sets for s390x 64-bit. - static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = - { - { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x }, - { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x }, - { "Linux Operating System Data", "linux", k_num_linux_registers_s390x, g_linux_regnums_s390x }, - }; +namespace { +// s390x 64-bit general purpose registers. +static const uint32_t g_gpr_regnums_s390x[] = { + lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x, + lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x, + lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x, + lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x, + lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x, + lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x, + lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x, + lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x, + lldb_pswm_s390x, lldb_pswa_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - + 1 == + k_num_gpr_registers_s390x, + "g_gpr_regnums_s390x has wrong number of register infos"); + +// s390x 64-bit floating point registers. +static const uint32_t g_fpu_regnums_s390x[] = { + lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x, + lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x, + lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x, + lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x, + lldb_fpc_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - + 1 == + k_num_fpr_registers_s390x, + "g_fpu_regnums_s390x has wrong number of register infos"); + +// s390x Linux operating-system information. +static const uint32_t g_linux_regnums_s390x[] = { + lldb_orig_r2_s390x, lldb_last_break_s390x, lldb_system_call_s390x, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert((sizeof(g_linux_regnums_s390x) / + sizeof(g_linux_regnums_s390x[0])) - + 1 == + k_num_linux_registers_s390x, + "g_linux_regnums_s390x has wrong number of register infos"); + +// Number of register sets provided by this context. +enum { k_num_register_sets = 3 }; + +// Register sets for s390x 64-bit. +static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { + {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x, + g_gpr_regnums_s390x}, + {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x, + g_fpu_regnums_s390x}, + {"Linux Operating System Data", "linux", k_num_linux_registers_s390x, + g_linux_regnums_s390x}, +}; } #define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4) @@ -131,15 +94,15 @@ namespace // Required ptrace defines. // ---------------------------------------------------------------------------- -#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ +#define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ NativeRegisterContextLinux * -NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) -{ - return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx); +NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) { + return new NativeRegisterContextLinux_s390x(target_arch, native_thread, + concrete_frame_idx); } // ---------------------------------------------------------------------------- @@ -147,570 +110,527 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec // ---------------------------------------------------------------------------- static RegisterInfoInterface * -CreateRegisterInfoInterface(const ArchSpec &target_arch) -{ - assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && - "Register setting path assumes this is a 64-bit host"); - return new RegisterContextLinux_s390x(target_arch); -} - -NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, - NativeThreadProtocol &native_thread, - uint32_t concrete_frame_idx) - : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch)) -{ - // Set up data about ranges of valid registers. - switch (target_arch.GetMachine()) - { - case llvm::Triple::systemz: - m_reg_info.num_registers = k_num_registers_s390x; - m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; - m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; - m_reg_info.last_gpr = k_last_gpr_s390x; - m_reg_info.first_fpr = k_first_fpr_s390x; - m_reg_info.last_fpr = k_last_fpr_s390x; - break; - default: - assert(false && "Unhandled target architecture."); - break; - } - - // Clear out the watchpoint state. - m_watchpoint_addr = LLDB_INVALID_ADDRESS; +CreateRegisterInfoInterface(const ArchSpec &target_arch) { + assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && + "Register setting path assumes this is a 64-bit host"); + return new RegisterContextLinux_s390x(target_arch); +} + +NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( + const ArchSpec &target_arch, NativeThreadProtocol &native_thread, + uint32_t concrete_frame_idx) + : NativeRegisterContextLinux(native_thread, concrete_frame_idx, + CreateRegisterInfoInterface(target_arch)) { + // Set up data about ranges of valid registers. + switch (target_arch.GetMachine()) { + case llvm::Triple::systemz: + m_reg_info.num_registers = k_num_registers_s390x; + m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; + m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; + m_reg_info.last_gpr = k_last_gpr_s390x; + m_reg_info.first_fpr = k_first_fpr_s390x; + m_reg_info.last_fpr = k_last_fpr_s390x; + break; + default: + assert(false && "Unhandled target architecture."); + break; + } + + // Clear out the watchpoint state. + m_watchpoint_addr = LLDB_INVALID_ADDRESS; +} + +uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount() const { + uint32_t sets = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + if (IsRegisterSetAvailable(set_index)) + ++sets; + } + + return sets; +} + +uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { + const RegisterSet *set = GetRegisterSet(set_index); + if (set) + count += set->num_registers; + } + return count; } -uint32_t -NativeRegisterContextLinux_s390x::GetRegisterSetCount() const -{ - uint32_t sets = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - if (IsRegisterSetAvailable(set_index)) - ++sets; - } +const RegisterSet * +NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const { + if (!IsRegisterSetAvailable(set_index)) + return nullptr; - return sets; -} + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::systemz: + return &g_reg_sets_s390x[set_index]; + default: + assert(false && "Unhandled target architecture."); + return nullptr; + } -uint32_t -NativeRegisterContextLinux_s390x::GetUserRegisterCount() const -{ - uint32_t count = 0; - for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) - { - const RegisterSet *set = GetRegisterSet(set_index); - if (set) - count += set->num_registers; - } - return count; + return nullptr; } -const RegisterSet * -NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const -{ - if (!IsRegisterSetAvailable(set_index)) - return nullptr; - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) - { - case llvm::Triple::systemz: - return &g_reg_sets_s390x[set_index]; - default: - assert(false && "Unhandled target architecture."); - return nullptr; - } +bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable( + uint32_t set_index) const { + return set_index < k_num_register_sets; +} - return nullptr; +bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const { + // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR + // register area. + return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; } -bool -NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(uint32_t set_index) const -{ - return set_index < k_num_register_sets; -} - -bool -NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const -{ - // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR register area. - return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; -} - -bool -NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const -{ - return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr); -} - -Error -NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value) -{ - if (!reg_info) - return Error("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Error("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name); - - if (IsGPR(reg)) - { - s390_regs regs; - Error error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) - { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Error(); - } +bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const { + return (m_reg_info.first_fpr <= reg_index && + reg_index <= m_reg_info.last_fpr); +} - if (IsFPR(reg)) - { - s390_fp_regs fp_regs; - Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within FPR, not the whole user area. - uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) - { - case 4: - reg_value.SetUInt32(*(uint32_t *)src); - break; - case 8: - reg_value.SetUInt64(*(uint64_t *)src); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return Error(); - } +Error NativeRegisterContextLinux_s390x::ReadRegister( + const RegisterInfo *reg_info, RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); - if (reg == lldb_last_break_s390x) - { - uint64_t last_break; - Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); - if (error.Fail()) - return error; + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot " + "read directly", + reg_info->name); - reg_value.SetUInt64(last_break); - return Error(); + if (IsGPR(reg)) { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return Error(); + } - if (reg == lldb_system_call_s390x) - { - uint32_t system_call; - Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - if (error.Fail()) - return error; - - reg_value.SetUInt32(system_call); - return Error(); + if (IsFPR(reg)) { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); + if (error.Fail()) + return error; + + // byte_offset is just the offset within FPR, not the whole user area. + uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) { + case 4: + reg_value.SetUInt32(*(uint32_t *)src); + break; + case 8: + reg_value.SetUInt64(*(uint64_t *)src); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return Error(); + } - return Error("failed - register wasn't recognized"); -} - -Error -NativeRegisterContextLinux_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue ®_value) -{ - if (!reg_info) - return Error("reg_info NULL"); - - const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; - if (reg == LLDB_INVALID_REGNUM) - return Error("register \"%s\" is an internal-only lldb register, cannot write directly", reg_info->name); - - if (IsGPR(reg)) - { - s390_regs regs; - Error error = DoReadGPR(®s, sizeof(regs)); - if (error.Fail()) - return error; - - uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); - switch (reg_info->byte_size) - { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteGPR(®s, sizeof(regs)); - } + if (reg == lldb_last_break_s390x) { + uint64_t last_break; + Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); + if (error.Fail()) + return error; - if (IsFPR(reg)) - { - s390_fp_regs fp_regs; - Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); - if (error.Fail()) - return error; - - // byte_offset is just the offset within fp_regs, not the whole user area. - uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; - assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); - switch (reg_info->byte_size) - { - case 4: - *(uint32_t *)dst = reg_value.GetAsUInt32(); - break; - case 8: - *(uint64_t *)dst = reg_value.GetAsUInt64(); - break; - default: - assert(false && "Unhandled data size."); - return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); - } - return DoWriteFPR(&fp_regs, sizeof(fp_regs)); - } + reg_value.SetUInt64(last_break); + return Error(); + } - if (reg == lldb_last_break_s390x) - { - return Error("The last break address is read-only"); - } + if (reg == lldb_system_call_s390x) { + uint32_t system_call; + Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + if (error.Fail()) + return error; - if (reg == lldb_system_call_s390x) - { - uint32_t system_call = reg_value.GetAsUInt32(); - return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - } + reg_value.SetUInt32(system_call); + return Error(); + } - return Error("failed - register wasn't recognized"); + return Error("failed - register wasn't recognized"); } -Error -NativeRegisterContextLinux_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) -{ - Error error; +Error NativeRegisterContextLinux_s390x::WriteRegister( + const RegisterInfo *reg_info, const RegisterValue ®_value) { + if (!reg_info) + return Error("reg_info NULL"); - data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); - if (!data_sp) - { - error.SetErrorStringWithFormat("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE); - return error; - } + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + if (reg == LLDB_INVALID_REGNUM) + return Error("register \"%s\" is an internal-only lldb register, cannot " + "write directly", + reg_info->name); - uint8_t *dst = data_sp->GetBytes(); - if (dst == nullptr) - { - error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer", - REG_CONTEXT_SIZE); - return error; + if (IsGPR(reg)) { + s390_regs regs; + Error error = DoReadGPR(®s, sizeof(regs)); + if (error.Fail()) + return error; + + uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); + switch (reg_info->byte_size) { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); } + return DoWriteGPR(®s, sizeof(regs)); + } - error = DoReadGPR(dst, sizeof(s390_regs)); - dst += sizeof(s390_regs); + if (IsFPR(reg)) { + s390_fp_regs fp_regs; + Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); if (error.Fail()) - return error; + return error; + + // byte_offset is just the offset within fp_regs, not the whole user area. + uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; + assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); + switch (reg_info->byte_size) { + case 4: + *(uint32_t *)dst = reg_value.GetAsUInt32(); + break; + case 8: + *(uint64_t *)dst = reg_value.GetAsUInt64(); + break; + default: + assert(false && "Unhandled data size."); + return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); + } + return DoWriteFPR(&fp_regs, sizeof(fp_regs)); + } - error = DoReadFPR(dst, sizeof(s390_fp_regs)); - dst += sizeof(s390_fp_regs); - if (error.Fail()) - return error; + if (reg == lldb_last_break_s390x) { + return Error("The last break address is read-only"); + } + + if (reg == lldb_system_call_s390x) { + uint32_t system_call = reg_value.GetAsUInt32(); + return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); + } - // Ignore errors if the regset is unsupported (happens on older kernels). - DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); - dst += 4; + return Error("failed - register wasn't recognized"); +} - // To enable inferior function calls while the process is stopped in - // an interrupted system call, we need to clear the system call flag. - // It will be restored to its original value by WriteAllRegisterValues. - // Again we ignore error if the regset is unsupported. - uint32_t system_call = 0; - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); +Error NativeRegisterContextLinux_s390x::ReadAllRegisterValues( + lldb::DataBufferSP &data_sp) { + Error error; + data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); + if (!data_sp) { + error.SetErrorStringWithFormat( + "failed to allocate DataBufferHeap instance of size %" PRIu64, + REG_CONTEXT_SIZE); return error; -} + } -Error -NativeRegisterContextLinux_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) -{ - Error error; + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) { + error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 + " returned a null pointer", + REG_CONTEXT_SIZE); + return error; + } - if (!data_sp) - { - error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s invalid data_sp provided", __FUNCTION__); - return error; - } + error = DoReadGPR(dst, sizeof(s390_regs)); + dst += sizeof(s390_regs); + if (error.Fail()) + return error; - if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) - { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched data size, expected %" PRIu64 - ", actual %" PRIu64, - __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); - return error; - } + error = DoReadFPR(dst, sizeof(s390_fp_regs)); + dst += sizeof(s390_fp_regs); + if (error.Fail()) + return error; - uint8_t *src = data_sp->GetBytes(); - if (src == nullptr) - { - error.SetErrorStringWithFormat( - "NativeRegisterContextLinux_s390x::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__); - return error; - } + // Ignore errors if the regset is unsupported (happens on older kernels). + DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); + dst += 4; - error = DoWriteGPR(src, sizeof(s390_regs)); - src += sizeof(s390_regs); - if (error.Fail()) - return error; + // To enable inferior function calls while the process is stopped in + // an interrupted system call, we need to clear the system call flag. + // It will be restored to its original value by WriteAllRegisterValues. + // Again we ignore error if the regset is unsupported. + uint32_t system_call = 0; + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); - error = DoWriteFPR(src, sizeof(s390_fp_regs)); - src += sizeof(s390_fp_regs); - if (error.Fail()) - return error; + return error; +} - // Ignore errors if the regset is unsupported (happens on older kernels). - DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); - src += 4; +Error NativeRegisterContextLinux_s390x::WriteAllRegisterValues( + const lldb::DataBufferSP &data_sp) { + Error error; + if (!data_sp) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s invalid data_sp provided", + __FUNCTION__); return error; + } + + if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { + error.SetErrorStringWithFormat( + "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); + return error; + } + + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) { + error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s " + "DataBuffer::GetBytes() returned a null " + "pointer", + __FUNCTION__); + return error; + } + + error = DoWriteGPR(src, sizeof(s390_regs)); + src += sizeof(s390_regs); + if (error.Fail()) + return error; + + error = DoWriteFPR(src, sizeof(s390_fp_regs)); + src += sizeof(s390_fp_regs); + if (error.Fail()) + return error; + + // Ignore errors if the regset is unsupported (happens on older kernels). + DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); + src += 4; + + return error; } -Error -NativeRegisterContextLinux_s390x::DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, - RegisterValue &value) -{ - return Error("DoReadRegisterValue unsupported"); +Error NativeRegisterContextLinux_s390x::DoReadRegisterValue( + uint32_t offset, const char *reg_name, uint32_t size, + RegisterValue &value) { + return Error("DoReadRegisterValue unsupported"); } -Error -NativeRegisterContextLinux_s390x::DoWriteRegisterValue(uint32_t offset, const char *reg_name, - const RegisterValue &value) -{ - return Error("DoWriteRegisterValue unsupported"); +Error NativeRegisterContextLinux_s390x::DoWriteRegisterValue( + uint32_t offset, const char *reg_name, const RegisterValue &value) { + return Error("DoWriteRegisterValue unsupported"); } -Error -NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, size_t buf_size) -{ - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; +Error NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, + size_t buf_size) { + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; - return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, m_thread.GetID(), &parea); + return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, + m_thread.GetID(), &parea); } -Error -NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, const void *buf, size_t buf_size) -{ - ptrace_area parea; - parea.len = buf_size; - parea.process_addr = (addr_t)buf; - parea.kernel_addr = offset; +Error NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, + const void *buf, + size_t buf_size) { + ptrace_area parea; + parea.len = buf_size; + parea.process_addr = (addr_t)buf; + parea.kernel_addr = offset; - return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, m_thread.GetID(), &parea); + return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, + m_thread.GetID(), &parea); } -Error -NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_regs)); - return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_regs)); + return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_regs)); - return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_regs)); + return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_fp_regs)); - return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_fp_regs)); + return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) -{ - assert(buf_size == sizeof(s390_fp_regs)); - return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); +Error NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) { + assert(buf_size == sizeof(s390_fp_regs)); + return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); } -Error -NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size) -{ - struct iovec iov; - iov.iov_base = buf; - iov.iov_len = buf_size; +Error NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, + void *buf, + size_t buf_size) { + struct iovec iov; + iov.iov_base = buf; + iov.iov_len = buf_size; - return ReadRegisterSet(&iov, buf_size, regset); + return ReadRegisterSet(&iov, buf_size, regset); } -Error -NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size) -{ - struct iovec iov; - iov.iov_base = const_cast<void *>(buf); - iov.iov_len = buf_size; +Error NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, + const void *buf, + size_t buf_size) { + struct iovec iov; + iov.iov_base = const_cast<void *>(buf); + iov.iov_len = buf_size; - return WriteRegisterSet(&iov, buf_size, regset); + return WriteRegisterSet(&iov, buf_size, regset); } -Error -NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, bool &is_hit) -{ - per_lowcore_bits per_lowcore; +Error NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, + bool &is_hit) { + per_lowcore_bits per_lowcore; - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); - - if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) - { - is_hit = false; - return Error(); - } - - Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); - if (error.Fail()) - { - is_hit = false; - return error; - } - - is_hit = (per_lowcore.perc_storage_alteration == 1 && per_lowcore.perc_store_real_address == 0); - - if (is_hit) - { - // Do not report this watchpoint again. - memset(&per_lowcore, 0, sizeof(per_lowcore)); - PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore)); - } + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); + if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) { + is_hit = false; return Error(); -} + } -Error -NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) -{ - uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); - for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) - { - bool is_hit; - Error error = IsWatchpointHit(wp_index, is_hit); - if (error.Fail()) - { - wp_index = LLDB_INVALID_INDEX32; - return error; - } - else if (is_hit) - { - return error; - } + Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), + &per_lowcore, sizeof(per_lowcore)); + if (error.Fail()) { + is_hit = false; + return error; + } + + is_hit = (per_lowcore.perc_storage_alteration == 1 && + per_lowcore.perc_store_real_address == 0); + + if (is_hit) { + // Do not report this watchpoint again. + memset(&per_lowcore, 0, sizeof(per_lowcore)); + PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, + sizeof(per_lowcore)); + } + + return Error(); +} + +Error NativeRegisterContextLinux_s390x::GetWatchpointHitIndex( + uint32_t &wp_index, lldb::addr_t trap_addr) { + uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); + for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { + bool is_hit; + Error error = IsWatchpointHit(wp_index, is_hit); + if (error.Fail()) { + wp_index = LLDB_INVALID_INDEX32; + return error; + } else if (is_hit) { + return error; } - wp_index = LLDB_INVALID_INDEX32; - return Error(); + } + wp_index = LLDB_INVALID_INDEX32; + return Error(); } -Error -NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return Error("Watchpoint index out of range"); +Error NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, + bool &is_vacant) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return Error("Watchpoint index out of range"); - is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; + is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; - return Error(); + return Error(); } -bool -NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(uint32_t wp_index) -{ - per_struct per_info; +bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint( + uint32_t wp_index) { + per_struct per_info; - if (wp_index >= NumSupportedHardwareWatchpoints()) - return false; + if (wp_index >= NumSupportedHardwareWatchpoints()) + return false; - Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return false; + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return false; - per_info.control_regs.bits.em_storage_alteration = 0; - per_info.control_regs.bits.storage_alt_space_ctl = 0; - per_info.starting_addr = 0; - per_info.ending_addr = 0; + per_info.control_regs.bits.em_storage_alteration = 0; + per_info.control_regs.bits.storage_alt_space_ctl = 0; + per_info.starting_addr = 0; + per_info.ending_addr = 0; - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return false; + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return false; - m_watchpoint_addr = LLDB_INVALID_ADDRESS; - return true; + m_watchpoint_addr = LLDB_INVALID_ADDRESS; + return true; } -Error -NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() -{ - if (ClearHardwareWatchpoint(0)) - return Error(); - return Error("Clearing all hardware watchpoints failed."); +Error NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() { + if (ClearHardwareWatchpoint(0)) + return Error(); + return Error("Clearing all hardware watchpoints failed."); } -uint32_t -NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) -{ - per_struct per_info; +uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint( + lldb::addr_t addr, size_t size, uint32_t watch_flags) { + per_struct per_info; - if (watch_flags != 0x1) - return LLDB_INVALID_INDEX32; + if (watch_flags != 0x1) + return LLDB_INVALID_INDEX32; - if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) - return LLDB_INVALID_INDEX32; + if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) + return LLDB_INVALID_INDEX32; - Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; + Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; - per_info.control_regs.bits.em_storage_alteration = 1; - per_info.control_regs.bits.storage_alt_space_ctl = 1; - per_info.starting_addr = addr; - per_info.ending_addr = addr + size - 1; + per_info.control_regs.bits.em_storage_alteration = 1; + per_info.control_regs.bits.storage_alt_space_ctl = 1; + per_info.starting_addr = addr; + per_info.ending_addr = addr + size - 1; - error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info)); - if (error.Fail()) - return LLDB_INVALID_INDEX32; + error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, + sizeof(per_info)); + if (error.Fail()) + return LLDB_INVALID_INDEX32; - m_watchpoint_addr = addr; - return 0; + m_watchpoint_addr = addr; + return 0; } lldb::addr_t -NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) -{ - if (wp_index >= NumSupportedHardwareWatchpoints()) - return LLDB_INVALID_ADDRESS; - return m_watchpoint_addr; +NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) { + if (wp_index >= NumSupportedHardwareWatchpoints()) + return LLDB_INVALID_ADDRESS; + return m_watchpoint_addr; } -uint32_t -NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() -{ - return 1; +uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() { + return 1; } #endif // defined(__s390x__) && defined(__linux__) |

