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