xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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 &reg_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 &reg_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