241 lines · cpp
1//===-- NativeRegisterContextFreeBSD_mips64.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-exception6//7//===----------------------------------------------------------------------===//8 9#if defined(__mips64__)10 11#include "NativeRegisterContextFreeBSD_mips64.h"12 13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/RegisterValue.h"15#include "lldb/Utility/Status.h"16 17#include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"18#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h"19 20// clang-format off21#include <sys/param.h>22#include <sys/ptrace.h>23#include <sys/types.h>24// clang-format on25#include <optional>26 27using namespace lldb;28using namespace lldb_private;29using namespace lldb_private::process_freebsd;30 31NativeRegisterContextFreeBSD *32NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(33 const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {34 return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread);35}36 37NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64(38 const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread)39 : NativeRegisterContextRegisterInfo(40 native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {}41 42RegisterContextFreeBSD_mips64 &43NativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const {44 return static_cast<RegisterContextFreeBSD_mips64 &>(45 *m_register_info_interface_up);46}47 48uint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const {49 return GetRegisterInfo().GetRegisterSetCount();50}51 52const RegisterSet *53NativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const {54 return GetRegisterInfo().GetRegisterSet(set_index);55}56 57uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const {58 uint32_t count = 0;59 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)60 count += GetRegisterSet(set_index)->num_registers;61 return count;62}63 64std::optional<NativeRegisterContextFreeBSD_mips64::RegSetKind>65NativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum(66 uint32_t reg_num) const {67 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {68 case llvm::Triple::mips64:69 if (reg_num >= k_first_gpr_mips64 && reg_num <= k_last_gpr_mips64)70 return GPRegSet;71 if (reg_num >= k_first_fpr_mips64 && reg_num <= k_last_fpr_mips64)72 return FPRegSet;73 break;74 default:75 llvm_unreachable("Unhandled target architecture.");76 }77 78 llvm_unreachable("Register does not belong to any register set");79}80 81Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) {82 switch (set) {83 case GPRegSet:84 return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),85 m_reg_data.data());86 case FPRegSet:87 return NativeProcessFreeBSD::PtraceWrapper(88 PT_GETFPREGS, m_thread.GetID(),89 m_reg_data.data() + GetRegisterInfo().GetGPRSize());90 }91 llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet");92}93 94Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) {95 switch (set) {96 case GPRegSet:97 return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),98 m_reg_data.data());99 case FPRegSet:100 return NativeProcessFreeBSD::PtraceWrapper(101 PT_SETFPREGS, m_thread.GetID(),102 m_reg_data.data() + GetRegisterInfo().GetGPRSize());103 }104 llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet");105}106 107Status108NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info,109 RegisterValue ®_value) {110 Status error;111 112 if (!reg_info) {113 error = Status::FromErrorString("reg_info NULL");114 return error;115 }116 117 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];118 119 if (reg == LLDB_INVALID_REGNUM)120 return Status("no lldb regnum for %s", reg_info && reg_info->name121 ? reg_info->name122 : "<unknown register>");123 124 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);125 if (!opt_set) {126 // This is likely an internal register for lldb use only and should not be127 // directly queried.128 error = Status::FromErrorStringWithFormat(129 "register \"%s\" is in unrecognized set", reg_info->name);130 return error;131 }132 133 RegSetKind set = *opt_set;134 error = ReadRegisterSet(set);135 if (error.Fail())136 return error;137 138 assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());139 reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,140 reg_info->byte_size, endian::InlHostByteOrder());141 return error;142}143 144Status NativeRegisterContextFreeBSD_mips64::WriteRegister(145 const RegisterInfo *reg_info, const RegisterValue ®_value) {146 Status error;147 148 if (!reg_info)149 return Status("reg_info NULL");150 151 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];152 153 if (reg == LLDB_INVALID_REGNUM)154 return Status("no lldb regnum for %s", reg_info && reg_info->name155 ? reg_info->name156 : "<unknown register>");157 158 std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);159 if (!opt_set) {160 // This is likely an internal register for lldb use only and should not be161 // directly queried.162 error = Status::FromErrorStringWithFormat(163 "register \"%s\" is in unrecognized set", reg_info->name);164 return error;165 }166 167 RegSetKind set = *opt_set;168 error = ReadRegisterSet(set);169 if (error.Fail())170 return error;171 172 assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());173 ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),174 reg_info->byte_size);175 176 return WriteRegisterSet(set);177}178 179Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues(180 lldb::WritableDataBufferSP &data_sp) {181 Status error;182 183 error = ReadRegisterSet(GPRegSet);184 if (error.Fail())185 return error;186 187 error = ReadRegisterSet(FPRegSet);188 if (error.Fail())189 return error;190 191 data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));192 uint8_t *dst = data_sp->GetBytes();193 ::memcpy(dst, m_reg_data.data(), m_reg_data.size());194 195 return error;196}197 198Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues(199 const lldb::DataBufferSP &data_sp) {200 Status error;201 202 if (!data_sp) {203 error = Status::FromErrorStringWithFormat(204 "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided",205 __FUNCTION__);206 return error;207 }208 209 if (data_sp->GetByteSize() != m_reg_data.size()) {210 error = Status::FromErrorStringWithFormat(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 = Status::FromErrorStringWithFormat(220 "NativeRegisterContextFreeBSD_mips64::%s "221 "DataBuffer::GetBytes() returned a null "222 "pointer",223 __FUNCTION__);224 return error;225 }226 ::memcpy(m_reg_data.data(), src, m_reg_data.size());227 228 error = WriteRegisterSet(GPRegSet);229 if (error.Fail())230 return error;231 232 return WriteRegisterSet(FPRegSet);233}234 235llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom(236 NativeRegisterContextFreeBSD &source) {237 return llvm::Error::success();238}239 240#endif // defined (__mips64__)241