1bee4d6efSMichał Górny //===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===//
2bee4d6efSMichał Górny //
3bee4d6efSMichał Górny // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bee4d6efSMichał Górny // See https://llvm.org/LICENSE.txt for license information.
5bee4d6efSMichał Górny // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bee4d6efSMichał Górny //
7bee4d6efSMichał Górny //===----------------------------------------------------------------------===//
8bee4d6efSMichał Górny
9bee4d6efSMichał Górny #if defined(__powerpc__)
10bee4d6efSMichał Górny
11bee4d6efSMichał Górny #include "NativeRegisterContextFreeBSD_powerpc.h"
12bee4d6efSMichał Górny
13bee4d6efSMichał Górny #include "lldb/Host/HostInfo.h"
14bee4d6efSMichał Górny #include "lldb/Utility/DataBufferHeap.h"
15bee4d6efSMichał Górny #include "lldb/Utility/RegisterValue.h"
16bee4d6efSMichał Górny #include "lldb/Utility/Status.h"
17bee4d6efSMichał Górny
18bee4d6efSMichał Górny #include "Plugins/Process/FreeBSD/NativeProcessFreeBSD.h"
19bee4d6efSMichał Górny // for register enum definitions
20bee4d6efSMichał Górny #include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
21bee4d6efSMichał Górny
22bee4d6efSMichał Górny // clang-format off
23bee4d6efSMichał Górny #include <sys/param.h>
24bee4d6efSMichał Górny #include <sys/ptrace.h>
25bee4d6efSMichał Górny #include <sys/types.h>
26bee4d6efSMichał Górny // clang-format on
27bee4d6efSMichał Górny
28bee4d6efSMichał Górny using namespace lldb;
29bee4d6efSMichał Górny using namespace lldb_private;
30bee4d6efSMichał Górny using namespace lldb_private::process_freebsd;
31bee4d6efSMichał Górny
32bee4d6efSMichał Górny static const uint32_t g_gpr_regnums[] = {
33bee4d6efSMichał Górny gpr_r0_powerpc, gpr_r1_powerpc, gpr_r2_powerpc, gpr_r3_powerpc,
34bee4d6efSMichał Górny gpr_r4_powerpc, gpr_r5_powerpc, gpr_r6_powerpc, gpr_r7_powerpc,
35bee4d6efSMichał Górny gpr_r8_powerpc, gpr_r9_powerpc, gpr_r10_powerpc, gpr_r11_powerpc,
36bee4d6efSMichał Górny gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,
37bee4d6efSMichał Górny gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,
38bee4d6efSMichał Górny gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,
39bee4d6efSMichał Górny gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,
40bee4d6efSMichał Górny gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,
41bee4d6efSMichał Górny gpr_lr_powerpc, gpr_cr_powerpc, gpr_xer_powerpc, gpr_ctr_powerpc,
42bee4d6efSMichał Górny gpr_pc_powerpc,
43bee4d6efSMichał Górny };
44bee4d6efSMichał Górny
45bee4d6efSMichał Górny static const uint32_t g_fpr_regnums[] = {
46bee4d6efSMichał Górny fpr_f0_powerpc, fpr_f1_powerpc, fpr_f2_powerpc, fpr_f3_powerpc,
47bee4d6efSMichał Górny fpr_f4_powerpc, fpr_f5_powerpc, fpr_f6_powerpc, fpr_f7_powerpc,
48bee4d6efSMichał Górny fpr_f8_powerpc, fpr_f9_powerpc, fpr_f10_powerpc, fpr_f11_powerpc,
49bee4d6efSMichał Górny fpr_f12_powerpc, fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,
50bee4d6efSMichał Górny fpr_f16_powerpc, fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,
51bee4d6efSMichał Górny fpr_f20_powerpc, fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,
52bee4d6efSMichał Górny fpr_f24_powerpc, fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,
53bee4d6efSMichał Górny fpr_f28_powerpc, fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,
54bee4d6efSMichał Górny fpr_fpscr_powerpc,
55bee4d6efSMichał Górny };
56bee4d6efSMichał Górny
57bee4d6efSMichał Górny // Number of register sets provided by this context.
58bee4d6efSMichał Górny enum { k_num_register_sets = 2 };
59bee4d6efSMichał Górny
60bee4d6efSMichał Górny static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
61bee4d6efSMichał Górny {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,
62bee4d6efSMichał Górny g_gpr_regnums},
63bee4d6efSMichał Górny {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,
64bee4d6efSMichał Górny g_fpr_regnums},
65bee4d6efSMichał Górny };
66bee4d6efSMichał Górny
67bee4d6efSMichał Górny NativeRegisterContextFreeBSD *
CreateHostNativeRegisterContextFreeBSD(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)68bee4d6efSMichał Górny NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
69bee4d6efSMichał Górny const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
70bee4d6efSMichał Górny return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
71bee4d6efSMichał Górny }
72bee4d6efSMichał Górny
73bee4d6efSMichał Górny static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)74bee4d6efSMichał Górny CreateRegisterInfoInterface(const ArchSpec &target_arch) {
75bee4d6efSMichał Górny if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
76bee4d6efSMichał Górny return new RegisterContextFreeBSD_powerpc32(target_arch);
77bee4d6efSMichał Górny } else {
78bee4d6efSMichał Górny assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
79bee4d6efSMichał Górny "Register setting path assumes this is a 64-bit host");
80bee4d6efSMichał Górny return new RegisterContextFreeBSD_powerpc64(target_arch);
81bee4d6efSMichał Górny }
82bee4d6efSMichał Górny }
83bee4d6efSMichał Górny
NativeRegisterContextFreeBSD_powerpc(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)84bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
85bee4d6efSMichał Górny const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
86bee4d6efSMichał Górny : NativeRegisterContextRegisterInfo(
87bee4d6efSMichał Górny native_thread, CreateRegisterInfoInterface(target_arch)) {}
88bee4d6efSMichał Górny
89bee4d6efSMichał Górny RegisterContextFreeBSD_powerpc &
GetRegisterInfo() const90bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
91bee4d6efSMichał Górny return static_cast<RegisterContextFreeBSD_powerpc &>(
92bee4d6efSMichał Górny *m_register_info_interface_up);
93bee4d6efSMichał Górny }
94bee4d6efSMichał Górny
GetRegisterSetCount() const95bee4d6efSMichał Górny uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
96bee4d6efSMichał Górny return k_num_register_sets;
97bee4d6efSMichał Górny }
98bee4d6efSMichał Górny
99bee4d6efSMichał Górny const RegisterSet *
GetRegisterSet(uint32_t set_index) const100bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {
101bee4d6efSMichał Górny switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
102bee4d6efSMichał Górny case llvm::Triple::ppc:
103bee4d6efSMichał Górny return &g_reg_sets_powerpc[set_index];
104bee4d6efSMichał Górny default:
105bee4d6efSMichał Górny llvm_unreachable("Unhandled target architecture.");
106bee4d6efSMichał Górny }
107bee4d6efSMichał Górny }
108bee4d6efSMichał Górny
109bee4d6efSMichał Górny llvm::Optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>
GetSetForNativeRegNum(uint32_t reg_num) const110bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
111bee4d6efSMichał Górny uint32_t reg_num) const {
112bee4d6efSMichał Górny switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
113bee4d6efSMichał Górny case llvm::Triple::ppc:
114bee4d6efSMichał Górny if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)
115bee4d6efSMichał Górny return GPRegSet;
116bee4d6efSMichał Górny if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)
117bee4d6efSMichał Górny return FPRegSet;
118bee4d6efSMichał Górny break;
119bee4d6efSMichał Górny default:
120bee4d6efSMichał Górny llvm_unreachable("Unhandled target architecture.");
121bee4d6efSMichał Górny }
122bee4d6efSMichał Górny
123bee4d6efSMichał Górny llvm_unreachable("Register does not belong to any register set");
124bee4d6efSMichał Górny }
125bee4d6efSMichał Górny
GetUserRegisterCount() const126bee4d6efSMichał Górny uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
127bee4d6efSMichał Górny uint32_t count = 0;
128bee4d6efSMichał Górny for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
129bee4d6efSMichał Górny count += GetRegisterSet(set_index)->num_registers;
130bee4d6efSMichał Górny return count;
131bee4d6efSMichał Górny }
132bee4d6efSMichał Górny
ReadRegisterSet(RegSetKind set)133bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {
134bee4d6efSMichał Górny switch (set) {
135bee4d6efSMichał Górny case GPRegSet:
136bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
137bee4d6efSMichał Górny m_reg_data.data());
138bee4d6efSMichał Górny case FPRegSet:
139bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_GETFPREGS, m_thread.GetID(),
140bee4d6efSMichał Górny m_reg_data.data() + sizeof(reg));
141bee4d6efSMichał Górny }
142bee4d6efSMichał Górny llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
143bee4d6efSMichał Górny }
144bee4d6efSMichał Górny
WriteRegisterSet(RegSetKind set)145bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {
146bee4d6efSMichał Górny switch (set) {
147bee4d6efSMichał Górny case GPRegSet:
148bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
149bee4d6efSMichał Górny m_reg_data.data());
150bee4d6efSMichał Górny case FPRegSet:
151bee4d6efSMichał Górny return NativeProcessFreeBSD::PtraceWrapper(PT_SETFPREGS, m_thread.GetID(),
152bee4d6efSMichał Górny m_reg_data.data() + sizeof(reg));
153bee4d6efSMichał Górny }
154bee4d6efSMichał Górny llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
155bee4d6efSMichał Górny }
156bee4d6efSMichał Górny
157bee4d6efSMichał Górny Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)158bee4d6efSMichał Górny NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,
159bee4d6efSMichał Górny RegisterValue ®_value) {
160bee4d6efSMichał Górny Status error;
161bee4d6efSMichał Górny
162bee4d6efSMichał Górny if (!reg_info) {
163bee4d6efSMichał Górny error.SetErrorString("reg_info NULL");
164bee4d6efSMichał Górny return error;
165bee4d6efSMichał Górny }
166bee4d6efSMichał Górny
167bee4d6efSMichał Górny const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
168bee4d6efSMichał Górny
169bee4d6efSMichał Górny if (reg == LLDB_INVALID_REGNUM)
170bee4d6efSMichał Górny return Status("no lldb regnum for %s", reg_info && reg_info->name
171bee4d6efSMichał Górny ? reg_info->name
172bee4d6efSMichał Górny : "<unknown register>");
173bee4d6efSMichał Górny
174bee4d6efSMichał Górny llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
175bee4d6efSMichał Górny if (!opt_set) {
176bee4d6efSMichał Górny // This is likely an internal register for lldb use only and should not be
177bee4d6efSMichał Górny // directly queried.
178bee4d6efSMichał Górny error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
179bee4d6efSMichał Górny reg_info->name);
180bee4d6efSMichał Górny return error;
181bee4d6efSMichał Górny }
182bee4d6efSMichał Górny
183bee4d6efSMichał Górny RegSetKind set = opt_set.getValue();
184bee4d6efSMichał Górny error = ReadRegisterSet(set);
185bee4d6efSMichał Górny if (error.Fail())
186bee4d6efSMichał Górny return error;
187bee4d6efSMichał Górny
188bee4d6efSMichał Górny assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
189bee4d6efSMichał Górny reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
190bee4d6efSMichał Górny reg_info->byte_size, endian::InlHostByteOrder());
191bee4d6efSMichał Górny return error;
192bee4d6efSMichał Górny }
193bee4d6efSMichał Górny
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)194bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(
195bee4d6efSMichał Górny const RegisterInfo *reg_info, const RegisterValue ®_value) {
196bee4d6efSMichał Górny Status error;
197bee4d6efSMichał Górny
198bee4d6efSMichał Górny if (!reg_info)
199bee4d6efSMichał Górny return Status("reg_info NULL");
200bee4d6efSMichał Górny
201bee4d6efSMichał Górny const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
202bee4d6efSMichał Górny
203bee4d6efSMichał Górny if (reg == LLDB_INVALID_REGNUM)
204bee4d6efSMichał Górny return Status("no lldb regnum for %s", reg_info && reg_info->name
205bee4d6efSMichał Górny ? reg_info->name
206bee4d6efSMichał Górny : "<unknown register>");
207bee4d6efSMichał Górny
208bee4d6efSMichał Górny llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
209bee4d6efSMichał Górny if (!opt_set) {
210bee4d6efSMichał Górny // This is likely an internal register for lldb use only and should not be
211bee4d6efSMichał Górny // directly queried.
212bee4d6efSMichał Górny error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
213bee4d6efSMichał Górny reg_info->name);
214bee4d6efSMichał Górny return error;
215bee4d6efSMichał Górny }
216bee4d6efSMichał Górny
217bee4d6efSMichał Górny RegSetKind set = opt_set.getValue();
218bee4d6efSMichał Górny error = ReadRegisterSet(set);
219bee4d6efSMichał Górny if (error.Fail())
220bee4d6efSMichał Górny return error;
221bee4d6efSMichał Górny
222bee4d6efSMichał Górny assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
223bee4d6efSMichał Górny ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
224bee4d6efSMichał Górny reg_info->byte_size);
225bee4d6efSMichał Górny
226bee4d6efSMichał Górny return WriteRegisterSet(set);
227bee4d6efSMichał Górny }
228bee4d6efSMichał Górny
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)229bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
230c2f64601SJonas Devlieghere lldb::WritableDataBufferSP &data_sp) {
231bee4d6efSMichał Górny Status error;
232bee4d6efSMichał Górny
233bee4d6efSMichał Górny error = ReadRegisterSet(GPRegSet);
234bee4d6efSMichał Górny if (error.Fail())
235bee4d6efSMichał Górny return error;
236bee4d6efSMichał Górny
237bee4d6efSMichał Górny error = ReadRegisterSet(FPRegSet);
238bee4d6efSMichał Górny if (error.Fail())
239bee4d6efSMichał Górny return error;
240bee4d6efSMichał Górny
241bee4d6efSMichał Górny data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
242bee4d6efSMichał Górny uint8_t *dst = data_sp->GetBytes();
243bee4d6efSMichał Górny ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
244bee4d6efSMichał Górny
245bee4d6efSMichał Górny return error;
246bee4d6efSMichał Górny }
247bee4d6efSMichał Górny
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)248bee4d6efSMichał Górny Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
249bee4d6efSMichał Górny const lldb::DataBufferSP &data_sp) {
250bee4d6efSMichał Górny Status error;
251bee4d6efSMichał Górny
252bee4d6efSMichał Górny if (!data_sp) {
253bee4d6efSMichał Górny error.SetErrorStringWithFormat(
254bee4d6efSMichał Górny "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
255bee4d6efSMichał Górny __FUNCTION__);
256bee4d6efSMichał Górny return error;
257bee4d6efSMichał Górny }
258bee4d6efSMichał Górny
259bee4d6efSMichał Górny if (data_sp->GetByteSize() != m_reg_data.size()) {
260bee4d6efSMichał Górny error.SetErrorStringWithFormat(
261bee4d6efSMichał Górny "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
262bee4d6efSMichał Górny "data size, expected %zu, actual %" PRIu64,
263bee4d6efSMichał Górny __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
264bee4d6efSMichał Górny return error;
265bee4d6efSMichał Górny }
266bee4d6efSMichał Górny
267*470eb5c2SJonas Devlieghere const uint8_t *src = data_sp->GetBytes();
268bee4d6efSMichał Górny if (src == nullptr) {
269bee4d6efSMichał Górny error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
270bee4d6efSMichał Górny "DataBuffer::GetBytes() returned a null "
271bee4d6efSMichał Górny "pointer",
272bee4d6efSMichał Górny __FUNCTION__);
273bee4d6efSMichał Górny return error;
274bee4d6efSMichał Górny }
275bee4d6efSMichał Górny ::memcpy(m_reg_data.data(), src, m_reg_data.size());
276bee4d6efSMichał Górny
277bee4d6efSMichał Górny error = WriteRegisterSet(GPRegSet);
278bee4d6efSMichał Górny if (error.Fail())
279bee4d6efSMichał Górny return error;
280bee4d6efSMichał Górny
281bee4d6efSMichał Górny return WriteRegisterSet(FPRegSet);
282bee4d6efSMichał Górny }
283bee4d6efSMichał Górny
CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD & source)284bee4d6efSMichał Górny llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
285bee4d6efSMichał Górny NativeRegisterContextFreeBSD &source) {
286bee4d6efSMichał Górny return llvm::Error::success();
287bee4d6efSMichał Górny }
288bee4d6efSMichał Górny
289bee4d6efSMichał Górny #endif // defined (__powerpc__)
290