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