Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_powerpc.cpp
96380 views
//===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#if defined(__powerpc__)910#include "NativeRegisterContextFreeBSD_powerpc.h"1112#include "lldb/Host/HostInfo.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/RegisterValue.h"15#include "lldb/Utility/Status.h"1617#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"18// for register enum definitions19#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"2021// clang-format off22#include <sys/param.h>23#include <sys/ptrace.h>24#include <sys/types.h>25// clang-format on26#include <optional>2728using namespace lldb;29using namespace lldb_private;30using namespace lldb_private::process_freebsd;3132static const uint32_t g_gpr_regnums[] = {33gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc,34gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc,35gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc,36gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,37gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,38gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,39gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,40gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,41gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc,42gpr_pc_powerpc,43};4445static const uint32_t g_fpr_regnums[] = {46fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc,47fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc,48fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc,49fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,50fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,51fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,52fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,53fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,54fpr_fpscr_powerpc,55};5657// Number of register sets provided by this context.58enum { k_num_register_sets = 2 };5960static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {61{"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,62g_gpr_regnums},63{"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,64g_fpr_regnums},65};6667NativeRegisterContextFreeBSD *68NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(69const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {70return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);71}7273static RegisterInfoInterface *74CreateRegisterInfoInterface(const ArchSpec &target_arch) {75if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {76return new RegisterContextFreeBSD_powerpc32(target_arch);77} else {78assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&79"Register setting path assumes this is a 64-bit host");80return new RegisterContextFreeBSD_powerpc64(target_arch);81}82}8384NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(85const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)86: NativeRegisterContextRegisterInfo(87native_thread, CreateRegisterInfoInterface(target_arch)) {}8889RegisterContextFreeBSD_powerpc &90NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {91return static_cast<RegisterContextFreeBSD_powerpc &>(92*m_register_info_interface_up);93}9495uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {96return k_num_register_sets;97}9899const RegisterSet *100NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {101switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {102case llvm::Triple::ppc:103return &g_reg_sets_powerpc[set_index];104default:105llvm_unreachable("Unhandled target architecture.");106}107}108109std::optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>110NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(111uint32_t reg_num) const {112switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {113case llvm::Triple::ppc:114if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)115return GPRegSet;116if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)117return FPRegSet;118break;119default:120llvm_unreachable("Unhandled target architecture.");121}122123llvm_unreachable("Register does not belong to any register set");124}125126uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {127uint32_t count = 0;128for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)129count += GetRegisterSet(set_index)->num_registers;130return count;131}132133Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {134switch (set) {135case GPRegSet:136return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),137m_reg_data.data());138case FPRegSet:139return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),140m_reg_data.data() + sizeof(reg));141}142llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");143}144145Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {146switch (set) {147case GPRegSet:148return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),149m_reg_data.data());150case FPRegSet:151return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),152m_reg_data.data() + sizeof(reg));153}154llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");155}156157Status158NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,159RegisterValue ®_value) {160Status error;161162if (!reg_info) {163error.SetErrorString("reg_info NULL");164return error;165}166167const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];168169if (reg == LLDB_INVALID_REGNUM)170return Status("no lldb regnum for %s", reg_info && reg_info->name171? reg_info->name172: "<unknown register>");173174std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);175if (!opt_set) {176// This is likely an internal register for lldb use only and should not be177// directly queried.178error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",179reg_info->name);180return error;181}182183RegSetKind set = *opt_set;184error = ReadRegisterSet(set);185if (error.Fail())186return error;187188assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());189reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,190reg_info->byte_size, endian::InlHostByteOrder());191return error;192}193194Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(195const RegisterInfo *reg_info, const RegisterValue ®_value) {196Status error;197198if (!reg_info)199return Status("reg_info NULL");200201const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];202203if (reg == LLDB_INVALID_REGNUM)204return Status("no lldb regnum for %s", reg_info && reg_info->name205? reg_info->name206: "<unknown register>");207208std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);209if (!opt_set) {210// This is likely an internal register for lldb use only and should not be211// directly queried.212error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",213reg_info->name);214return error;215}216217RegSetKind set = *opt_set;218error = ReadRegisterSet(set);219if (error.Fail())220return error;221222assert(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(),224reg_info->byte_size);225226return WriteRegisterSet(set);227}228229Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(230lldb::WritableDataBufferSP &data_sp) {231Status error;232233error = ReadRegisterSet(GPRegSet);234if (error.Fail())235return error;236237error = ReadRegisterSet(FPRegSet);238if (error.Fail())239return error;240241data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));242uint8_t *dst = data_sp->GetBytes();243::memcpy(dst, m_reg_data.data(), m_reg_data.size());244245return error;246}247248Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(249const lldb::DataBufferSP &data_sp) {250Status error;251252if (!data_sp) {253error.SetErrorStringWithFormat(254"NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",255__FUNCTION__);256return error;257}258259if (data_sp->GetByteSize() != m_reg_data.size()) {260error.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());264return error;265}266267const uint8_t *src = data_sp->GetBytes();268if (src == nullptr) {269error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "270"DataBuffer::GetBytes() returned a null "271"pointer",272__FUNCTION__);273return error;274}275::memcpy(m_reg_data.data(), src, m_reg_data.size());276277error = WriteRegisterSet(GPRegSet);278if (error.Fail())279return error;280281return WriteRegisterSet(FPRegSet);282}283284llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(285NativeRegisterContextFreeBSD &source) {286return llvm::Error::success();287}288289#endif // defined (__powerpc__)290291292