1d409305fSDimitry Andric //===-- NativeRegisterContextFreeBSD_mips64.cpp ---------------------------===// 2d409305fSDimitry Andric // 3d409305fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4d409305fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5d409305fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6d409305fSDimitry Andric // 7d409305fSDimitry Andric //===----------------------------------------------------------------------===// 8d409305fSDimitry Andric 9d409305fSDimitry Andric #if defined(__mips64__) 10d409305fSDimitry Andric 11d409305fSDimitry Andric #include "NativeRegisterContextFreeBSD_mips64.h" 12d409305fSDimitry Andric 13d409305fSDimitry Andric #include "lldb/Utility/DataBufferHeap.h" 14d409305fSDimitry Andric #include "lldb/Utility/RegisterValue.h" 15d409305fSDimitry Andric #include "lldb/Utility/Status.h" 16d409305fSDimitry Andric 17d409305fSDimitry Andric #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h" 18349cc55cSDimitry Andric #include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h" 19d409305fSDimitry Andric 20d409305fSDimitry Andric // clang-format off 21d409305fSDimitry Andric #include <sys/param.h> 22d409305fSDimitry Andric #include <sys/ptrace.h> 23d409305fSDimitry Andric #include <sys/types.h> 24d409305fSDimitry Andric // clang-format on 25bdd1243dSDimitry Andric #include <optional> 26d409305fSDimitry Andric 27d409305fSDimitry Andric using namespace lldb; 28d409305fSDimitry Andric using namespace lldb_private; 29d409305fSDimitry Andric using namespace lldb_private::process_freebsd; 30d409305fSDimitry Andric 31d409305fSDimitry Andric NativeRegisterContextFreeBSD * 32d409305fSDimitry Andric NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD( 33*0fca6ea1SDimitry Andric const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) { 34d409305fSDimitry Andric return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread); 35d409305fSDimitry Andric } 36d409305fSDimitry Andric 37d409305fSDimitry Andric NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64( 38*0fca6ea1SDimitry Andric const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) 39d409305fSDimitry Andric : NativeRegisterContextRegisterInfo( 40d409305fSDimitry Andric native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {} 41d409305fSDimitry Andric 42d409305fSDimitry Andric RegisterContextFreeBSD_mips64 & 43d409305fSDimitry Andric NativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const { 44d409305fSDimitry Andric return static_cast<RegisterContextFreeBSD_mips64 &>( 45d409305fSDimitry Andric *m_register_info_interface_up); 46d409305fSDimitry Andric } 47d409305fSDimitry Andric 48d409305fSDimitry Andric uint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const { 49d409305fSDimitry Andric return GetRegisterInfo().GetRegisterSetCount(); 50d409305fSDimitry Andric } 51d409305fSDimitry Andric 52d409305fSDimitry Andric const RegisterSet * 53d409305fSDimitry Andric NativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const { 54d409305fSDimitry Andric return GetRegisterInfo().GetRegisterSet(set_index); 55d409305fSDimitry Andric } 56d409305fSDimitry Andric 57d409305fSDimitry Andric uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const { 58d409305fSDimitry Andric uint32_t count = 0; 59d409305fSDimitry Andric for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 60d409305fSDimitry Andric count += GetRegisterSet(set_index)->num_registers; 61d409305fSDimitry Andric return count; 62d409305fSDimitry Andric } 63d409305fSDimitry Andric 64bdd1243dSDimitry Andric std::optional<NativeRegisterContextFreeBSD_mips64::RegSetKind> 65349cc55cSDimitry Andric NativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum( 66349cc55cSDimitry Andric uint32_t reg_num) const { 67349cc55cSDimitry Andric switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { 68349cc55cSDimitry Andric case llvm::Triple::mips64: 69349cc55cSDimitry Andric if (reg_num >= k_first_gpr_mips64 && reg_num <= k_last_gpr_mips64) 70349cc55cSDimitry Andric return GPRegSet; 71349cc55cSDimitry Andric if (reg_num >= k_first_fpr_mips64 && reg_num <= k_last_fpr_mips64) 72349cc55cSDimitry Andric return FPRegSet; 73349cc55cSDimitry Andric break; 74349cc55cSDimitry Andric default: 75349cc55cSDimitry Andric llvm_unreachable("Unhandled target architecture."); 76349cc55cSDimitry Andric } 77349cc55cSDimitry Andric 78349cc55cSDimitry Andric llvm_unreachable("Register does not belong to any register set"); 79349cc55cSDimitry Andric } 80349cc55cSDimitry Andric 81d409305fSDimitry Andric Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) { 82d409305fSDimitry Andric switch (set) { 83d409305fSDimitry Andric case GPRegSet: 84d409305fSDimitry Andric return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), 85d409305fSDimitry Andric m_reg_data.data()); 86349cc55cSDimitry Andric case FPRegSet: 87349cc55cSDimitry Andric return NativeProcessFreeBSD::PtraceWrapper( 88349cc55cSDimitry Andric PT_GETFPREGS, m_thread.GetID(), 89349cc55cSDimitry Andric m_reg_data.data() + GetRegisterInfo().GetGPRSize()); 90d409305fSDimitry Andric } 91d409305fSDimitry Andric llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet"); 92d409305fSDimitry Andric } 93d409305fSDimitry Andric 94d409305fSDimitry Andric Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) { 95d409305fSDimitry Andric switch (set) { 96d409305fSDimitry Andric case GPRegSet: 97d409305fSDimitry Andric return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), 98d409305fSDimitry Andric m_reg_data.data()); 99349cc55cSDimitry Andric case FPRegSet: 100349cc55cSDimitry Andric return NativeProcessFreeBSD::PtraceWrapper( 101349cc55cSDimitry Andric PT_SETFPREGS, m_thread.GetID(), 102349cc55cSDimitry Andric m_reg_data.data() + GetRegisterInfo().GetGPRSize()); 103d409305fSDimitry Andric } 104d409305fSDimitry Andric llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet"); 105d409305fSDimitry Andric } 106d409305fSDimitry Andric 107d409305fSDimitry Andric Status 108d409305fSDimitry Andric NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info, 109d409305fSDimitry Andric RegisterValue ®_value) { 110d409305fSDimitry Andric Status error; 111d409305fSDimitry Andric 112d409305fSDimitry Andric if (!reg_info) { 113d409305fSDimitry Andric error.SetErrorString("reg_info NULL"); 114d409305fSDimitry Andric return error; 115d409305fSDimitry Andric } 116d409305fSDimitry Andric 117d409305fSDimitry Andric const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 118d409305fSDimitry Andric 119d409305fSDimitry Andric if (reg == LLDB_INVALID_REGNUM) 120d409305fSDimitry Andric return Status("no lldb regnum for %s", reg_info && reg_info->name 121d409305fSDimitry Andric ? reg_info->name 122d409305fSDimitry Andric : "<unknown register>"); 123d409305fSDimitry Andric 124bdd1243dSDimitry Andric std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 125349cc55cSDimitry Andric if (!opt_set) { 126349cc55cSDimitry Andric // This is likely an internal register for lldb use only and should not be 127349cc55cSDimitry Andric // directly queried. 128349cc55cSDimitry Andric error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 129349cc55cSDimitry Andric reg_info->name); 130349cc55cSDimitry Andric return error; 131349cc55cSDimitry Andric } 132349cc55cSDimitry Andric 1331ac55f4cSDimitry Andric RegSetKind set = *opt_set; 134d409305fSDimitry Andric error = ReadRegisterSet(set); 135d409305fSDimitry Andric if (error.Fail()) 136d409305fSDimitry Andric return error; 137d409305fSDimitry Andric 138d409305fSDimitry Andric assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 139d409305fSDimitry Andric reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset, 140d409305fSDimitry Andric reg_info->byte_size, endian::InlHostByteOrder()); 141d409305fSDimitry Andric return error; 142d409305fSDimitry Andric } 143d409305fSDimitry Andric 144d409305fSDimitry Andric Status NativeRegisterContextFreeBSD_mips64::WriteRegister( 145d409305fSDimitry Andric const RegisterInfo *reg_info, const RegisterValue ®_value) { 146d409305fSDimitry Andric Status error; 147d409305fSDimitry Andric 148d409305fSDimitry Andric if (!reg_info) 149d409305fSDimitry Andric return Status("reg_info NULL"); 150d409305fSDimitry Andric 151d409305fSDimitry Andric const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 152d409305fSDimitry Andric 153d409305fSDimitry Andric if (reg == LLDB_INVALID_REGNUM) 154d409305fSDimitry Andric return Status("no lldb regnum for %s", reg_info && reg_info->name 155d409305fSDimitry Andric ? reg_info->name 156d409305fSDimitry Andric : "<unknown register>"); 157d409305fSDimitry Andric 158bdd1243dSDimitry Andric std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg); 159349cc55cSDimitry Andric if (!opt_set) { 160349cc55cSDimitry Andric // This is likely an internal register for lldb use only and should not be 161349cc55cSDimitry Andric // directly queried. 162349cc55cSDimitry Andric error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set", 163349cc55cSDimitry Andric reg_info->name); 164349cc55cSDimitry Andric return error; 165349cc55cSDimitry Andric } 166349cc55cSDimitry Andric 1671ac55f4cSDimitry Andric RegSetKind set = *opt_set; 168d409305fSDimitry Andric error = ReadRegisterSet(set); 169d409305fSDimitry Andric if (error.Fail()) 170d409305fSDimitry Andric return error; 171d409305fSDimitry Andric 172d409305fSDimitry Andric assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 173d409305fSDimitry Andric ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(), 174d409305fSDimitry Andric reg_info->byte_size); 175d409305fSDimitry Andric 176d409305fSDimitry Andric return WriteRegisterSet(set); 177d409305fSDimitry Andric } 178d409305fSDimitry Andric 179d409305fSDimitry Andric Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues( 18081ad6265SDimitry Andric lldb::WritableDataBufferSP &data_sp) { 181d409305fSDimitry Andric Status error; 182d409305fSDimitry Andric 183d409305fSDimitry Andric error = ReadRegisterSet(GPRegSet); 184d409305fSDimitry Andric if (error.Fail()) 185d409305fSDimitry Andric return error; 186d409305fSDimitry Andric 187349cc55cSDimitry Andric error = ReadRegisterSet(FPRegSet); 188349cc55cSDimitry Andric if (error.Fail()) 189349cc55cSDimitry Andric return error; 190349cc55cSDimitry Andric 191d409305fSDimitry Andric data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); 192d409305fSDimitry Andric uint8_t *dst = data_sp->GetBytes(); 193d409305fSDimitry Andric ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); 194d409305fSDimitry Andric 195d409305fSDimitry Andric return error; 196d409305fSDimitry Andric } 197d409305fSDimitry Andric 198d409305fSDimitry Andric Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues( 199d409305fSDimitry Andric const lldb::DataBufferSP &data_sp) { 200d409305fSDimitry Andric Status error; 201d409305fSDimitry Andric 202d409305fSDimitry Andric if (!data_sp) { 203d409305fSDimitry Andric error.SetErrorStringWithFormat( 204d409305fSDimitry Andric "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided", 205d409305fSDimitry Andric __FUNCTION__); 206d409305fSDimitry Andric return error; 207d409305fSDimitry Andric } 208d409305fSDimitry Andric 209d409305fSDimitry Andric if (data_sp->GetByteSize() != m_reg_data.size()) { 210d409305fSDimitry Andric error.SetErrorStringWithFormat( 211d409305fSDimitry Andric "NativeRegisterContextFreeBSD_mips64::%s data_sp contained mismatched " 212d409305fSDimitry Andric "data size, expected %" PRIu64 ", actual %" PRIu64, 213d409305fSDimitry Andric __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize()); 214d409305fSDimitry Andric return error; 215d409305fSDimitry Andric } 216d409305fSDimitry Andric 21781ad6265SDimitry Andric const uint8_t *src = data_sp->GetBytes(); 218d409305fSDimitry Andric if (src == nullptr) { 219d409305fSDimitry Andric error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_mips64::%s " 220d409305fSDimitry Andric "DataBuffer::GetBytes() returned a null " 221d409305fSDimitry Andric "pointer", 222d409305fSDimitry Andric __FUNCTION__); 223d409305fSDimitry Andric return error; 224d409305fSDimitry Andric } 225d409305fSDimitry Andric ::memcpy(m_reg_data.data(), src, m_reg_data.size()); 226d409305fSDimitry Andric 227349cc55cSDimitry Andric error = WriteRegisterSet(GPRegSet); 228349cc55cSDimitry Andric if (error.Fail()) 229349cc55cSDimitry Andric return error; 230349cc55cSDimitry Andric 231349cc55cSDimitry Andric return WriteRegisterSet(FPRegSet); 232d409305fSDimitry Andric } 233d409305fSDimitry Andric 234d409305fSDimitry Andric llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom( 235d409305fSDimitry Andric NativeRegisterContextFreeBSD &source) { 236d409305fSDimitry Andric return llvm::Error::success(); 237d409305fSDimitry Andric } 238d409305fSDimitry Andric 239d409305fSDimitry Andric #endif // defined (__mips64__) 240