================ @@ -0,0 +1,559 @@ +//===-- NativeRegisterContextFreeBSD_riscv64.cpp --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#if defined(__riscv) && __riscv_xlen == 64 + +#include "NativeRegisterContextFreeBSD_riscv64.h" + +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" +#include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h" + +// clang-format off +#include <sys/param.h> +#include <sys/ptrace.h> +#include <sys/types.h> +// clang-format on + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_freebsd; + +// Translation between RegisterInfoPosix_riscv64 and reg.h +// https://github.com/freebsd/freebsd-src/blob/main/sys/riscv/include/reg.h: +// +// struct reg { +// __uint64_t ra; /* return address */ +// __uint64_t sp; /* stack pointer */ +// __uint64_t gp; /* global pointer */ +// __uint64_t tp; /* thread pointer */ +// __uint64_t t[7]; /* temporaries */ +// __uint64_t s[12]; /* saved registers */ +// __uint64_t a[8]; /* function arguments */ +// __uint64_t sepc; /* exception program counter */ +// __uint64_t sstatus; /* status register */ +// }; +// +// struct fpreg { +// __uint64_t fp_x[32][2]; /* Floating point registers */ +// __uint64_t fp_fcsr; /* Floating point control reg */ +// }; +// +// struct dbreg { +// int dummy; +// }; + +// ============================================================================ +// Static Conversion Functions between FreeBSD and POSIX +// ============================================================================ + +void NativeRegisterContextFreeBSD_riscv64::FreeBSDToPOSIXGPR( + const struct reg &freebsd_gpr, RegisterInfoPOSIX_riscv64::GPR &posix_gpr) { + posix_gpr.gpr[gpr_pc_riscv64] = freebsd_gpr.sepc; // x0/pc + posix_gpr.gpr[gpr_ra_riscv64] = freebsd_gpr.ra; // x1/ra + posix_gpr.gpr[gpr_sp_riscv64] = freebsd_gpr.sp; // x2/sp + posix_gpr.gpr[gpr_gp_riscv64] = freebsd_gpr.gp; // x3/gp + posix_gpr.gpr[gpr_tp_riscv64] = freebsd_gpr.tp; // x4/tp + + // x5-x7: t0-t2 + posix_gpr.gpr[gpr_t0_riscv64] = freebsd_gpr.t[0]; + posix_gpr.gpr[gpr_t1_riscv64] = freebsd_gpr.t[1]; + posix_gpr.gpr[gpr_t2_riscv64] = freebsd_gpr.t[2]; + + // x8-x9: s0-s1 (s0 is also fp) + posix_gpr.gpr[gpr_s0_riscv64] = freebsd_gpr.s[0]; + posix_gpr.gpr[gpr_s1_riscv64] = freebsd_gpr.s[1]; + + // x10-x17: a0-a7 + for (int i = 0; i < 8; i++) + posix_gpr.gpr[gpr_a0_riscv64 + i] = freebsd_gpr.a[i]; + + // x18-x27: s2-s11 + for (int i = 0; i < 10; i++) + posix_gpr.gpr[gpr_s2_riscv64 + i] = freebsd_gpr.s[2 + i]; + + // x28-x31: t3-t6 + posix_gpr.gpr[gpr_t3_riscv64] = freebsd_gpr.t[3]; + posix_gpr.gpr[gpr_t4_riscv64] = freebsd_gpr.t[4]; + posix_gpr.gpr[gpr_t5_riscv64] = freebsd_gpr.t[5]; + posix_gpr.gpr[gpr_t6_riscv64] = freebsd_gpr.t[6]; +} + +void NativeRegisterContextFreeBSD_riscv64::POSIXToFreeBSDGPR( + const RegisterInfoPOSIX_riscv64::GPR &posix_gpr, struct reg &freebsd_gpr) { + freebsd_gpr.sepc = posix_gpr.gpr[gpr_pc_riscv64]; // x0/pc + freebsd_gpr.ra = posix_gpr.gpr[gpr_ra_riscv64]; // x1/ra + freebsd_gpr.sp = posix_gpr.gpr[gpr_sp_riscv64]; // x2/sp + freebsd_gpr.gp = posix_gpr.gpr[gpr_gp_riscv64]; // x3/gp + freebsd_gpr.tp = posix_gpr.gpr[gpr_tp_riscv64]; // x4/tp + + // x5-x7: t0-t2 + freebsd_gpr.t[0] = posix_gpr.gpr[gpr_t0_riscv64]; + freebsd_gpr.t[1] = posix_gpr.gpr[gpr_t1_riscv64]; + freebsd_gpr.t[2] = posix_gpr.gpr[gpr_t2_riscv64]; + + // x8-x9: s0-s1 + freebsd_gpr.s[0] = posix_gpr.gpr[gpr_s0_riscv64]; + freebsd_gpr.s[1] = posix_gpr.gpr[gpr_s1_riscv64]; + + // x10-x17: a0-a7 + for (int i = 0; i < 8; i++) + freebsd_gpr.a[i] = posix_gpr.gpr[gpr_a0_riscv64 + i]; + + // x18-x27: s2-s11 + for (int i = 0; i < 10; i++) + freebsd_gpr.s[2 + i] = posix_gpr.gpr[gpr_s2_riscv64 + i]; + + // x28-x31: t3-t6 + freebsd_gpr.t[3] = posix_gpr.gpr[gpr_t3_riscv64]; + freebsd_gpr.t[4] = posix_gpr.gpr[gpr_t4_riscv64]; + freebsd_gpr.t[5] = posix_gpr.gpr[gpr_t5_riscv64]; + freebsd_gpr.t[6] = posix_gpr.gpr[gpr_t6_riscv64]; +} + +void NativeRegisterContextFreeBSD_riscv64::FreeBSDToPOSIXFPR( + const struct fpreg &freebsd_fpr, + RegisterInfoPOSIX_riscv64::FPR &posix_fpr) { + // FreeBSD stores FP registers as 128-bit (fp_x[32][2]) + // POSIX expects 64-bit (fpr[32]) + // We only use the lower 64 bits (D extension, double precision) + for (int i = 0; i < 32; i++) + posix_fpr.fpr[i] = freebsd_fpr.fp_x[i][0]; + + // FCSR: FreeBSD has 64-bit, POSIX expects 32-bit + posix_fpr.fcsr = static_cast<uint32_t>(freebsd_fpr.fp_fcsr); +} + +void NativeRegisterContextFreeBSD_riscv64::POSIXToFreeBSDFPR( + const RegisterInfoPOSIX_riscv64::FPR &posix_fpr, + struct fpreg &freebsd_fpr) { + // POSIX has 64-bit FP registers, FreeBSD expects 128-bit + for (int i = 0; i < 32; i++) { + freebsd_fpr.fp_x[i][0] = posix_fpr.fpr[i]; // Lower 64 bits + freebsd_fpr.fp_x[i][1] = 0; // Upper 64 bits (unused for D) + } + + // FCSR: POSIX has 32-bit, FreeBSD expects 64-bit + freebsd_fpr.fp_fcsr = static_cast<uint64_t>(posix_fpr.fcsr); +} + +// ============================================================================ +// Constructor and Setup +// ============================================================================ + +NativeRegisterContextFreeBSD * +NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( + const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) { + return new NativeRegisterContextFreeBSD_riscv64(target_arch, native_thread); +} + +NativeRegisterContextFreeBSD_riscv64::NativeRegisterContextFreeBSD_riscv64( + const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) + : NativeRegisterContextFreeBSD(native_thread), m_gpr(), m_fpr(), + m_gpr_is_valid(false), m_fpr_is_valid(false) { + m_register_info_interface_up = + std::make_unique<RegisterInfoPOSIX_riscv64>(target_arch, 0); + + ::memset(&m_gpr, 0, sizeof(m_gpr)); + ::memset(&m_fpr, 0, sizeof(m_fpr)); +} + +RegisterInfoPOSIX_riscv64 & +NativeRegisterContextFreeBSD_riscv64::GetRegisterInfo() const { + return static_cast<RegisterInfoPOSIX_riscv64 &>( + *m_register_info_interface_up); +} + +// ============================================================================ +// Register Set Information +// ============================================================================ + +uint32_t NativeRegisterContextFreeBSD_riscv64::GetRegisterSetCount() const { + return GetRegisterInfo().GetRegisterSetCount(); +} + +const RegisterSet * +NativeRegisterContextFreeBSD_riscv64::GetRegisterSet(uint32_t set_index) const { + return GetRegisterInfo().GetRegisterSet(set_index); +} + +uint32_t NativeRegisterContextFreeBSD_riscv64::GetUserRegisterCount() const { + uint32_t count = 0; + for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) + count += GetRegisterSet(set_index)->num_registers; + return count; +} + +void NativeRegisterContextFreeBSD_riscv64::InvalidateAllRegisters() { + m_gpr_is_valid = false; + m_fpr_is_valid = false; +} + +// ============================================================================ +// Ptrace Wrappers +// ============================================================================ + +Status NativeRegisterContextFreeBSD_riscv64::ReadGPR() { + if (m_gpr_is_valid) + return Status(); + + Status error = + NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), &m_gpr); + + if (error.Success()) + m_gpr_is_valid = true; + + return error; +} + +Status NativeRegisterContextFreeBSD_riscv64::WriteGPR() { + Status error = + NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), &m_gpr); + + if (error.Success()) + m_gpr_is_valid = true; + + return error; +} + +Status NativeRegisterContextFreeBSD_riscv64::ReadFPR() { + if (m_fpr_is_valid) + return Status(); + + Status error = NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, + m_thread.GetID(), &m_fpr); + + if (error.Success()) + m_fpr_is_valid = true; + + return error; +} + +Status NativeRegisterContextFreeBSD_riscv64::WriteFPR() { + Status error = NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, + m_thread.GetID(), &m_fpr); + + if (error.Success()) + m_fpr_is_valid = true; + + return error; +} + +// ============================================================================ +// Single Register Access Helpers +// ============================================================================ + +Status +NativeRegisterContextFreeBSD_riscv64::GetGPRValue(uint32_t reg_index, + uint64_t &value) const { + // Map LLDB register index to FreeBSD struct reg field + switch (reg_index) { + case gpr_pc_riscv64: + value = m_gpr.sepc; + return Status(); + case gpr_ra_riscv64: + value = m_gpr.ra; + return Status(); + case gpr_sp_riscv64: + value = m_gpr.sp; + return Status(); + case gpr_gp_riscv64: + value = m_gpr.gp; + return Status(); + case gpr_tp_riscv64: + value = m_gpr.tp; + return Status(); + + // t0-t6 + case gpr_t0_riscv64: + case gpr_t1_riscv64: + case gpr_t2_riscv64: + value = m_gpr.t[reg_index - gpr_t0_riscv64]; + return Status(); + case gpr_t3_riscv64: + case gpr_t4_riscv64: + case gpr_t5_riscv64: + case gpr_t6_riscv64: + value = m_gpr.t[reg_index - gpr_t3_riscv64 + 3]; + return Status(); + + // s0-s11 + case gpr_s0_riscv64: + case gpr_s1_riscv64: + value = m_gpr.s[reg_index - gpr_s0_riscv64]; + return Status(); + case gpr_s2_riscv64: + case gpr_s3_riscv64: + case gpr_s4_riscv64: + case gpr_s5_riscv64: + case gpr_s6_riscv64: + case gpr_s7_riscv64: + case gpr_s8_riscv64: + case gpr_s9_riscv64: + case gpr_s10_riscv64: + case gpr_s11_riscv64: + value = m_gpr.s[reg_index - gpr_s2_riscv64 + 2]; + return Status(); + + // a0-a7 + case gpr_a0_riscv64: + case gpr_a1_riscv64: + case gpr_a2_riscv64: + case gpr_a3_riscv64: + case gpr_a4_riscv64: + case gpr_a5_riscv64: + case gpr_a6_riscv64: + case gpr_a7_riscv64: + value = m_gpr.a[reg_index - gpr_a0_riscv64]; + return Status(); + + default: + return Status::FromErrorStringWithFormat("invalid GPR register index: %u", + reg_index); + } +} + +Status NativeRegisterContextFreeBSD_riscv64::SetGPRValue(uint32_t reg_index, + uint64_t value) { + switch (reg_index) { + case gpr_pc_riscv64: + m_gpr.sepc = value; + return Status(); + case gpr_ra_riscv64: + m_gpr.ra = value; + return Status(); + case gpr_sp_riscv64: + m_gpr.sp = value; + return Status(); + case gpr_gp_riscv64: + m_gpr.gp = value; + return Status(); + case gpr_tp_riscv64: + m_gpr.tp = value; + return Status(); + + case gpr_t0_riscv64: + case gpr_t1_riscv64: + case gpr_t2_riscv64: + m_gpr.t[reg_index - gpr_t0_riscv64] = value; + return Status(); + case gpr_t3_riscv64: + case gpr_t4_riscv64: + case gpr_t5_riscv64: + case gpr_t6_riscv64: + m_gpr.t[reg_index - gpr_t3_riscv64 + 3] = value; + return Status(); + + case gpr_s0_riscv64: + case gpr_s1_riscv64: + m_gpr.s[reg_index - gpr_s0_riscv64] = value; + return Status(); + case gpr_s2_riscv64: + case gpr_s3_riscv64: + case gpr_s4_riscv64: + case gpr_s5_riscv64: + case gpr_s6_riscv64: + case gpr_s7_riscv64: + case gpr_s8_riscv64: + case gpr_s9_riscv64: + case gpr_s10_riscv64: + case gpr_s11_riscv64: + m_gpr.s[reg_index - gpr_s2_riscv64 + 2] = value; + return Status(); + + case gpr_a0_riscv64: + case gpr_a1_riscv64: + case gpr_a2_riscv64: + case gpr_a3_riscv64: + case gpr_a4_riscv64: + case gpr_a5_riscv64: + case gpr_a6_riscv64: + case gpr_a7_riscv64: + m_gpr.a[reg_index - gpr_a0_riscv64] = value; + return Status(); + + default: + return Status::FromErrorStringWithFormat("invalid GPR register index: %u", + reg_index); + } +} + +// ============================================================================ +// Single Register Read/Write +// ============================================================================ + +Status +NativeRegisterContextFreeBSD_riscv64::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (!reg_info) + return Status::FromErrorString("reg_info NULL"); + + const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; + + if (reg == LLDB_INVALID_REGNUM) + return Status::FromErrorStringWithFormat( + "no lldb regnum for %s", reg_info->name ? reg_info->name : "<unknown>"); + + if (GetRegisterInfo().IsGPR(reg)) { + Status error = ReadGPR(); + if (error.Fail()) + return error; + + uint64_t value; + error = GetGPRValue(reg, value); + if (error.Fail()) + return error; + + reg_value = value; + return Status(); + } + + if (GetRegisterInfo().IsFPR(reg)) { + Status error = ReadFPR(); + if (error.Fail()) + return error; + + uint32_t fpr_index = + reg - GetRegisterInfo().GetRegisterInfo()[reg].kinds[eRegisterKindLLDB]; + + if (fpr_index < 32) { + reg_value = m_fpr.fp_x[fpr_index][0]; // Lower 64 bits + } else if (fpr_index == 32) { + reg_value = static_cast<uint32_t>(m_fpr.fp_fcsr); + } else { + return Status::FromErrorString("invalid FPR index"); + } ---------------- DavidSpickett wrote:
https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements https://github.com/llvm/llvm-project/pull/180549 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
