1bb00d0b6SUlrich Weigand //===-- NativeRegisterContextLinux_s390x.cpp --------------------*- C++ -*-===// 2bb00d0b6SUlrich Weigand // 3bb00d0b6SUlrich Weigand // The LLVM Compiler Infrastructure 4bb00d0b6SUlrich Weigand // 5bb00d0b6SUlrich Weigand // This file is distributed under the University of Illinois Open Source 6bb00d0b6SUlrich Weigand // License. See LICENSE.TXT for details. 7bb00d0b6SUlrich Weigand // 8bb00d0b6SUlrich Weigand //===----------------------------------------------------------------------===// 9bb00d0b6SUlrich Weigand 10bb00d0b6SUlrich Weigand #if defined(__s390x__) && defined(__linux__) 11bb00d0b6SUlrich Weigand 12bb00d0b6SUlrich Weigand #include "NativeRegisterContextLinux_s390x.h" 13bb00d0b6SUlrich Weigand 14bb00d0b6SUlrich Weigand #include "lldb/Core/DataBufferHeap.h" 15bb00d0b6SUlrich Weigand #include "lldb/Core/Error.h" 16bb00d0b6SUlrich Weigand #include "lldb/Core/Log.h" 17bb00d0b6SUlrich Weigand #include "lldb/Core/RegisterValue.h" 18bb00d0b6SUlrich Weigand #include "lldb/Host/HostInfo.h" 19bb00d0b6SUlrich Weigand 20bb00d0b6SUlrich Weigand #include "Plugins/Process/Utility/RegisterContextLinux_s390x.h" 21bb00d0b6SUlrich Weigand 22bb00d0b6SUlrich Weigand #include <asm/ptrace.h> 23bb00d0b6SUlrich Weigand #include <linux/uio.h> 24bb00d0b6SUlrich Weigand #include <sys/ptrace.h> 25bb00d0b6SUlrich Weigand 26bb00d0b6SUlrich Weigand using namespace lldb_private; 27bb00d0b6SUlrich Weigand using namespace lldb_private::process_linux; 28bb00d0b6SUlrich Weigand 29bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 30bb00d0b6SUlrich Weigand // Private namespace. 31bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 32bb00d0b6SUlrich Weigand 33b9c1b51eSKate Stone namespace { 34bb00d0b6SUlrich Weigand // s390x 64-bit general purpose registers. 35b9c1b51eSKate Stone static const uint32_t g_gpr_regnums_s390x[] = { 36b9c1b51eSKate Stone lldb_r0_s390x, lldb_r1_s390x, lldb_r2_s390x, lldb_r3_s390x, 37b9c1b51eSKate Stone lldb_r4_s390x, lldb_r5_s390x, lldb_r6_s390x, lldb_r7_s390x, 38b9c1b51eSKate Stone lldb_r8_s390x, lldb_r9_s390x, lldb_r10_s390x, lldb_r11_s390x, 39b9c1b51eSKate Stone lldb_r12_s390x, lldb_r13_s390x, lldb_r14_s390x, lldb_r15_s390x, 40b9c1b51eSKate Stone lldb_acr0_s390x, lldb_acr1_s390x, lldb_acr2_s390x, lldb_acr3_s390x, 41b9c1b51eSKate Stone lldb_acr4_s390x, lldb_acr5_s390x, lldb_acr6_s390x, lldb_acr7_s390x, 42b9c1b51eSKate Stone lldb_acr8_s390x, lldb_acr9_s390x, lldb_acr10_s390x, lldb_acr11_s390x, 43b9c1b51eSKate Stone lldb_acr12_s390x, lldb_acr13_s390x, lldb_acr14_s390x, lldb_acr15_s390x, 44b9c1b51eSKate Stone lldb_pswm_s390x, lldb_pswa_s390x, 45bb00d0b6SUlrich Weigand LLDB_INVALID_REGNUM // register sets need to end with this flag 46bb00d0b6SUlrich Weigand }; 47b9c1b51eSKate Stone static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 48b9c1b51eSKate Stone 1 == 49b9c1b51eSKate Stone k_num_gpr_registers_s390x, 50bb00d0b6SUlrich Weigand "g_gpr_regnums_s390x has wrong number of register infos"); 51bb00d0b6SUlrich Weigand 52bb00d0b6SUlrich Weigand // s390x 64-bit floating point registers. 53b9c1b51eSKate Stone static const uint32_t g_fpu_regnums_s390x[] = { 54b9c1b51eSKate Stone lldb_f0_s390x, lldb_f1_s390x, lldb_f2_s390x, lldb_f3_s390x, 55b9c1b51eSKate Stone lldb_f4_s390x, lldb_f5_s390x, lldb_f6_s390x, lldb_f7_s390x, 56b9c1b51eSKate Stone lldb_f8_s390x, lldb_f9_s390x, lldb_f10_s390x, lldb_f11_s390x, 57b9c1b51eSKate Stone lldb_f12_s390x, lldb_f13_s390x, lldb_f14_s390x, lldb_f15_s390x, 58bb00d0b6SUlrich Weigand lldb_fpc_s390x, 59bb00d0b6SUlrich Weigand LLDB_INVALID_REGNUM // register sets need to end with this flag 60bb00d0b6SUlrich Weigand }; 61b9c1b51eSKate Stone static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 62b9c1b51eSKate Stone 1 == 63b9c1b51eSKate Stone k_num_fpr_registers_s390x, 64bb00d0b6SUlrich Weigand "g_fpu_regnums_s390x has wrong number of register infos"); 65bb00d0b6SUlrich Weigand 66bb00d0b6SUlrich Weigand // s390x Linux operating-system information. 67b9c1b51eSKate Stone static const uint32_t g_linux_regnums_s390x[] = { 68b9c1b51eSKate Stone lldb_orig_r2_s390x, lldb_last_break_s390x, lldb_system_call_s390x, 69bb00d0b6SUlrich Weigand LLDB_INVALID_REGNUM // register sets need to end with this flag 70bb00d0b6SUlrich Weigand }; 71b9c1b51eSKate Stone static_assert((sizeof(g_linux_regnums_s390x) / 72b9c1b51eSKate Stone sizeof(g_linux_regnums_s390x[0])) - 73b9c1b51eSKate Stone 1 == 74b9c1b51eSKate Stone k_num_linux_registers_s390x, 75bb00d0b6SUlrich Weigand "g_linux_regnums_s390x has wrong number of register infos"); 76bb00d0b6SUlrich Weigand 77bb00d0b6SUlrich Weigand // Number of register sets provided by this context. 78b9c1b51eSKate Stone enum { k_num_register_sets = 3 }; 79bb00d0b6SUlrich Weigand 80bb00d0b6SUlrich Weigand // Register sets for s390x 64-bit. 81b9c1b51eSKate Stone static const RegisterSet g_reg_sets_s390x[k_num_register_sets] = { 82b9c1b51eSKate Stone {"General Purpose Registers", "gpr", k_num_gpr_registers_s390x, 83b9c1b51eSKate Stone g_gpr_regnums_s390x}, 84b9c1b51eSKate Stone {"Floating Point Registers", "fpr", k_num_fpr_registers_s390x, 85b9c1b51eSKate Stone g_fpu_regnums_s390x}, 86b9c1b51eSKate Stone {"Linux Operating System Data", "linux", k_num_linux_registers_s390x, 87b9c1b51eSKate Stone g_linux_regnums_s390x}, 88bb00d0b6SUlrich Weigand }; 89bb00d0b6SUlrich Weigand } 90bb00d0b6SUlrich Weigand 91bb00d0b6SUlrich Weigand #define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4) 92bb00d0b6SUlrich Weigand 93bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 94bb00d0b6SUlrich Weigand // Required ptrace defines. 95bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 96bb00d0b6SUlrich Weigand 97bb00d0b6SUlrich Weigand #define NT_S390_LAST_BREAK 0x306 /* s390 breaking event address */ 98bb00d0b6SUlrich Weigand #define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */ 99bb00d0b6SUlrich Weigand 100bb00d0b6SUlrich Weigand NativeRegisterContextLinux * 101b9c1b51eSKate Stone NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux( 102b9c1b51eSKate Stone const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 103b9c1b51eSKate Stone uint32_t concrete_frame_idx) { 104b9c1b51eSKate Stone return new NativeRegisterContextLinux_s390x(target_arch, native_thread, 105b9c1b51eSKate Stone concrete_frame_idx); 106bb00d0b6SUlrich Weigand } 107bb00d0b6SUlrich Weigand 108bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 109bb00d0b6SUlrich Weigand // NativeRegisterContextLinux_s390x members. 110bb00d0b6SUlrich Weigand // ---------------------------------------------------------------------------- 111bb00d0b6SUlrich Weigand 112bb00d0b6SUlrich Weigand static RegisterInfoInterface * 113b9c1b51eSKate Stone CreateRegisterInfoInterface(const ArchSpec &target_arch) { 114bb00d0b6SUlrich Weigand assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && 115bb00d0b6SUlrich Weigand "Register setting path assumes this is a 64-bit host"); 116bb00d0b6SUlrich Weigand return new RegisterContextLinux_s390x(target_arch); 117bb00d0b6SUlrich Weigand } 118bb00d0b6SUlrich Weigand 119b9c1b51eSKate Stone NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x( 120b9c1b51eSKate Stone const ArchSpec &target_arch, NativeThreadProtocol &native_thread, 121bb00d0b6SUlrich Weigand uint32_t concrete_frame_idx) 122b9c1b51eSKate Stone : NativeRegisterContextLinux(native_thread, concrete_frame_idx, 123b9c1b51eSKate Stone CreateRegisterInfoInterface(target_arch)) { 124bb00d0b6SUlrich Weigand // Set up data about ranges of valid registers. 125b9c1b51eSKate Stone switch (target_arch.GetMachine()) { 126bb00d0b6SUlrich Weigand case llvm::Triple::systemz: 127bb00d0b6SUlrich Weigand m_reg_info.num_registers = k_num_registers_s390x; 128bb00d0b6SUlrich Weigand m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x; 129bb00d0b6SUlrich Weigand m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x; 130bb00d0b6SUlrich Weigand m_reg_info.last_gpr = k_last_gpr_s390x; 131bb00d0b6SUlrich Weigand m_reg_info.first_fpr = k_first_fpr_s390x; 132bb00d0b6SUlrich Weigand m_reg_info.last_fpr = k_last_fpr_s390x; 133bb00d0b6SUlrich Weigand break; 134bb00d0b6SUlrich Weigand default: 135bb00d0b6SUlrich Weigand assert(false && "Unhandled target architecture."); 136bb00d0b6SUlrich Weigand break; 137bb00d0b6SUlrich Weigand } 138bb00d0b6SUlrich Weigand 139bb00d0b6SUlrich Weigand // Clear out the watchpoint state. 140bb00d0b6SUlrich Weigand m_watchpoint_addr = LLDB_INVALID_ADDRESS; 141bb00d0b6SUlrich Weigand } 142bb00d0b6SUlrich Weigand 143b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_s390x::GetRegisterSetCount() const { 144bb00d0b6SUlrich Weigand uint32_t sets = 0; 145b9c1b51eSKate Stone for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { 146bb00d0b6SUlrich Weigand if (IsRegisterSetAvailable(set_index)) 147bb00d0b6SUlrich Weigand ++sets; 148bb00d0b6SUlrich Weigand } 149bb00d0b6SUlrich Weigand 150bb00d0b6SUlrich Weigand return sets; 151bb00d0b6SUlrich Weigand } 152bb00d0b6SUlrich Weigand 153b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_s390x::GetUserRegisterCount() const { 154bb00d0b6SUlrich Weigand uint32_t count = 0; 155b9c1b51eSKate Stone for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) { 156bb00d0b6SUlrich Weigand const RegisterSet *set = GetRegisterSet(set_index); 157bb00d0b6SUlrich Weigand if (set) 158bb00d0b6SUlrich Weigand count += set->num_registers; 159bb00d0b6SUlrich Weigand } 160bb00d0b6SUlrich Weigand return count; 161bb00d0b6SUlrich Weigand } 162bb00d0b6SUlrich Weigand 163bb00d0b6SUlrich Weigand const RegisterSet * 164b9c1b51eSKate Stone NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const { 165bb00d0b6SUlrich Weigand if (!IsRegisterSetAvailable(set_index)) 166bb00d0b6SUlrich Weigand return nullptr; 167bb00d0b6SUlrich Weigand 168b9c1b51eSKate Stone switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 169bb00d0b6SUlrich Weigand case llvm::Triple::systemz: 170bb00d0b6SUlrich Weigand return &g_reg_sets_s390x[set_index]; 171bb00d0b6SUlrich Weigand default: 172bb00d0b6SUlrich Weigand assert(false && "Unhandled target architecture."); 173bb00d0b6SUlrich Weigand return nullptr; 174bb00d0b6SUlrich Weigand } 175bb00d0b6SUlrich Weigand 176bb00d0b6SUlrich Weigand return nullptr; 177bb00d0b6SUlrich Weigand } 178bb00d0b6SUlrich Weigand 179b9c1b51eSKate Stone bool NativeRegisterContextLinux_s390x::IsRegisterSetAvailable( 180b9c1b51eSKate Stone uint32_t set_index) const { 181bb00d0b6SUlrich Weigand return set_index < k_num_register_sets; 182bb00d0b6SUlrich Weigand } 183bb00d0b6SUlrich Weigand 184b9c1b51eSKate Stone bool NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const { 185b9c1b51eSKate Stone // GPRs come first. "orig_r2" counts as GPR since it is part of the GPR 186b9c1b51eSKate Stone // register area. 187bb00d0b6SUlrich Weigand return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x; 188bb00d0b6SUlrich Weigand } 189bb00d0b6SUlrich Weigand 190b9c1b51eSKate Stone bool NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const { 191b9c1b51eSKate Stone return (m_reg_info.first_fpr <= reg_index && 192b9c1b51eSKate Stone reg_index <= m_reg_info.last_fpr); 193bb00d0b6SUlrich Weigand } 194bb00d0b6SUlrich Weigand 195b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::ReadRegister( 196b9c1b51eSKate Stone const RegisterInfo *reg_info, RegisterValue ®_value) { 197bb00d0b6SUlrich Weigand if (!reg_info) 198bb00d0b6SUlrich Weigand return Error("reg_info NULL"); 199bb00d0b6SUlrich Weigand 200bb00d0b6SUlrich Weigand const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 201bb00d0b6SUlrich Weigand if (reg == LLDB_INVALID_REGNUM) 202b9c1b51eSKate Stone return Error("register \"%s\" is an internal-only lldb register, cannot " 203b9c1b51eSKate Stone "read directly", 204b9c1b51eSKate Stone reg_info->name); 205bb00d0b6SUlrich Weigand 206b9c1b51eSKate Stone if (IsGPR(reg)) { 207bb00d0b6SUlrich Weigand s390_regs regs; 208bb00d0b6SUlrich Weigand Error error = DoReadGPR(®s, sizeof(regs)); 209bb00d0b6SUlrich Weigand if (error.Fail()) 210bb00d0b6SUlrich Weigand return error; 211bb00d0b6SUlrich Weigand 212bb00d0b6SUlrich Weigand uint8_t *src = (uint8_t *)®s + reg_info->byte_offset; 213bb00d0b6SUlrich Weigand assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); 214b9c1b51eSKate Stone switch (reg_info->byte_size) { 215bb00d0b6SUlrich Weigand case 4: 216bb00d0b6SUlrich Weigand reg_value.SetUInt32(*(uint32_t *)src); 217bb00d0b6SUlrich Weigand break; 218bb00d0b6SUlrich Weigand case 8: 219bb00d0b6SUlrich Weigand reg_value.SetUInt64(*(uint64_t *)src); 220bb00d0b6SUlrich Weigand break; 221bb00d0b6SUlrich Weigand default: 222bb00d0b6SUlrich Weigand assert(false && "Unhandled data size."); 223bb00d0b6SUlrich Weigand return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); 224bb00d0b6SUlrich Weigand } 225*665be50eSMehdi Amini return Error(); 226bb00d0b6SUlrich Weigand } 227bb00d0b6SUlrich Weigand 228b9c1b51eSKate Stone if (IsFPR(reg)) { 229bb00d0b6SUlrich Weigand s390_fp_regs fp_regs; 230bb00d0b6SUlrich Weigand Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); 231bb00d0b6SUlrich Weigand if (error.Fail()) 232bb00d0b6SUlrich Weigand return error; 233bb00d0b6SUlrich Weigand 234bb00d0b6SUlrich Weigand // byte_offset is just the offset within FPR, not the whole user area. 235bb00d0b6SUlrich Weigand uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset; 236bb00d0b6SUlrich Weigand assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); 237b9c1b51eSKate Stone switch (reg_info->byte_size) { 238bb00d0b6SUlrich Weigand case 4: 239bb00d0b6SUlrich Weigand reg_value.SetUInt32(*(uint32_t *)src); 240bb00d0b6SUlrich Weigand break; 241bb00d0b6SUlrich Weigand case 8: 242bb00d0b6SUlrich Weigand reg_value.SetUInt64(*(uint64_t *)src); 243bb00d0b6SUlrich Weigand break; 244bb00d0b6SUlrich Weigand default: 245bb00d0b6SUlrich Weigand assert(false && "Unhandled data size."); 246bb00d0b6SUlrich Weigand return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); 247bb00d0b6SUlrich Weigand } 248*665be50eSMehdi Amini return Error(); 249bb00d0b6SUlrich Weigand } 250bb00d0b6SUlrich Weigand 251b9c1b51eSKate Stone if (reg == lldb_last_break_s390x) { 252bb00d0b6SUlrich Weigand uint64_t last_break; 253bb00d0b6SUlrich Weigand Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8); 254bb00d0b6SUlrich Weigand if (error.Fail()) 255bb00d0b6SUlrich Weigand return error; 256bb00d0b6SUlrich Weigand 257bb00d0b6SUlrich Weigand reg_value.SetUInt64(last_break); 258*665be50eSMehdi Amini return Error(); 259bb00d0b6SUlrich Weigand } 260bb00d0b6SUlrich Weigand 261b9c1b51eSKate Stone if (reg == lldb_system_call_s390x) { 262bb00d0b6SUlrich Weigand uint32_t system_call; 263bb00d0b6SUlrich Weigand Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); 264bb00d0b6SUlrich Weigand if (error.Fail()) 265bb00d0b6SUlrich Weigand return error; 266bb00d0b6SUlrich Weigand 267bb00d0b6SUlrich Weigand reg_value.SetUInt32(system_call); 268*665be50eSMehdi Amini return Error(); 269bb00d0b6SUlrich Weigand } 270bb00d0b6SUlrich Weigand 271bb00d0b6SUlrich Weigand return Error("failed - register wasn't recognized"); 272bb00d0b6SUlrich Weigand } 273bb00d0b6SUlrich Weigand 274b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::WriteRegister( 275b9c1b51eSKate Stone const RegisterInfo *reg_info, const RegisterValue ®_value) { 276bb00d0b6SUlrich Weigand if (!reg_info) 277bb00d0b6SUlrich Weigand return Error("reg_info NULL"); 278bb00d0b6SUlrich Weigand 279bb00d0b6SUlrich Weigand const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 280bb00d0b6SUlrich Weigand if (reg == LLDB_INVALID_REGNUM) 281b9c1b51eSKate Stone return Error("register \"%s\" is an internal-only lldb register, cannot " 282b9c1b51eSKate Stone "write directly", 283b9c1b51eSKate Stone reg_info->name); 284bb00d0b6SUlrich Weigand 285b9c1b51eSKate Stone if (IsGPR(reg)) { 286bb00d0b6SUlrich Weigand s390_regs regs; 287bb00d0b6SUlrich Weigand Error error = DoReadGPR(®s, sizeof(regs)); 288bb00d0b6SUlrich Weigand if (error.Fail()) 289bb00d0b6SUlrich Weigand return error; 290bb00d0b6SUlrich Weigand 291bb00d0b6SUlrich Weigand uint8_t *dst = (uint8_t *)®s + reg_info->byte_offset; 292bb00d0b6SUlrich Weigand assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs)); 293b9c1b51eSKate Stone switch (reg_info->byte_size) { 294bb00d0b6SUlrich Weigand case 4: 295bb00d0b6SUlrich Weigand *(uint32_t *)dst = reg_value.GetAsUInt32(); 296bb00d0b6SUlrich Weigand break; 297bb00d0b6SUlrich Weigand case 8: 298bb00d0b6SUlrich Weigand *(uint64_t *)dst = reg_value.GetAsUInt64(); 299bb00d0b6SUlrich Weigand break; 300bb00d0b6SUlrich Weigand default: 301bb00d0b6SUlrich Weigand assert(false && "Unhandled data size."); 302bb00d0b6SUlrich Weigand return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); 303bb00d0b6SUlrich Weigand } 304bb00d0b6SUlrich Weigand return DoWriteGPR(®s, sizeof(regs)); 305bb00d0b6SUlrich Weigand } 306bb00d0b6SUlrich Weigand 307b9c1b51eSKate Stone if (IsFPR(reg)) { 308bb00d0b6SUlrich Weigand s390_fp_regs fp_regs; 309bb00d0b6SUlrich Weigand Error error = DoReadFPR(&fp_regs, sizeof(fp_regs)); 310bb00d0b6SUlrich Weigand if (error.Fail()) 311bb00d0b6SUlrich Weigand return error; 312bb00d0b6SUlrich Weigand 313bb00d0b6SUlrich Weigand // byte_offset is just the offset within fp_regs, not the whole user area. 314bb00d0b6SUlrich Weigand uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset; 315bb00d0b6SUlrich Weigand assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs)); 316b9c1b51eSKate Stone switch (reg_info->byte_size) { 317bb00d0b6SUlrich Weigand case 4: 318bb00d0b6SUlrich Weigand *(uint32_t *)dst = reg_value.GetAsUInt32(); 319bb00d0b6SUlrich Weigand break; 320bb00d0b6SUlrich Weigand case 8: 321bb00d0b6SUlrich Weigand *(uint64_t *)dst = reg_value.GetAsUInt64(); 322bb00d0b6SUlrich Weigand break; 323bb00d0b6SUlrich Weigand default: 324bb00d0b6SUlrich Weigand assert(false && "Unhandled data size."); 325bb00d0b6SUlrich Weigand return Error("unhandled byte size: %" PRIu32, reg_info->byte_size); 326bb00d0b6SUlrich Weigand } 327bb00d0b6SUlrich Weigand return DoWriteFPR(&fp_regs, sizeof(fp_regs)); 328bb00d0b6SUlrich Weigand } 329bb00d0b6SUlrich Weigand 330b9c1b51eSKate Stone if (reg == lldb_last_break_s390x) { 331bb00d0b6SUlrich Weigand return Error("The last break address is read-only"); 332bb00d0b6SUlrich Weigand } 333bb00d0b6SUlrich Weigand 334b9c1b51eSKate Stone if (reg == lldb_system_call_s390x) { 335bb00d0b6SUlrich Weigand uint32_t system_call = reg_value.GetAsUInt32(); 336bb00d0b6SUlrich Weigand return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); 337bb00d0b6SUlrich Weigand } 338bb00d0b6SUlrich Weigand 339bb00d0b6SUlrich Weigand return Error("failed - register wasn't recognized"); 340bb00d0b6SUlrich Weigand } 341bb00d0b6SUlrich Weigand 342b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::ReadAllRegisterValues( 343b9c1b51eSKate Stone lldb::DataBufferSP &data_sp) { 344bb00d0b6SUlrich Weigand Error error; 345bb00d0b6SUlrich Weigand 346bb00d0b6SUlrich Weigand data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0)); 347b9c1b51eSKate Stone if (!data_sp) { 348b9c1b51eSKate Stone error.SetErrorStringWithFormat( 349b9c1b51eSKate Stone "failed to allocate DataBufferHeap instance of size %" PRIu64, 350b9c1b51eSKate Stone REG_CONTEXT_SIZE); 351bb00d0b6SUlrich Weigand return error; 352bb00d0b6SUlrich Weigand } 353bb00d0b6SUlrich Weigand 354bb00d0b6SUlrich Weigand uint8_t *dst = data_sp->GetBytes(); 355b9c1b51eSKate Stone if (dst == nullptr) { 356b9c1b51eSKate Stone error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 357b9c1b51eSKate Stone " returned a null pointer", 358bb00d0b6SUlrich Weigand REG_CONTEXT_SIZE); 359bb00d0b6SUlrich Weigand return error; 360bb00d0b6SUlrich Weigand } 361bb00d0b6SUlrich Weigand 362bb00d0b6SUlrich Weigand error = DoReadGPR(dst, sizeof(s390_regs)); 363bb00d0b6SUlrich Weigand dst += sizeof(s390_regs); 364bb00d0b6SUlrich Weigand if (error.Fail()) 365bb00d0b6SUlrich Weigand return error; 366bb00d0b6SUlrich Weigand 367bb00d0b6SUlrich Weigand error = DoReadFPR(dst, sizeof(s390_fp_regs)); 368bb00d0b6SUlrich Weigand dst += sizeof(s390_fp_regs); 369bb00d0b6SUlrich Weigand if (error.Fail()) 370bb00d0b6SUlrich Weigand return error; 371bb00d0b6SUlrich Weigand 372bb00d0b6SUlrich Weigand // Ignore errors if the regset is unsupported (happens on older kernels). 373bb00d0b6SUlrich Weigand DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4); 374bb00d0b6SUlrich Weigand dst += 4; 375bb00d0b6SUlrich Weigand 376bb00d0b6SUlrich Weigand // To enable inferior function calls while the process is stopped in 377bb00d0b6SUlrich Weigand // an interrupted system call, we need to clear the system call flag. 378bb00d0b6SUlrich Weigand // It will be restored to its original value by WriteAllRegisterValues. 379bb00d0b6SUlrich Weigand // Again we ignore error if the regset is unsupported. 380bb00d0b6SUlrich Weigand uint32_t system_call = 0; 381bb00d0b6SUlrich Weigand DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4); 382bb00d0b6SUlrich Weigand 383bb00d0b6SUlrich Weigand return error; 384bb00d0b6SUlrich Weigand } 385bb00d0b6SUlrich Weigand 386b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::WriteAllRegisterValues( 387b9c1b51eSKate Stone const lldb::DataBufferSP &data_sp) { 388bb00d0b6SUlrich Weigand Error error; 389bb00d0b6SUlrich Weigand 390b9c1b51eSKate Stone if (!data_sp) { 391b9c1b51eSKate Stone error.SetErrorStringWithFormat( 392b9c1b51eSKate Stone "NativeRegisterContextLinux_s390x::%s invalid data_sp provided", 393b9c1b51eSKate Stone __FUNCTION__); 394bb00d0b6SUlrich Weigand return error; 395bb00d0b6SUlrich Weigand } 396bb00d0b6SUlrich Weigand 397b9c1b51eSKate Stone if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) { 398bb00d0b6SUlrich Weigand error.SetErrorStringWithFormat( 399b9c1b51eSKate Stone "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched " 400b9c1b51eSKate Stone "data size, expected %" PRIu64 ", actual %" PRIu64, 401bb00d0b6SUlrich Weigand __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize()); 402bb00d0b6SUlrich Weigand return error; 403bb00d0b6SUlrich Weigand } 404bb00d0b6SUlrich Weigand 405bb00d0b6SUlrich Weigand uint8_t *src = data_sp->GetBytes(); 406b9c1b51eSKate Stone if (src == nullptr) { 407b9c1b51eSKate Stone error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s " 408b9c1b51eSKate Stone "DataBuffer::GetBytes() returned a null " 409b9c1b51eSKate Stone "pointer", 410b9c1b51eSKate Stone __FUNCTION__); 411bb00d0b6SUlrich Weigand return error; 412bb00d0b6SUlrich Weigand } 413bb00d0b6SUlrich Weigand 414bb00d0b6SUlrich Weigand error = DoWriteGPR(src, sizeof(s390_regs)); 415bb00d0b6SUlrich Weigand src += sizeof(s390_regs); 416bb00d0b6SUlrich Weigand if (error.Fail()) 417bb00d0b6SUlrich Weigand return error; 418bb00d0b6SUlrich Weigand 419bb00d0b6SUlrich Weigand error = DoWriteFPR(src, sizeof(s390_fp_regs)); 420bb00d0b6SUlrich Weigand src += sizeof(s390_fp_regs); 421bb00d0b6SUlrich Weigand if (error.Fail()) 422bb00d0b6SUlrich Weigand return error; 423bb00d0b6SUlrich Weigand 424bb00d0b6SUlrich Weigand // Ignore errors if the regset is unsupported (happens on older kernels). 425bb00d0b6SUlrich Weigand DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4); 426bb00d0b6SUlrich Weigand src += 4; 427bb00d0b6SUlrich Weigand 428bb00d0b6SUlrich Weigand return error; 429bb00d0b6SUlrich Weigand } 430bb00d0b6SUlrich Weigand 431b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoReadRegisterValue( 432b9c1b51eSKate Stone uint32_t offset, const char *reg_name, uint32_t size, 433b9c1b51eSKate Stone RegisterValue &value) { 434bb00d0b6SUlrich Weigand return Error("DoReadRegisterValue unsupported"); 435bb00d0b6SUlrich Weigand } 436bb00d0b6SUlrich Weigand 437b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoWriteRegisterValue( 438b9c1b51eSKate Stone uint32_t offset, const char *reg_name, const RegisterValue &value) { 439bb00d0b6SUlrich Weigand return Error("DoWriteRegisterValue unsupported"); 440bb00d0b6SUlrich Weigand } 441bb00d0b6SUlrich Weigand 442b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, 443b9c1b51eSKate Stone size_t buf_size) { 444bb00d0b6SUlrich Weigand ptrace_area parea; 445bb00d0b6SUlrich Weigand parea.len = buf_size; 446bb00d0b6SUlrich Weigand parea.process_addr = (addr_t)buf; 447bb00d0b6SUlrich Weigand parea.kernel_addr = offset; 448bb00d0b6SUlrich Weigand 449b9c1b51eSKate Stone return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, 450b9c1b51eSKate Stone m_thread.GetID(), &parea); 451bb00d0b6SUlrich Weigand } 452bb00d0b6SUlrich Weigand 453b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, 454b9c1b51eSKate Stone const void *buf, 455b9c1b51eSKate Stone size_t buf_size) { 456bb00d0b6SUlrich Weigand ptrace_area parea; 457bb00d0b6SUlrich Weigand parea.len = buf_size; 458bb00d0b6SUlrich Weigand parea.process_addr = (addr_t)buf; 459bb00d0b6SUlrich Weigand parea.kernel_addr = offset; 460bb00d0b6SUlrich Weigand 461b9c1b51eSKate Stone return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, 462b9c1b51eSKate Stone m_thread.GetID(), &parea); 463bb00d0b6SUlrich Weigand } 464bb00d0b6SUlrich Weigand 465b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size) { 466bb00d0b6SUlrich Weigand assert(buf_size == sizeof(s390_regs)); 467bb00d0b6SUlrich Weigand return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size); 468bb00d0b6SUlrich Weigand } 469bb00d0b6SUlrich Weigand 470b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size) { 471bb00d0b6SUlrich Weigand assert(buf_size == sizeof(s390_regs)); 472bb00d0b6SUlrich Weigand return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size); 473bb00d0b6SUlrich Weigand } 474bb00d0b6SUlrich Weigand 475b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size) { 476bb00d0b6SUlrich Weigand assert(buf_size == sizeof(s390_fp_regs)); 477bb00d0b6SUlrich Weigand return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); 478bb00d0b6SUlrich Weigand } 479bb00d0b6SUlrich Weigand 480b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size) { 481bb00d0b6SUlrich Weigand assert(buf_size == sizeof(s390_fp_regs)); 482bb00d0b6SUlrich Weigand return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size); 483bb00d0b6SUlrich Weigand } 484bb00d0b6SUlrich Weigand 485b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, 486b9c1b51eSKate Stone void *buf, 487b9c1b51eSKate Stone size_t buf_size) { 488bb00d0b6SUlrich Weigand struct iovec iov; 489bb00d0b6SUlrich Weigand iov.iov_base = buf; 490bb00d0b6SUlrich Weigand iov.iov_len = buf_size; 491bb00d0b6SUlrich Weigand 492bb00d0b6SUlrich Weigand return ReadRegisterSet(&iov, buf_size, regset); 493bb00d0b6SUlrich Weigand } 494bb00d0b6SUlrich Weigand 495b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, 496b9c1b51eSKate Stone const void *buf, 497b9c1b51eSKate Stone size_t buf_size) { 498bb00d0b6SUlrich Weigand struct iovec iov; 499bb00d0b6SUlrich Weigand iov.iov_base = const_cast<void *>(buf); 500bb00d0b6SUlrich Weigand iov.iov_len = buf_size; 501bb00d0b6SUlrich Weigand 502bb00d0b6SUlrich Weigand return WriteRegisterSet(&iov, buf_size, regset); 503bb00d0b6SUlrich Weigand } 504bb00d0b6SUlrich Weigand 505b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, 506b9c1b51eSKate Stone bool &is_hit) { 507bb00d0b6SUlrich Weigand per_lowcore_bits per_lowcore; 508bb00d0b6SUlrich Weigand 509bb00d0b6SUlrich Weigand if (wp_index >= NumSupportedHardwareWatchpoints()) 510bb00d0b6SUlrich Weigand return Error("Watchpoint index out of range"); 511bb00d0b6SUlrich Weigand 512b9c1b51eSKate Stone if (m_watchpoint_addr == LLDB_INVALID_ADDRESS) { 513bb00d0b6SUlrich Weigand is_hit = false; 514*665be50eSMehdi Amini return Error(); 515bb00d0b6SUlrich Weigand } 516bb00d0b6SUlrich Weigand 517b9c1b51eSKate Stone Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), 518b9c1b51eSKate Stone &per_lowcore, sizeof(per_lowcore)); 519b9c1b51eSKate Stone if (error.Fail()) { 520bb00d0b6SUlrich Weigand is_hit = false; 521bb00d0b6SUlrich Weigand return error; 522bb00d0b6SUlrich Weigand } 523bb00d0b6SUlrich Weigand 524b9c1b51eSKate Stone is_hit = (per_lowcore.perc_storage_alteration == 1 && 525b9c1b51eSKate Stone per_lowcore.perc_store_real_address == 0); 526bb00d0b6SUlrich Weigand 527b9c1b51eSKate Stone if (is_hit) { 528bb00d0b6SUlrich Weigand // Do not report this watchpoint again. 529bb00d0b6SUlrich Weigand memset(&per_lowcore, 0, sizeof(per_lowcore)); 530b9c1b51eSKate Stone PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, 531b9c1b51eSKate Stone sizeof(per_lowcore)); 532bb00d0b6SUlrich Weigand } 533bb00d0b6SUlrich Weigand 534*665be50eSMehdi Amini return Error(); 535bb00d0b6SUlrich Weigand } 536bb00d0b6SUlrich Weigand 537b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::GetWatchpointHitIndex( 538b9c1b51eSKate Stone uint32_t &wp_index, lldb::addr_t trap_addr) { 539bb00d0b6SUlrich Weigand uint32_t num_hw_wps = NumSupportedHardwareWatchpoints(); 540b9c1b51eSKate Stone for (wp_index = 0; wp_index < num_hw_wps; ++wp_index) { 541bb00d0b6SUlrich Weigand bool is_hit; 542bb00d0b6SUlrich Weigand Error error = IsWatchpointHit(wp_index, is_hit); 543b9c1b51eSKate Stone if (error.Fail()) { 544bb00d0b6SUlrich Weigand wp_index = LLDB_INVALID_INDEX32; 545bb00d0b6SUlrich Weigand return error; 546b9c1b51eSKate Stone } else if (is_hit) { 547bb00d0b6SUlrich Weigand return error; 548bb00d0b6SUlrich Weigand } 549bb00d0b6SUlrich Weigand } 550bb00d0b6SUlrich Weigand wp_index = LLDB_INVALID_INDEX32; 551*665be50eSMehdi Amini return Error(); 552bb00d0b6SUlrich Weigand } 553bb00d0b6SUlrich Weigand 554b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, 555b9c1b51eSKate Stone bool &is_vacant) { 556bb00d0b6SUlrich Weigand if (wp_index >= NumSupportedHardwareWatchpoints()) 557bb00d0b6SUlrich Weigand return Error("Watchpoint index out of range"); 558bb00d0b6SUlrich Weigand 559bb00d0b6SUlrich Weigand is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS; 560bb00d0b6SUlrich Weigand 561*665be50eSMehdi Amini return Error(); 562bb00d0b6SUlrich Weigand } 563bb00d0b6SUlrich Weigand 564b9c1b51eSKate Stone bool NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint( 565b9c1b51eSKate Stone uint32_t wp_index) { 566bb00d0b6SUlrich Weigand per_struct per_info; 567bb00d0b6SUlrich Weigand 568bb00d0b6SUlrich Weigand if (wp_index >= NumSupportedHardwareWatchpoints()) 569bb00d0b6SUlrich Weigand return false; 570bb00d0b6SUlrich Weigand 571b9c1b51eSKate Stone Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, 572b9c1b51eSKate Stone sizeof(per_info)); 573bb00d0b6SUlrich Weigand if (error.Fail()) 574bb00d0b6SUlrich Weigand return false; 575bb00d0b6SUlrich Weigand 576bb00d0b6SUlrich Weigand per_info.control_regs.bits.em_storage_alteration = 0; 577bb00d0b6SUlrich Weigand per_info.control_regs.bits.storage_alt_space_ctl = 0; 578bb00d0b6SUlrich Weigand per_info.starting_addr = 0; 579bb00d0b6SUlrich Weigand per_info.ending_addr = 0; 580bb00d0b6SUlrich Weigand 581b9c1b51eSKate Stone error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, 582b9c1b51eSKate Stone sizeof(per_info)); 583bb00d0b6SUlrich Weigand if (error.Fail()) 584bb00d0b6SUlrich Weigand return false; 585bb00d0b6SUlrich Weigand 586bb00d0b6SUlrich Weigand m_watchpoint_addr = LLDB_INVALID_ADDRESS; 587bb00d0b6SUlrich Weigand return true; 588bb00d0b6SUlrich Weigand } 589bb00d0b6SUlrich Weigand 590b9c1b51eSKate Stone Error NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints() { 591bb00d0b6SUlrich Weigand if (ClearHardwareWatchpoint(0)) 592*665be50eSMehdi Amini return Error(); 593bb00d0b6SUlrich Weigand return Error("Clearing all hardware watchpoints failed."); 594bb00d0b6SUlrich Weigand } 595bb00d0b6SUlrich Weigand 596b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_s390x::SetHardwareWatchpoint( 597b9c1b51eSKate Stone lldb::addr_t addr, size_t size, uint32_t watch_flags) { 598bb00d0b6SUlrich Weigand per_struct per_info; 599bb00d0b6SUlrich Weigand 600bb00d0b6SUlrich Weigand if (watch_flags != 0x1) 601bb00d0b6SUlrich Weigand return LLDB_INVALID_INDEX32; 602bb00d0b6SUlrich Weigand 603bb00d0b6SUlrich Weigand if (m_watchpoint_addr != LLDB_INVALID_ADDRESS) 604bb00d0b6SUlrich Weigand return LLDB_INVALID_INDEX32; 605bb00d0b6SUlrich Weigand 606b9c1b51eSKate Stone Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, 607b9c1b51eSKate Stone sizeof(per_info)); 608bb00d0b6SUlrich Weigand if (error.Fail()) 609bb00d0b6SUlrich Weigand return LLDB_INVALID_INDEX32; 610bb00d0b6SUlrich Weigand 611bb00d0b6SUlrich Weigand per_info.control_regs.bits.em_storage_alteration = 1; 612bb00d0b6SUlrich Weigand per_info.control_regs.bits.storage_alt_space_ctl = 1; 613bb00d0b6SUlrich Weigand per_info.starting_addr = addr; 614bb00d0b6SUlrich Weigand per_info.ending_addr = addr + size - 1; 615bb00d0b6SUlrich Weigand 616b9c1b51eSKate Stone error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, 617b9c1b51eSKate Stone sizeof(per_info)); 618bb00d0b6SUlrich Weigand if (error.Fail()) 619bb00d0b6SUlrich Weigand return LLDB_INVALID_INDEX32; 620bb00d0b6SUlrich Weigand 621bb00d0b6SUlrich Weigand m_watchpoint_addr = addr; 622bb00d0b6SUlrich Weigand return 0; 623bb00d0b6SUlrich Weigand } 624bb00d0b6SUlrich Weigand 625bb00d0b6SUlrich Weigand lldb::addr_t 626b9c1b51eSKate Stone NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index) { 627bb00d0b6SUlrich Weigand if (wp_index >= NumSupportedHardwareWatchpoints()) 628bb00d0b6SUlrich Weigand return LLDB_INVALID_ADDRESS; 629bb00d0b6SUlrich Weigand return m_watchpoint_addr; 630bb00d0b6SUlrich Weigand } 631bb00d0b6SUlrich Weigand 632b9c1b51eSKate Stone uint32_t NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints() { 633bb00d0b6SUlrich Weigand return 1; 634bb00d0b6SUlrich Weigand } 635bb00d0b6SUlrich Weigand 636bb00d0b6SUlrich Weigand #endif // defined(__s390x__) && defined(__linux__) 637