summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp1050
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 &reg_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(&regs, sizeof(regs));
- if (error.Fail())
- return error;
-
- uint8_t *src = (uint8_t *)&regs + 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 &reg_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(&regs, sizeof(regs));
+ if (error.Fail())
+ return error;
+
+ uint8_t *src = (uint8_t *)&regs + 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 &reg_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(&regs, sizeof(regs));
- if (error.Fail())
- return error;
-
- uint8_t *dst = (uint8_t *)&regs + 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(&regs, 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 &reg_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(&regs, sizeof(regs));
+ if (error.Fail())
+ return error;
+
+ uint8_t *dst = (uint8_t *)&regs + 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(&regs, 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__)
OpenPOWER on IntegriCloud