1bee4d6efSMichał Górny //===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===// 2bee4d6efSMichał Górny // 3bee4d6efSMichał Górny // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4bee4d6efSMichał Górny // See https://llvm.org/LICENSE.txt for license information. 5bee4d6efSMichał Górny // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6bee4d6efSMichał Górny // 7bee4d6efSMichał Górny //===----------------------------------------------------------------------===// 8bee4d6efSMichał Górny 9bee4d6efSMichał Górny #if defined(__powerpc__) 10bee4d6efSMichał Górny 11bee4d6efSMichał Górny #include "NativeRegisterContextFreeBSD_powerpc.h" 12bee4d6efSMichał Górny 13bee4d6efSMichał Górny #include "lldb/Host/HostInfo.h" 14bee4d6efSMichał Górny #include "lldb/Utility/DataBufferHeap.h" 15bee4d6efSMichał Górny #include "lldb/Utility/RegisterValue.h" 16bee4d6efSMichał Górny #include "lldb/Utility/Status.h" 17bee4d6efSMichał Górny 18bee4d6efSMichał Górny #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" 19bee4d6efSMichał Górny // for register enum definitions 20bee4d6efSMichał Górny #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h" 21bee4d6efSMichał Górny 22bee4d6efSMichał Górny // clang-format off 23bee4d6efSMichał Górny #include <sys/param.h> 24bee4d6efSMichał Górny #include <sys/ptrace.h> 25bee4d6efSMichał Górny #include <sys/types.h> 26bee4d6efSMichał Górny // clang-format on 27f190ce62SKazu Hirata #include <optional> 28bee4d6efSMichał Górny 29bee4d6efSMichał Górny using namespace lldb; 30bee4d6efSMichał Górny using namespace lldb_private; 31bee4d6efSMichał Górny using namespace lldb_private::process_freebsd; 32bee4d6efSMichał Górny 33bee4d6efSMichał Górny static const uint32_t g_gpr_regnums[] = { 34bee4d6efSMichał Górny gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc, 35bee4d6efSMichał Górny gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc, 36bee4d6efSMichał Górny gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc, 37bee4d6efSMichał Górny gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc, 38bee4d6efSMichał Górny gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc, 39bee4d6efSMichał Górny gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc, 40bee4d6efSMichał Górny gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc, 41bee4d6efSMichał Górny gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc, 42bee4d6efSMichał Górny gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc, 43bee4d6efSMichał Górny gpr_pc_powerpc, 44bee4d6efSMichał Górny }; 45bee4d6efSMichał Górny 46bee4d6efSMichał Górny static const uint32_t g_fpr_regnums[] = { 47bee4d6efSMichał Górny fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc, 48bee4d6efSMichał Górny fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc, 49bee4d6efSMichał Górny fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc, 50bee4d6efSMichał Górny fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc, 51bee4d6efSMichał Górny fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc, 52bee4d6efSMichał Górny fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc, 53bee4d6efSMichał Górny fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc, 54bee4d6efSMichał Górny fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc, 55bee4d6efSMichał Górny fpr_fpscr_powerpc, 56bee4d6efSMichał Górny }; 57bee4d6efSMichał Górny 58bee4d6efSMichał Górny // Number of register sets provided by this context. 59bee4d6efSMichał Górny enum { k_num_register_sets = 2 }; 60bee4d6efSMichał Górny 61bee4d6efSMichał Górny static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = { 62bee4d6efSMichał Górny {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc, 63bee4d6efSMichał Górny g_gpr_regnums}, 64bee4d6efSMichał Górny {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc, 65bee4d6efSMichał Górny g_fpr_regnums}, 66bee4d6efSMichał Górny }; 67bee4d6efSMichał Górny 68bee4d6efSMichał Górny NativeRegisterContextFreeBSD * 69bee4d6efSMichał Górny NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( 70ea4cf923SDavid Spickett const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) { 71bee4d6efSMichał Górny return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread); 72bee4d6efSMichał Górny } 73bee4d6efSMichał Górny 74bee4d6efSMichał Górny static RegisterInfoInterface * 75bee4d6efSMichał Górny CreateRegisterInfoInterface(const ArchSpec &target_arch) { 76bee4d6efSMichał Górny if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) { 77bee4d6efSMichał Górny return new RegisterContextFreeBSD_powerpc32(target_arch); 78bee4d6efSMichał Górny } else { 79bee4d6efSMichał Górny assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) && 80bee4d6efSMichał Górny "Register setting path assumes this is a 64-bit host"); 81bee4d6efSMichał Górny return new RegisterContextFreeBSD_powerpc64(target_arch); 82bee4d6efSMichał Górny } 83bee4d6efSMichał Górny } 84bee4d6efSMichał Górny 85bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc( 86ea4cf923SDavid Spickett const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) 87bee4d6efSMichał Górny : NativeRegisterContextRegisterInfo( 88bee4d6efSMichał Górny native_thread, CreateRegisterInfoInterface(target_arch)) {} 89bee4d6efSMichał Górny 90bee4d6efSMichał Górny RegisterContextFreeBSD_powerpc & 91bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const { 92bee4d6efSMichał Górny return static_cast<RegisterContextFreeBSD_powerpc &>( 93bee4d6efSMichał Górny *m_register_info_interface_up); 94bee4d6efSMichał Górny } 95bee4d6efSMichał Górny 96bee4d6efSMichał Górny uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const { 97bee4d6efSMichał Górny return k_num_register_sets; 98bee4d6efSMichał Górny } 99bee4d6efSMichał Górny 100bee4d6efSMichał Górny const RegisterSet * 101bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const { 102bee4d6efSMichał Górny switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 103bee4d6efSMichał Górny case llvm::Triple::ppc: 104bee4d6efSMichał Górny return &g_reg_sets_powerpc[set_index]; 105bee4d6efSMichał Górny default: 106bee4d6efSMichał Górny llvm_unreachable("Unhandled target architecture."); 107bee4d6efSMichał Górny } 108bee4d6efSMichał Górny } 109bee4d6efSMichał Górny 1102fe83274SKazu Hirata std::optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind> 111bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum( 112bee4d6efSMichał Górny uint32_t reg_num) const { 113bee4d6efSMichał Górny switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 114bee4d6efSMichał Górny case llvm::Triple::ppc: 115bee4d6efSMichał Górny if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc) 116bee4d6efSMichał Górny return GPRegSet; 117bee4d6efSMichał Górny if (reg_num >= k_first_fpr && reg_num <= k_last_fpr) 118bee4d6efSMichał Górny return FPRegSet; 119bee4d6efSMichał Górny break; 120bee4d6efSMichał Górny default: 121bee4d6efSMichał Górny llvm_unreachable("Unhandled target architecture."); 122bee4d6efSMichał Górny } 123bee4d6efSMichał Górny 124bee4d6efSMichał Górny llvm_unreachable("Register does not belong to any register set"); 125bee4d6efSMichał Górny } 126bee4d6efSMichał Górny 127bee4d6efSMichał Górny uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const { 128bee4d6efSMichał Górny uint32_t count = 0; 129bee4d6efSMichał Górny for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 130bee4d6efSMichał Górny count += GetRegisterSet(set_index)->num_registers; 131bee4d6efSMichał Górny return count; 132bee4d6efSMichał Górny } 133bee4d6efSMichał Górny 134bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) { 135bee4d6efSMichał Górny switch (set) { 136bee4d6efSMichał Górny case GPRegSet: 137bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), 138bee4d6efSMichał Górny m_reg_data.data()); 139bee4d6efSMichał Górny case FPRegSet: 140bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(), 141bee4d6efSMichał Górny m_reg_data.data() + sizeof(reg)); 142bee4d6efSMichał Górny } 143bee4d6efSMichał Górny llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet"); 144bee4d6efSMichał Górny } 145bee4d6efSMichał Górny 146bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) { 147bee4d6efSMichał Górny switch (set) { 148bee4d6efSMichał Górny case GPRegSet: 149bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), 150bee4d6efSMichał Górny m_reg_data.data()); 151bee4d6efSMichał Górny case FPRegSet: 152bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(), 153bee4d6efSMichał Górny m_reg_data.data() + sizeof(reg)); 154bee4d6efSMichał Górny } 155bee4d6efSMichał Górny llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet"); 156bee4d6efSMichał Górny } 157bee4d6efSMichał Górny 158bee4d6efSMichał Górny Status 159bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info, 160bee4d6efSMichał Górny RegisterValue ®_value) { 161bee4d6efSMichał Górny Status error; 162bee4d6efSMichał Górny 163bee4d6efSMichał Górny if (!reg_info) { 164*0642cd76SAdrian Prantl error = Status::FromErrorString("reg_info NULL"); 165bee4d6efSMichał Górny return error; 166bee4d6efSMichał Górny } 167bee4d6efSMichał Górny 168bee4d6efSMichał Górny const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 169bee4d6efSMichał Górny 170bee4d6efSMichał Górny if (reg == LLDB_INVALID_REGNUM) 171*0642cd76SAdrian Prantl return Status::FromErrorStringWithFormat( 172*0642cd76SAdrian Prantl "no lldb regnum for %s", 173*0642cd76SAdrian Prantl reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 174bee4d6efSMichał Górny 1752fe83274SKazu Hirata std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 176bee4d6efSMichał Górny if (!opt_set) { 177bee4d6efSMichał Górny // This is likely an internal register for lldb use only and should not be 178bee4d6efSMichał Górny // directly queried. 179*0642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 180*0642cd76SAdrian Prantl "register \"%s\" is in unrecognized set", reg_info->name); 181bee4d6efSMichał Górny return error; 182bee4d6efSMichał Górny } 183bee4d6efSMichał Górny 184003f2b37SFangrui Song RegSetKind set = *opt_set; 185bee4d6efSMichał Górny error = ReadRegisterSet(set); 186bee4d6efSMichał Górny if (error.Fail()) 187bee4d6efSMichał Górny return error; 188bee4d6efSMichał Górny 189bee4d6efSMichał Górny assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 190bee4d6efSMichał Górny reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset, 191bee4d6efSMichał Górny reg_info->byte_size, endian::InlHostByteOrder()); 192bee4d6efSMichał Górny return error; 193bee4d6efSMichał Górny } 194bee4d6efSMichał Górny 195bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteRegister( 196bee4d6efSMichał Górny const RegisterInfo *reg_info, const RegisterValue ®_value) { 197bee4d6efSMichał Górny Status error; 198bee4d6efSMichał Górny 199bee4d6efSMichał Górny if (!reg_info) 200*0642cd76SAdrian Prantl return Status::FromErrorString("reg_info NULL"); 201bee4d6efSMichał Górny 202bee4d6efSMichał Górny const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 203bee4d6efSMichał Górny 204bee4d6efSMichał Górny if (reg == LLDB_INVALID_REGNUM) 205*0642cd76SAdrian Prantl return Status::FromErrorStringWithFormat( 206*0642cd76SAdrian Prantl "no lldb regnum for %s", 207*0642cd76SAdrian Prantl reg_info && reg_info->name ? reg_info->name : "<unknown register>"); 208bee4d6efSMichał Górny 2092fe83274SKazu Hirata std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 210bee4d6efSMichał Górny if (!opt_set) { 211bee4d6efSMichał Górny // This is likely an internal register for lldb use only and should not be 212bee4d6efSMichał Górny // directly queried. 213*0642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 214*0642cd76SAdrian Prantl "register \"%s\" is in unrecognized set", reg_info->name); 215bee4d6efSMichał Górny return error; 216bee4d6efSMichał Górny } 217bee4d6efSMichał Górny 218003f2b37SFangrui Song RegSetKind set = *opt_set; 219bee4d6efSMichał Górny error = ReadRegisterSet(set); 220bee4d6efSMichał Górny if (error.Fail()) 221bee4d6efSMichał Górny return error; 222bee4d6efSMichał Górny 223bee4d6efSMichał Górny assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 224bee4d6efSMichał Górny ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(), 225bee4d6efSMichał Górny reg_info->byte_size); 226bee4d6efSMichał Górny 227bee4d6efSMichał Górny return WriteRegisterSet(set); 228bee4d6efSMichał Górny } 229bee4d6efSMichał Górny 230bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues( 231c2f64601SJonas Devlieghere lldb::WritableDataBufferSP &data_sp) { 232bee4d6efSMichał Górny Status error; 233bee4d6efSMichał Górny 234bee4d6efSMichał Górny error = ReadRegisterSet(GPRegSet); 235bee4d6efSMichał Górny if (error.Fail()) 236bee4d6efSMichał Górny return error; 237bee4d6efSMichał Górny 238bee4d6efSMichał Górny error = ReadRegisterSet(FPRegSet); 239bee4d6efSMichał Górny if (error.Fail()) 240bee4d6efSMichał Górny return error; 241bee4d6efSMichał Górny 242bee4d6efSMichał Górny data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); 243bee4d6efSMichał Górny uint8_t *dst = data_sp->GetBytes(); 244bee4d6efSMichał Górny ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); 245bee4d6efSMichał Górny 246bee4d6efSMichał Górny return error; 247bee4d6efSMichał Górny } 248bee4d6efSMichał Górny 249bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues( 250bee4d6efSMichał Górny const lldb::DataBufferSP &data_sp) { 251bee4d6efSMichał Górny Status error; 252bee4d6efSMichał Górny 253bee4d6efSMichał Górny if (!data_sp) { 254*0642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 255bee4d6efSMichał Górny "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided", 256bee4d6efSMichał Górny __FUNCTION__); 257bee4d6efSMichał Górny return error; 258bee4d6efSMichał Górny } 259bee4d6efSMichał Górny 260bee4d6efSMichał Górny if (data_sp->GetByteSize() != m_reg_data.size()) { 261*0642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 262bee4d6efSMichał Górny "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched " 263bee4d6efSMichał Górny "data size, expected %zu, actual %" PRIu64, 264bee4d6efSMichał Górny __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize()); 265bee4d6efSMichał Górny return error; 266bee4d6efSMichał Górny } 267bee4d6efSMichał Górny 268470eb5c2SJonas Devlieghere const uint8_t *src = data_sp->GetBytes(); 269bee4d6efSMichał Górny if (src == nullptr) { 270*0642cd76SAdrian Prantl error = Status::FromErrorStringWithFormat( 271*0642cd76SAdrian Prantl "NativeRegisterContextFreeBSD_powerpc::%s " 272bee4d6efSMichał Górny "DataBuffer::GetBytes() returned a null " 273bee4d6efSMichał Górny "pointer", 274bee4d6efSMichał Górny __FUNCTION__); 275bee4d6efSMichał Górny return error; 276bee4d6efSMichał Górny } 277bee4d6efSMichał Górny ::memcpy(m_reg_data.data(), src, m_reg_data.size()); 278bee4d6efSMichał Górny 279bee4d6efSMichał Górny error = WriteRegisterSet(GPRegSet); 280bee4d6efSMichał Górny if (error.Fail()) 281bee4d6efSMichał Górny return error; 282bee4d6efSMichał Górny 283bee4d6efSMichał Górny return WriteRegisterSet(FPRegSet); 284bee4d6efSMichał Górny } 285bee4d6efSMichał Górny 286bee4d6efSMichał Górny llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom( 287bee4d6efSMichał Górny NativeRegisterContextFreeBSD &source) { 288bee4d6efSMichał Górny return llvm::Error::success(); 289bee4d6efSMichał Górny } 290bee4d6efSMichał Górny 291bee4d6efSMichał Górny #endif // defined (__powerpc__) 292