1 //===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 #if defined(__powerpc__)
11 #include "NativeRegisterContextFreeBSD_powerpc.h"
13 #include "lldb/Host/HostInfo.h"
14 #include "lldb/Utility/DataBufferHeap.h"
15 #include "lldb/Utility/RegisterValue.h"
16 #include "lldb/Utility/Status.h"
18 #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
19 // for register enum definitions
20 #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
23 #include <sys/param.h>
24 #include <sys/ptrace.h>
25 #include <sys/types.h>
30 using namespace lldb_private
;
31 using namespace lldb_private::process_freebsd
;
33 static const uint32_t g_gpr_regnums
[] = {
34 gpr_r0_powerpc
, gpr_r1_powerpc
, gpr_r2_powerpc
, gpr_r3_powerpc
,
35 gpr_r4_powerpc
, gpr_r5_powerpc
, gpr_r6_powerpc
, gpr_r7_powerpc
,
36 gpr_r8_powerpc
, gpr_r9_powerpc
, gpr_r10_powerpc
, gpr_r11_powerpc
,
37 gpr_r12_powerpc
, gpr_r13_powerpc
, gpr_r14_powerpc
, gpr_r15_powerpc
,
38 gpr_r16_powerpc
, gpr_r17_powerpc
, gpr_r18_powerpc
, gpr_r19_powerpc
,
39 gpr_r20_powerpc
, gpr_r21_powerpc
, gpr_r22_powerpc
, gpr_r23_powerpc
,
40 gpr_r24_powerpc
, gpr_r25_powerpc
, gpr_r26_powerpc
, gpr_r27_powerpc
,
41 gpr_r28_powerpc
, gpr_r29_powerpc
, gpr_r30_powerpc
, gpr_r31_powerpc
,
42 gpr_lr_powerpc
, gpr_cr_powerpc
, gpr_xer_powerpc
, gpr_ctr_powerpc
,
46 static const uint32_t g_fpr_regnums
[] = {
47 fpr_f0_powerpc
, fpr_f1_powerpc
, fpr_f2_powerpc
, fpr_f3_powerpc
,
48 fpr_f4_powerpc
, fpr_f5_powerpc
, fpr_f6_powerpc
, fpr_f7_powerpc
,
49 fpr_f8_powerpc
, fpr_f9_powerpc
, fpr_f10_powerpc
, fpr_f11_powerpc
,
50 fpr_f12_powerpc
, fpr_f13_powerpc
, fpr_f14_powerpc
, fpr_f15_powerpc
,
51 fpr_f16_powerpc
, fpr_f17_powerpc
, fpr_f18_powerpc
, fpr_f19_powerpc
,
52 fpr_f20_powerpc
, fpr_f21_powerpc
, fpr_f22_powerpc
, fpr_f23_powerpc
,
53 fpr_f24_powerpc
, fpr_f25_powerpc
, fpr_f26_powerpc
, fpr_f27_powerpc
,
54 fpr_f28_powerpc
, fpr_f29_powerpc
, fpr_f30_powerpc
, fpr_f31_powerpc
,
58 // Number of register sets provided by this context.
59 enum { k_num_register_sets
= 2 };
61 static const RegisterSet g_reg_sets_powerpc
[k_num_register_sets
] = {
62 {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc
,
64 {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc
,
68 NativeRegisterContextFreeBSD
*
69 NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
70 const ArchSpec
&target_arch
, NativeThreadProtocol
&native_thread
) {
71 return new NativeRegisterContextFreeBSD_powerpc(target_arch
, native_thread
);
74 static RegisterInfoInterface
*
75 CreateRegisterInfoInterface(const ArchSpec
&target_arch
) {
76 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
77 return new RegisterContextFreeBSD_powerpc32(target_arch
);
79 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
80 "Register setting path assumes this is a 64-bit host");
81 return new RegisterContextFreeBSD_powerpc64(target_arch
);
85 NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
86 const ArchSpec
&target_arch
, NativeThreadProtocol
&native_thread
)
87 : NativeRegisterContextRegisterInfo(
88 native_thread
, CreateRegisterInfoInterface(target_arch
)) {}
90 RegisterContextFreeBSD_powerpc
&
91 NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
92 return static_cast<RegisterContextFreeBSD_powerpc
&>(
93 *m_register_info_interface_up
);
96 uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
97 return k_num_register_sets
;
101 NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index
) const {
102 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
103 case llvm::Triple::ppc
:
104 return &g_reg_sets_powerpc
[set_index
];
106 llvm_unreachable("Unhandled target architecture.");
110 std::optional
<NativeRegisterContextFreeBSD_powerpc::RegSetKind
>
111 NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
112 uint32_t reg_num
) const {
113 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
114 case llvm::Triple::ppc
:
115 if (reg_num
>= k_first_gpr_powerpc
&& reg_num
<= k_last_gpr_powerpc
)
117 if (reg_num
>= k_first_fpr
&& reg_num
<= k_last_fpr
)
121 llvm_unreachable("Unhandled target architecture.");
124 llvm_unreachable("Register does not belong to any register set");
127 uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
129 for (uint32_t set_index
= 0; set_index
< GetRegisterSetCount(); ++set_index
)
130 count
+= GetRegisterSet(set_index
)->num_registers
;
134 Status
NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set
) {
137 return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS
, m_thread
.GetID(),
140 return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS
, m_thread
.GetID(),
141 m_reg_data
.data() + sizeof(reg
));
143 llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
146 Status
NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set
) {
149 return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS
, m_thread
.GetID(),
152 return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS
, m_thread
.GetID(),
153 m_reg_data
.data() + sizeof(reg
));
155 llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
159 NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo
*reg_info
,
160 RegisterValue
®_value
) {
164 error
.SetErrorString("reg_info NULL");
168 const uint32_t reg
= reg_info
->kinds
[lldb::eRegisterKindLLDB
];
170 if (reg
== LLDB_INVALID_REGNUM
)
171 return Status("no lldb regnum for %s", reg_info
&& reg_info
->name
173 : "<unknown register>");
175 std::optional
<RegSetKind
> opt_set
= GetSetForNativeRegNum(reg
);
177 // This is likely an internal register for lldb use only and should not be
179 error
.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
184 RegSetKind set
= *opt_set
;
185 error
= ReadRegisterSet(set
);
189 assert(reg_info
->byte_offset
+ reg_info
->byte_size
<= m_reg_data
.size());
190 reg_value
.SetBytes(m_reg_data
.data() + reg_info
->byte_offset
,
191 reg_info
->byte_size
, endian::InlHostByteOrder());
195 Status
NativeRegisterContextFreeBSD_powerpc::WriteRegister(
196 const RegisterInfo
*reg_info
, const RegisterValue
®_value
) {
200 return Status("reg_info NULL");
202 const uint32_t reg
= reg_info
->kinds
[lldb::eRegisterKindLLDB
];
204 if (reg
== LLDB_INVALID_REGNUM
)
205 return Status("no lldb regnum for %s", reg_info
&& reg_info
->name
207 : "<unknown register>");
209 std::optional
<RegSetKind
> opt_set
= GetSetForNativeRegNum(reg
);
211 // This is likely an internal register for lldb use only and should not be
213 error
.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
218 RegSetKind set
= *opt_set
;
219 error
= ReadRegisterSet(set
);
223 assert(reg_info
->byte_offset
+ reg_info
->byte_size
<= m_reg_data
.size());
224 ::memcpy(m_reg_data
.data() + reg_info
->byte_offset
, reg_value
.GetBytes(),
225 reg_info
->byte_size
);
227 return WriteRegisterSet(set
);
230 Status
NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
231 lldb::WritableDataBufferSP
&data_sp
) {
234 error
= ReadRegisterSet(GPRegSet
);
238 error
= ReadRegisterSet(FPRegSet
);
242 data_sp
.reset(new DataBufferHeap(m_reg_data
.size(), 0));
243 uint8_t *dst
= data_sp
->GetBytes();
244 ::memcpy(dst
, m_reg_data
.data(), m_reg_data
.size());
249 Status
NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
250 const lldb::DataBufferSP
&data_sp
) {
254 error
.SetErrorStringWithFormat(
255 "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
260 if (data_sp
->GetByteSize() != m_reg_data
.size()) {
261 error
.SetErrorStringWithFormat(
262 "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
263 "data size, expected %zu, actual %" PRIu64
,
264 __FUNCTION__
, m_reg_data
.size(), data_sp
->GetByteSize());
268 const uint8_t *src
= data_sp
->GetBytes();
269 if (src
== nullptr) {
270 error
.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
271 "DataBuffer::GetBytes() returned a null "
276 ::memcpy(m_reg_data
.data(), src
, m_reg_data
.size());
278 error
= WriteRegisterSet(GPRegSet
);
282 return WriteRegisterSet(FPRegSet
);
285 llvm::Error
NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
286 NativeRegisterContextFreeBSD
&source
) {
287 return llvm::Error::success();
290 #endif // defined (__powerpc__)