9#if defined(__s390x__) && defined(__linux__)
19#include <sys/ptrace.h>
43 k_num_gpr_registers_s390x,
44 "g_gpr_regnums_s390x has wrong number of register infos");
57 k_num_fpr_registers_s390x,
58 "g_fpu_regnums_s390x has wrong number of register infos");
61static const uint32_t g_linux_regnums_s390x[] = {
65static_assert((
sizeof(g_linux_regnums_s390x) /
66 sizeof(g_linux_regnums_s390x[0])) -
68 k_num_linux_registers_s390x,
69 "g_linux_regnums_s390x has wrong number of register infos");
81 g_linux_regnums_s390x},
85#define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4)
89#define NT_S390_LAST_BREAK 0x306
90#define NT_S390_SYSTEM_CALL 0x307
92std::unique_ptr<NativeRegisterContextLinux>
93NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
95 return std::make_unique<NativeRegisterContextLinux_s390x>(target_arch,
99llvm::Expected<ArchSpec>
100NativeRegisterContextLinux::DetermineArchitecture(
lldb::tid_t tid) {
101 return HostInfo::GetArchitecture();
107CreateRegisterInfoInterface(
const ArchSpec &target_arch) {
108 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
109 "Register setting path assumes this is a 64-bit host");
113NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(
116 native_thread, CreateRegisterInfoInterface(target_arch)),
120 case llvm::Triple::systemz:
129 assert(
false &&
"Unhandled target architecture.");
137uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount()
const {
140 if (IsRegisterSetAvailable(set_index))
147uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount()
const {
150 const RegisterSet *set = GetRegisterSet(set_index);
158NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index)
const {
159 if (!IsRegisterSetAvailable(set_index))
162 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
163 case llvm::Triple::systemz:
166 assert(
false &&
"Unhandled target architecture.");
173bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(
174 uint32_t set_index)
const {
178bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index)
const {
184bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index)
const {
185 return (m_reg_info.first_fpr <= reg_index &&
186 reg_index <= m_reg_info.last_fpr);
190NativeRegisterContextLinux_s390x::ReadRegister(
const RegisterInfo *reg_info,
193 return Status::FromErrorString(
"reg_info NULL");
197 return Status::FromErrorStringWithFormat(
198 "register \"%s\" is an internal-only lldb register, cannot "
207 uint8_t *src = (uint8_t *)&m_regs + reg_info->
byte_offset;
217 assert(
false &&
"Unhandled data size.");
218 return Status::FromErrorStringWithFormat(
"unhandled byte size: %" PRIu32,
230 uint8_t *src = (uint8_t *)&m_fp_regs + reg_info->
byte_offset;
240 assert(
false &&
"Unhandled data size.");
241 return Status::FromErrorStringWithFormat(
"unhandled byte size: %" PRIu32,
247 if (reg == lldb_last_break_s390x) {
249 Status error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8);
257 if (reg == lldb_system_call_s390x) {
258 uint32_t system_call;
259 Status error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
267 return Status::FromErrorString(
"failed - register wasn't recognized");
270Status NativeRegisterContextLinux_s390x::WriteRegister(
273 return Status::FromErrorString(
"reg_info NULL");
277 return Status::FromErrorStringWithFormat(
278 "register \"%s\" is an internal-only lldb register, cannot "
287 uint8_t *dst = (uint8_t *)&m_regs + reg_info->
byte_offset;
297 assert(
false &&
"Unhandled data size.");
298 return Status::FromErrorStringWithFormat(
"unhandled byte size: %" PRIu32,
310 uint8_t *dst = (uint8_t *)&m_fp_regs + reg_info->
byte_offset;
320 assert(
false &&
"Unhandled data size.");
321 return Status::FromErrorStringWithFormat(
"unhandled byte size: %" PRIu32,
327 if (reg == lldb_last_break_s390x) {
328 return Status::FromErrorString(
"The last break address is read-only");
331 if (reg == lldb_system_call_s390x) {
333 return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
336 return Status::FromErrorString(
"failed - register wasn't recognized");
339Status NativeRegisterContextLinux_s390x::ReadAllRegisterValues(
344 uint8_t *dst = data_sp->GetBytes();
348 memcpy(dst, GetGPRBuffer(), GetGPRSize());
354 memcpy(dst, GetFPRBuffer(), GetFPRSize());
358 DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4);
365 uint32_t system_call = 0;
366 DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
371Status NativeRegisterContextLinux_s390x::WriteAllRegisterValues(
376 error = Status::FromErrorStringWithFormat(
377 "NativeRegisterContextLinux_s390x::%s invalid data_sp provided",
383 error = Status::FromErrorStringWithFormat(
384 "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched "
385 "data size, expected %" PRIu64
", actual %" PRIu64,
390 const uint8_t *src = data_sp->GetBytes();
391 if (src ==
nullptr) {
392 error = Status::FromErrorStringWithFormat(
393 "NativeRegisterContextLinux_s390x::%s "
394 "DataBuffer::GetBytes() returned a null "
400 memcpy(GetGPRBuffer(), src, GetGPRSize());
406 memcpy(GetFPRBuffer(), src, GetFPRSize());
413 DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4);
419Status NativeRegisterContextLinux_s390x::DoReadRegisterValue(
420 uint32_t offset,
const char *reg_name, uint32_t size,
422 return Status::FromErrorString(
"DoReadRegisterValue unsupported");
425Status NativeRegisterContextLinux_s390x::DoWriteRegisterValue(
426 uint32_t offset,
const char *reg_name,
const RegisterValue &value) {
427 return Status::FromErrorString(
"DoWriteRegisterValue unsupported");
430Status NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset,
434 parea.len = buf_size;
435 parea.process_addr = (
addr_t)buf;
436 parea.kernel_addr = offset;
438 return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA,
439 m_thread.GetID(), &parea);
442Status NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset,
446 parea.len = buf_size;
447 parea.process_addr = (
addr_t)buf;
448 parea.kernel_addr = offset;
450 return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA,
451 m_thread.GetID(), &parea);
454Status NativeRegisterContextLinux_s390x::ReadGPR() {
455 return PeekUserArea(offsetof(user_regs_struct, psw), GetGPRBuffer(),
459Status NativeRegisterContextLinux_s390x::WriteGPR() {
460 return PokeUserArea(offsetof(user_regs_struct, psw), GetGPRBuffer(),
464Status NativeRegisterContextLinux_s390x::ReadFPR() {
465 return PeekUserArea(offsetof(user_regs_struct, fp_regs), GetGPRBuffer(),
469Status NativeRegisterContextLinux_s390x::WriteFPR() {
470 return PokeUserArea(offsetof(user_regs_struct, fp_regs), GetGPRBuffer(),
474Status NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset,
479 iov.iov_len = buf_size;
481 return ReadRegisterSet(&iov, buf_size, regset);
484Status NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset,
488 iov.iov_base =
const_cast<void *
>(buf);
489 iov.iov_len = buf_size;
491 return WriteRegisterSet(&iov, buf_size, regset);
494Status NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index,
496 per_lowcore_bits per_lowcore;
498 if (wp_index >= NumSupportedHardwareWatchpoints())
499 return Status::FromErrorString(
"Watchpoint index out of range");
506 Status error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore),
507 &per_lowcore,
sizeof(per_lowcore));
513 is_hit = (per_lowcore.perc_storage_alteration == 1 &&
514 per_lowcore.perc_store_real_address == 0);
518 memset(&per_lowcore, 0,
sizeof(per_lowcore));
519 PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore,
520 sizeof(per_lowcore));
526Status NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(
528 uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
529 for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) {
543Status NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index,
545 if (wp_index >= NumSupportedHardwareWatchpoints())
546 return Status::FromErrorString(
"Watchpoint index out of range");
553bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(
557 if (wp_index >= NumSupportedHardwareWatchpoints())
560 Status error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info,
565 per_info.control_regs.bits.em_storage_alteration = 0;
566 per_info.control_regs.bits.storage_alt_space_ctl = 0;
567 per_info.starting_addr = 0;
568 per_info.ending_addr = 0;
570 error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info,
579Status NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() {
580 if (ClearHardwareWatchpoint(0))
582 return Status::FromErrorString(
"Clearing all hardware watchpoints failed.");
585uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(
589 if (watch_flags != 0x1)
595 Status error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info,
600 per_info.control_regs.bits.em_storage_alteration = 1;
601 per_info.control_regs.bits.storage_alt_space_ctl = 1;
602 per_info.starting_addr = addr;
603 per_info.ending_addr = addr + size - 1;
605 error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info,
610 m_watchpoint_addr = addr;
615NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) {
616 if (wp_index >= NumSupportedHardwareWatchpoints())
618 return m_watchpoint_addr;
621uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() {
static llvm::raw_ostream & error(Stream &strm)
constexpr size_t k_num_register_sets
static const uint32_t g_gpr_regnums_s390x[]
static const uint32_t g_fpu_regnums_s390x[]
static const RegisterSet g_reg_sets_s390x[k_num_register_sets]
An architecture specification class.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
A subclass of DataBuffer that stores a data buffer on the heap.
RegisterInfo interface to patch RegisterInfo structure for archs.
void SetUInt64(uint64_t uint, Type t=eTypeUInt64)
uint64_t GetAsUInt64(uint64_t fail_value=UINT64_MAX, bool *success_ptr=nullptr) const
uint32_t GetAsUInt32(uint32_t fail_value=UINT32_MAX, bool *success_ptr=nullptr) const
void SetUInt32(uint32_t uint, Type t=eTypeUInt32)
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
#define LLDB_INVALID_REGNUM
A class that represents a running process on the host machine.
@ k_num_gpr_registers_s390x
@ k_num_fpr_registers_s390x
@ k_num_linux_registers_s390x
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
std::shared_ptr< lldb_private::WritableDataBuffer > WritableDataBufferSP
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const char * name
Name of this register, can't be NULL.
Registers are grouped into register sets.
size_t num_registers
The number of registers in REGISTERS array below.