1210284Sjmallett//===-- NativeRegisterContextFreeBSD_mips64.cpp ---------------------------===// 2210284Sjmallett// 3210284Sjmallett// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4210284Sjmallett// See https://llvm.org/LICENSE.txt for license information. 5210284Sjmallett// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6210284Sjmallett// 7210284Sjmallett//===----------------------------------------------------------------------===// 8210284Sjmallett 9210284Sjmallett#if defined(__mips64__) 10210284Sjmallett 11210284Sjmallett#include "NativeRegisterContextFreeBSD_mips64.h" 12210284Sjmallett 13210284Sjmallett#include "lldb/Utility/DataBufferHeap.h" 14210284Sjmallett#include "lldb/Utility/RegisterValue.h" 15210284Sjmallett#include "lldb/Utility/Status.h" 16210284Sjmallett 17210284Sjmallett#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" 18210284Sjmallett#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h" 19210284Sjmallett 20210284Sjmallett// clang-format off 21210284Sjmallett#include <sys/param.h> 22210284Sjmallett#include <sys/ptrace.h> 23210284Sjmallett#include <sys/types.h> 24210284Sjmallett// clang-format on 25210284Sjmallett#include <optional> 26210284Sjmallett 27210284Sjmallettusing namespace lldb; 28210284Sjmallettusing namespace lldb_private; 29210284Sjmallettusing namespace lldb_private::process_freebsd; 30210284Sjmallett 31210284SjmallettNativeRegisterContextFreeBSD * 32210284SjmallettNativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( 33210284Sjmallett const ArchSpec &target_arch, NativeThreadProtocol &native_thread) { 34210284Sjmallett return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread); 35210284Sjmallett} 36210284Sjmallett 37210284SjmallettNativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64( 38210284Sjmallett const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 39210284Sjmallett : NativeRegisterContextRegisterInfo( 40210284Sjmallett native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {} 41210284Sjmallett 42210284SjmallettRegisterContextFreeBSD_mips64 & 43210284SjmallettNativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const { 44210284Sjmallett return static_cast<RegisterContextFreeBSD_mips64 &>( 45210284Sjmallett *m_register_info_interface_up); 46210284Sjmallett} 47210284Sjmallett 48210284Sjmallettuint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const { 49210284Sjmallett return GetRegisterInfo().GetRegisterSetCount(); 50210284Sjmallett} 51210284Sjmallett 52210284Sjmallettconst RegisterSet * 53210284SjmallettNativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const { 54210284Sjmallett return GetRegisterInfo().GetRegisterSet(set_index); 55210284Sjmallett} 56210284Sjmallett 57210284Sjmallettuint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const { 58210284Sjmallett uint32_t count = 0; 59210284Sjmallett for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 60210284Sjmallett count += GetRegisterSet(set_index)->num_registers; 61210284Sjmallett return count; 62210284Sjmallett} 63210284Sjmallett 64210284Sjmallettstd::optional<NativeRegisterContextFreeBSD_mips64::RegSetKind> 65210284SjmallettNativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum( 66210284Sjmallett uint32_t reg_num) const { 67210284Sjmallett switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 68210284Sjmallett case llvm::Triple::mips64: 69210284Sjmallett if (reg_num >= k_first_gpr_mips64 && reg_num <= k_last_gpr_mips64) 70210284Sjmallett return GPRegSet; 71210284Sjmallett if (reg_num >= k_first_fpr_mips64 && reg_num <= k_last_fpr_mips64) 72210284Sjmallett return FPRegSet; 73210284Sjmallett break; 74210284Sjmallett default: 75210284Sjmallett llvm_unreachable("Unhandled target architecture."); 76210284Sjmallett } 77210284Sjmallett 78210284Sjmallett llvm_unreachable("Register does not belong to any register set"); 79210284Sjmallett} 80210284Sjmallett 81210284SjmallettStatus NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) { 82210284Sjmallett switch (set) { 83210284Sjmallett case GPRegSet: 84210284Sjmallett return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), 85210284Sjmallett m_reg_data.data()); 86210284Sjmallett case FPRegSet: 87210284Sjmallett return NativeProcessFreeBSD::PtraceWrapper( 88210284Sjmallett PT_GETFPREGS, m_thread.GetID(), 89210284Sjmallett m_reg_data.data() + GetRegisterInfo().GetGPRSize()); 90210284Sjmallett } 91210284Sjmallett llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet"); 92210284Sjmallett} 93210284Sjmallett 94210284SjmallettStatus NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) { 95210284Sjmallett switch (set) { 96210284Sjmallett case GPRegSet: 97210284Sjmallett return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), 98210284Sjmallett m_reg_data.data()); 99210284Sjmallett case FPRegSet: 100210284Sjmallett return NativeProcessFreeBSD::PtraceWrapper( 101210284Sjmallett PT_SETFPREGS, m_thread.GetID(), 102210284Sjmallett m_reg_data.data() + GetRegisterInfo().GetGPRSize()); 103210284Sjmallett } 104210284Sjmallett llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet"); 105210284Sjmallett} 106210284Sjmallett 107210284SjmallettStatus 108210284SjmallettNativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info, 109210284Sjmallett RegisterValue ®_value) { 110210284Sjmallett Status error; 111210284Sjmallett 112210284Sjmallett if (!reg_info) { 113210284Sjmallett error.SetErrorString("reg_info NULL"); 114210284Sjmallett return error; 115210284Sjmallett } 116210284Sjmallett 117210284Sjmallett const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 118210284Sjmallett 119210284Sjmallett if (reg == LLDB_INVALID_REGNUM) 120210284Sjmallett return Status("no lldb regnum for %s", reg_info && reg_info->name 121210284Sjmallett ? reg_info->name 122210284Sjmallett : "<unknown register>"); 123210284Sjmallett 124210284Sjmallett std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 125210284Sjmallett if (!opt_set) { 126210284Sjmallett // This is likely an internal register for lldb use only and should not be 127210284Sjmallett // directly queried. 128210284Sjmallett error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 129210284Sjmallett reg_info->name); 130210284Sjmallett return error; 131210284Sjmallett } 132210284Sjmallett 133210284Sjmallett RegSetKind set = *opt_set; 134210284Sjmallett error = ReadRegisterSet(set); 135210284Sjmallett if (error.Fail()) 136210284Sjmallett return error; 137210284Sjmallett 138210284Sjmallett assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 139210284Sjmallett reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset, 140210284Sjmallett reg_info->byte_size, endian::InlHostByteOrder()); 141210284Sjmallett return error; 142210284Sjmallett} 143210284Sjmallett 144210284SjmallettStatus NativeRegisterContextFreeBSD_mips64::WriteRegister( 145210284Sjmallett const RegisterInfo *reg_info, const RegisterValue ®_value) { 146210284Sjmallett Status error; 147210284Sjmallett 148210284Sjmallett if (!reg_info) 149210284Sjmallett return Status("reg_info NULL"); 150210284Sjmallett 151210284Sjmallett const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 152210284Sjmallett 153210284Sjmallett if (reg == LLDB_INVALID_REGNUM) 154210284Sjmallett return Status("no lldb regnum for %s", reg_info && reg_info->name 155210284Sjmallett ? reg_info->name 156210284Sjmallett : "<unknown register>"); 157210284Sjmallett 158210284Sjmallett std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 159210284Sjmallett if (!opt_set) { 160210284Sjmallett // This is likely an internal register for lldb use only and should not be 161210284Sjmallett // directly queried. 162210284Sjmallett error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 163210284Sjmallett reg_info->name); 164210284Sjmallett return error; 165210284Sjmallett } 166210284Sjmallett 167210284Sjmallett RegSetKind set = *opt_set; 168210284Sjmallett error = ReadRegisterSet(set); 169210284Sjmallett if (error.Fail()) 170210284Sjmallett return error; 171210284Sjmallett 172210284Sjmallett assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 173210284Sjmallett ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(), 174210284Sjmallett reg_info->byte_size); 175210284Sjmallett 176210284Sjmallett return WriteRegisterSet(set); 177210284Sjmallett} 178210284Sjmallett 179210284SjmallettStatus NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues( 180210284Sjmallett lldb::WritableDataBufferSP &data_sp) { 181210284Sjmallett Status error; 182210284Sjmallett 183210284Sjmallett error = ReadRegisterSet(GPRegSet); 184210284Sjmallett if (error.Fail()) 185210284Sjmallett return error; 186210284Sjmallett 187210284Sjmallett error = ReadRegisterSet(FPRegSet); 188210284Sjmallett if (error.Fail()) 189210284Sjmallett return error; 190210284Sjmallett 191210284Sjmallett data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); 192210284Sjmallett uint8_t *dst = data_sp->GetBytes(); 193210284Sjmallett ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); 194210284Sjmallett 195210284Sjmallett return error; 196210284Sjmallett} 197210284Sjmallett 198210284SjmallettStatus NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues( 199210284Sjmallett const lldb::DataBufferSP &data_sp) { 200210284Sjmallett Status error; 201210284Sjmallett 202210284Sjmallett if (!data_sp) { 203210284Sjmallett error.SetErrorStringWithFormat( 204210284Sjmallett "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided", 205210284Sjmallett __FUNCTION__); 206210284Sjmallett return error; 207210284Sjmallett } 208 209 if (data_sp->GetByteSize() != m_reg_data.size()) { 210 error.SetErrorStringWithFormat( 211 "NativeRegisterContextFreeBSD_mips64::%s data_sp contained mismatched " 212 "data size, expected %" PRIu64 ", actual %" PRIu64, 213 __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize()); 214 return error; 215 } 216 217 const uint8_t *src = data_sp->GetBytes(); 218 if (src == nullptr) { 219 error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_mips64::%s " 220 "DataBuffer::GetBytes() returned a null " 221 "pointer", 222 __FUNCTION__); 223 return error; 224 } 225 ::memcpy(m_reg_data.data(), src, m_reg_data.size()); 226 227 error = WriteRegisterSet(GPRegSet); 228 if (error.Fail()) 229 return error; 230 231 return WriteRegisterSet(FPRegSet); 232} 233 234llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom( 235 NativeRegisterContextFreeBSD &source) { 236 return llvm::Error::success(); 237} 238 239#endif // defined (__mips64__) 240