204 lines · cpp
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-exception6//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 off21#include <sys/param.h>22#include <sys/ptrace.h>23#include <sys/types.h>24// clang-format on25 26using namespace lldb;27using namespace lldb_private;28using namespace lldb_private::process_freebsd;29 30NativeRegisterContextFreeBSD *31NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(32 const ArchSpec &target_arch, NativeThreadFreeBSD &native_thread) {33 return new NativeRegisterContextFreeBSD_arm(target_arch, native_thread);34}35 36NativeRegisterContextFreeBSD_arm::NativeRegisterContextFreeBSD_arm(37 const ArchSpec &target_arch, NativeThreadFreeBSD &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 88Status89NativeRegisterContextFreeBSD_arm::ReadRegister(const RegisterInfo *reg_info,90 RegisterValue ®_value) {91 Status error;92 93 if (!reg_info) {94 error = Status::FromErrorString("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::FromErrorStringWithFormat(102 "no lldb regnum for %s",103 reg_info && reg_info->name ? reg_info->name : "<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::FromErrorString("reg_info NULL");122 123 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];124 125 if (reg == LLDB_INVALID_REGNUM)126 return Status::FromErrorStringWithFormat(127 "no lldb regnum for %s",128 reg_info && reg_info->name ? reg_info->name : "<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 = Status::FromErrorStringWithFormat(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 = Status::FromErrorStringWithFormat(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 = Status::FromErrorStringWithFormat(183 "NativeRegisterContextFreeBSD_arm::%s "184 "DataBuffer::GetBytes() returned a null "185 "pointer",186 __FUNCTION__);187 return error;188 }189 ::memcpy(m_reg_data.data(), src, m_reg_data.size());190 191 error = WriteRegisterSet(RegisterInfoPOSIX_arm::GPRegSet);192 if (error.Fail())193 return error;194 195 return WriteRegisterSet(RegisterInfoPOSIX_arm::FPRegSet);196}197 198llvm::Error NativeRegisterContextFreeBSD_arm::CopyHardwareWatchpointsFrom(199 NativeRegisterContextFreeBSD &source) {200 return llvm::Error::success();201}202 203#endif // defined (__arm__)204