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