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