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