1 //===-- NativeRegisterContextFreeBSD_arm64.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(__aarch64__) 10 11 #include "NativeRegisterContextFreeBSD_arm64.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/RegisterInfoPOSIX_arm64.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_arm64(target_arch, native_thread); 34 } 35 36 NativeRegisterContextFreeBSD_arm64::NativeRegisterContextFreeBSD_arm64( 37 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) 38 : NativeRegisterContextRegisterInfo( 39 native_thread, new RegisterInfoPOSIX_arm64(target_arch)) { 40 GetRegisterInfo().ConfigureVectorRegisterInfos( 41 RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64); 42 } 43 44 RegisterInfoPOSIX_arm64 & 45 NativeRegisterContextFreeBSD_arm64::GetRegisterInfo() const { 46 return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up); 47 } 48 49 uint32_t NativeRegisterContextFreeBSD_arm64::GetRegisterSetCount() const { 50 return GetRegisterInfo().GetRegisterSetCount(); 51 } 52 53 const RegisterSet * 54 NativeRegisterContextFreeBSD_arm64::GetRegisterSet(uint32_t set_index) const { 55 return GetRegisterInfo().GetRegisterSet(set_index); 56 } 57 58 uint32_t NativeRegisterContextFreeBSD_arm64::GetUserRegisterCount() const { 59 uint32_t count = 0; 60 for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index) 61 count += GetRegisterSet(set_index)->num_registers; 62 return count; 63 } 64 65 Status NativeRegisterContextFreeBSD_arm64::ReadRegisterSet(uint32_t set) { 66 switch (set) { 67 case RegisterInfoPOSIX_arm64::GPRegSet: 68 return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(), 69 m_reg_data.data()); 70 case RegisterInfoPOSIX_arm64::FPRegSet: 71 return NativeProcessFreeBSD::PtraceWrapper( 72 PT_GETFPREGS, m_thread.GetID(), 73 m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); 74 case RegisterInfoPOSIX_arm64::SVERegSet: 75 return Status("not supported"); 76 } 77 llvm_unreachable("NativeRegisterContextFreeBSD_arm64::ReadRegisterSet"); 78 } 79 80 Status NativeRegisterContextFreeBSD_arm64::WriteRegisterSet(uint32_t set) { 81 switch (set) { 82 case RegisterInfoPOSIX_arm64::GPRegSet: 83 return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(), 84 m_reg_data.data()); 85 case RegisterInfoPOSIX_arm64::FPRegSet: 86 return NativeProcessFreeBSD::PtraceWrapper( 87 PT_SETFPREGS, m_thread.GetID(), 88 m_reg_data.data() + sizeof(RegisterInfoPOSIX_arm64::GPR)); 89 case RegisterInfoPOSIX_arm64::SVERegSet: 90 return Status("not supported"); 91 } 92 llvm_unreachable("NativeRegisterContextFreeBSD_arm64::WriteRegisterSet"); 93 } 94 95 Status 96 NativeRegisterContextFreeBSD_arm64::ReadRegister(const RegisterInfo *reg_info, 97 RegisterValue ®_value) { 98 Status error; 99 100 if (!reg_info) { 101 error.SetErrorString("reg_info NULL"); 102 return error; 103 } 104 105 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 106 107 if (reg == LLDB_INVALID_REGNUM) 108 return Status("no lldb regnum for %s", reg_info && reg_info->name 109 ? reg_info->name 110 : "<unknown register>"); 111 112 uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg); 113 error = ReadRegisterSet(set); 114 if (error.Fail()) 115 return error; 116 117 assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 118 reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset, 119 reg_info->byte_size, endian::InlHostByteOrder()); 120 return error; 121 } 122 123 Status NativeRegisterContextFreeBSD_arm64::WriteRegister( 124 const RegisterInfo *reg_info, const RegisterValue ®_value) { 125 Status error; 126 127 if (!reg_info) 128 return Status("reg_info NULL"); 129 130 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 131 132 if (reg == LLDB_INVALID_REGNUM) 133 return Status("no lldb regnum for %s", reg_info && reg_info->name 134 ? reg_info->name 135 : "<unknown register>"); 136 137 uint32_t set = GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg); 138 error = ReadRegisterSet(set); 139 if (error.Fail()) 140 return error; 141 142 assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size()); 143 ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(), 144 reg_info->byte_size); 145 146 return WriteRegisterSet(set); 147 } 148 149 Status NativeRegisterContextFreeBSD_arm64::ReadAllRegisterValues( 150 lldb::DataBufferSP &data_sp) { 151 Status error; 152 153 error = ReadRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet); 154 if (error.Fail()) 155 return error; 156 157 error = ReadRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet); 158 if (error.Fail()) 159 return error; 160 161 data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0)); 162 uint8_t *dst = data_sp->GetBytes(); 163 ::memcpy(dst, m_reg_data.data(), m_reg_data.size()); 164 165 return error; 166 } 167 168 Status NativeRegisterContextFreeBSD_arm64::WriteAllRegisterValues( 169 const lldb::DataBufferSP &data_sp) { 170 Status error; 171 172 if (!data_sp) { 173 error.SetErrorStringWithFormat( 174 "NativeRegisterContextFreeBSD_arm64::%s invalid data_sp provided", 175 __FUNCTION__); 176 return error; 177 } 178 179 if (data_sp->GetByteSize() != m_reg_data.size()) { 180 error.SetErrorStringWithFormat( 181 "NativeRegisterContextFreeBSD_arm64::%s data_sp contained mismatched " 182 "data size, expected %" PRIu64 ", actual %" PRIu64, 183 __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize()); 184 return error; 185 } 186 187 uint8_t *src = data_sp->GetBytes(); 188 if (src == nullptr) { 189 error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_arm64::%s " 190 "DataBuffer::GetBytes() returned a null " 191 "pointer", 192 __FUNCTION__); 193 return error; 194 } 195 ::memcpy(m_reg_data.data(), src, m_reg_data.size()); 196 197 error = WriteRegisterSet(RegisterInfoPOSIX_arm64::GPRegSet); 198 if (error.Fail()) 199 return error; 200 201 return WriteRegisterSet(RegisterInfoPOSIX_arm64::FPRegSet); 202 } 203 204 llvm::Error NativeRegisterContextFreeBSD_arm64::CopyHardwareWatchpointsFrom( 205 NativeRegisterContextFreeBSD &source) { 206 return llvm::Error::success(); 207 } 208 209 #endif // defined (__aarch64__) 210