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