1be691f3bSpatrick //===-- NativeRegisterContextFreeBSD_mips64.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(__mips64__)
10be691f3bSpatrick
11be691f3bSpatrick #include "NativeRegisterContextFreeBSD_mips64.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"
18*f6aab3d8Srobert #include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.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
25*f6aab3d8Srobert #include <optional>
26be691f3bSpatrick
27be691f3bSpatrick using namespace lldb;
28be691f3bSpatrick using namespace lldb_private;
29be691f3bSpatrick using namespace lldb_private::process_freebsd;
30be691f3bSpatrick
31be691f3bSpatrick NativeRegisterContextFreeBSD *
CreateHostNativeRegisterContextFreeBSD(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)32be691f3bSpatrick NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
33be691f3bSpatrick const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
34be691f3bSpatrick return new NativeRegisterContextFreeBSD_mips64(target_arch, native_thread);
35be691f3bSpatrick }
36be691f3bSpatrick
NativeRegisterContextFreeBSD_mips64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)37be691f3bSpatrick NativeRegisterContextFreeBSD_mips64::NativeRegisterContextFreeBSD_mips64(
38be691f3bSpatrick const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
39be691f3bSpatrick : NativeRegisterContextRegisterInfo(
40be691f3bSpatrick native_thread, new RegisterContextFreeBSD_mips64(target_arch)) {}
41be691f3bSpatrick
42be691f3bSpatrick RegisterContextFreeBSD_mips64 &
GetRegisterInfo() const43be691f3bSpatrick NativeRegisterContextFreeBSD_mips64::GetRegisterInfo() const {
44be691f3bSpatrick return static_cast<RegisterContextFreeBSD_mips64 &>(
45be691f3bSpatrick *m_register_info_interface_up);
46be691f3bSpatrick }
47be691f3bSpatrick
GetRegisterSetCount() const48be691f3bSpatrick uint32_t NativeRegisterContextFreeBSD_mips64::GetRegisterSetCount() const {
49be691f3bSpatrick return GetRegisterInfo().GetRegisterSetCount();
50be691f3bSpatrick }
51be691f3bSpatrick
52be691f3bSpatrick const RegisterSet *
GetRegisterSet(uint32_t set_index) const53be691f3bSpatrick NativeRegisterContextFreeBSD_mips64::GetRegisterSet(uint32_t set_index) const {
54be691f3bSpatrick return GetRegisterInfo().GetRegisterSet(set_index);
55be691f3bSpatrick }
56be691f3bSpatrick
GetUserRegisterCount() const57be691f3bSpatrick uint32_t NativeRegisterContextFreeBSD_mips64::GetUserRegisterCount() const {
58be691f3bSpatrick uint32_t count = 0;
59be691f3bSpatrick for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
60be691f3bSpatrick count += GetRegisterSet(set_index)->num_registers;
61be691f3bSpatrick return count;
62be691f3bSpatrick }
63be691f3bSpatrick
64*f6aab3d8Srobert std::optional<NativeRegisterContextFreeBSD_mips64::RegSetKind>
GetSetForNativeRegNum(uint32_t reg_num) const65*f6aab3d8Srobert NativeRegisterContextFreeBSD_mips64::GetSetForNativeRegNum(
66*f6aab3d8Srobert uint32_t reg_num) const {
67*f6aab3d8Srobert switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
68*f6aab3d8Srobert case llvm::Triple::mips64:
69*f6aab3d8Srobert if (reg_num >= k_first_gpr_mips64 && reg_num <= k_last_gpr_mips64)
70*f6aab3d8Srobert return GPRegSet;
71*f6aab3d8Srobert if (reg_num >= k_first_fpr_mips64 && reg_num <= k_last_fpr_mips64)
72*f6aab3d8Srobert return FPRegSet;
73*f6aab3d8Srobert break;
74*f6aab3d8Srobert default:
75*f6aab3d8Srobert llvm_unreachable("Unhandled target architecture.");
76*f6aab3d8Srobert }
77*f6aab3d8Srobert
78*f6aab3d8Srobert llvm_unreachable("Register does not belong to any register set");
79*f6aab3d8Srobert }
80*f6aab3d8Srobert
ReadRegisterSet(RegSetKind set)81be691f3bSpatrick Status NativeRegisterContextFreeBSD_mips64::ReadRegisterSet(RegSetKind set) {
82be691f3bSpatrick switch (set) {
83be691f3bSpatrick case GPRegSet:
84be691f3bSpatrick return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
85be691f3bSpatrick m_reg_data.data());
86*f6aab3d8Srobert case FPRegSet:
87*f6aab3d8Srobert return NativeProcessFreeBSD::PtraceWrapper(
88*f6aab3d8Srobert PT_GETFPREGS, m_thread.GetID(),
89*f6aab3d8Srobert m_reg_data.data() + GetRegisterInfo().GetGPRSize());
90be691f3bSpatrick }
91be691f3bSpatrick llvm_unreachable("NativeRegisterContextFreeBSD_mips64::ReadRegisterSet");
92be691f3bSpatrick }
93be691f3bSpatrick
WriteRegisterSet(RegSetKind set)94be691f3bSpatrick Status NativeRegisterContextFreeBSD_mips64::WriteRegisterSet(RegSetKind set) {
95be691f3bSpatrick switch (set) {
96be691f3bSpatrick case GPRegSet:
97be691f3bSpatrick return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
98be691f3bSpatrick m_reg_data.data());
99*f6aab3d8Srobert case FPRegSet:
100*f6aab3d8Srobert return NativeProcessFreeBSD::PtraceWrapper(
101*f6aab3d8Srobert PT_SETFPREGS, m_thread.GetID(),
102*f6aab3d8Srobert m_reg_data.data() + GetRegisterInfo().GetGPRSize());
103be691f3bSpatrick }
104be691f3bSpatrick llvm_unreachable("NativeRegisterContextFreeBSD_mips64::WriteRegisterSet");
105be691f3bSpatrick }
106be691f3bSpatrick
107be691f3bSpatrick Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)108be691f3bSpatrick NativeRegisterContextFreeBSD_mips64::ReadRegister(const RegisterInfo *reg_info,
109be691f3bSpatrick RegisterValue ®_value) {
110be691f3bSpatrick Status error;
111be691f3bSpatrick
112be691f3bSpatrick if (!reg_info) {
113be691f3bSpatrick error.SetErrorString("reg_info NULL");
114be691f3bSpatrick return error;
115be691f3bSpatrick }
116be691f3bSpatrick
117be691f3bSpatrick const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
118be691f3bSpatrick
119be691f3bSpatrick if (reg == LLDB_INVALID_REGNUM)
120be691f3bSpatrick return Status("no lldb regnum for %s", reg_info && reg_info->name
121be691f3bSpatrick ? reg_info->name
122be691f3bSpatrick : "<unknown register>");
123be691f3bSpatrick
124*f6aab3d8Srobert std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
125*f6aab3d8Srobert if (!opt_set) {
126*f6aab3d8Srobert // This is likely an internal register for lldb use only and should not be
127*f6aab3d8Srobert // directly queried.
128*f6aab3d8Srobert error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
129*f6aab3d8Srobert reg_info->name);
130*f6aab3d8Srobert return error;
131*f6aab3d8Srobert }
132*f6aab3d8Srobert
133*f6aab3d8Srobert RegSetKind set = *opt_set;
134be691f3bSpatrick error = ReadRegisterSet(set);
135be691f3bSpatrick if (error.Fail())
136be691f3bSpatrick return error;
137be691f3bSpatrick
138be691f3bSpatrick assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
139be691f3bSpatrick reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
140be691f3bSpatrick reg_info->byte_size, endian::InlHostByteOrder());
141be691f3bSpatrick return error;
142be691f3bSpatrick }
143be691f3bSpatrick
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)144be691f3bSpatrick Status NativeRegisterContextFreeBSD_mips64::WriteRegister(
145be691f3bSpatrick const RegisterInfo *reg_info, const RegisterValue ®_value) {
146be691f3bSpatrick Status error;
147be691f3bSpatrick
148be691f3bSpatrick if (!reg_info)
149be691f3bSpatrick return Status("reg_info NULL");
150be691f3bSpatrick
151be691f3bSpatrick const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
152be691f3bSpatrick
153be691f3bSpatrick if (reg == LLDB_INVALID_REGNUM)
154be691f3bSpatrick return Status("no lldb regnum for %s", reg_info && reg_info->name
155be691f3bSpatrick ? reg_info->name
156be691f3bSpatrick : "<unknown register>");
157be691f3bSpatrick
158*f6aab3d8Srobert std::optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
159*f6aab3d8Srobert if (!opt_set) {
160*f6aab3d8Srobert // This is likely an internal register for lldb use only and should not be
161*f6aab3d8Srobert // directly queried.
162*f6aab3d8Srobert error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
163*f6aab3d8Srobert reg_info->name);
164*f6aab3d8Srobert return error;
165*f6aab3d8Srobert }
166*f6aab3d8Srobert
167*f6aab3d8Srobert RegSetKind set = *opt_set;
168be691f3bSpatrick error = ReadRegisterSet(set);
169be691f3bSpatrick if (error.Fail())
170be691f3bSpatrick return error;
171be691f3bSpatrick
172be691f3bSpatrick assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
173be691f3bSpatrick ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
174be691f3bSpatrick reg_info->byte_size);
175be691f3bSpatrick
176be691f3bSpatrick return WriteRegisterSet(set);
177be691f3bSpatrick }
178be691f3bSpatrick
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)179be691f3bSpatrick Status NativeRegisterContextFreeBSD_mips64::ReadAllRegisterValues(
180*f6aab3d8Srobert lldb::WritableDataBufferSP &data_sp) {
181be691f3bSpatrick Status error;
182be691f3bSpatrick
183be691f3bSpatrick error = ReadRegisterSet(GPRegSet);
184be691f3bSpatrick if (error.Fail())
185be691f3bSpatrick return error;
186be691f3bSpatrick
187*f6aab3d8Srobert error = ReadRegisterSet(FPRegSet);
188*f6aab3d8Srobert if (error.Fail())
189*f6aab3d8Srobert return error;
190*f6aab3d8Srobert
191be691f3bSpatrick data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
192be691f3bSpatrick uint8_t *dst = data_sp->GetBytes();
193be691f3bSpatrick ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
194be691f3bSpatrick
195be691f3bSpatrick return error;
196be691f3bSpatrick }
197be691f3bSpatrick
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)198be691f3bSpatrick Status NativeRegisterContextFreeBSD_mips64::WriteAllRegisterValues(
199be691f3bSpatrick const lldb::DataBufferSP &data_sp) {
200be691f3bSpatrick Status error;
201be691f3bSpatrick
202be691f3bSpatrick if (!data_sp) {
203be691f3bSpatrick error.SetErrorStringWithFormat(
204be691f3bSpatrick "NativeRegisterContextFreeBSD_mips64::%s invalid data_sp provided",
205be691f3bSpatrick __FUNCTION__);
206be691f3bSpatrick return error;
207be691f3bSpatrick }
208be691f3bSpatrick
209be691f3bSpatrick if (data_sp->GetByteSize() != m_reg_data.size()) {
210be691f3bSpatrick error.SetErrorStringWithFormat(
211be691f3bSpatrick "NativeRegisterContextFreeBSD_mips64::%s data_sp contained mismatched "
212be691f3bSpatrick "data size, expected %" PRIu64 ", actual %" PRIu64,
213be691f3bSpatrick __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
214be691f3bSpatrick return error;
215be691f3bSpatrick }
216be691f3bSpatrick
217*f6aab3d8Srobert const uint8_t *src = data_sp->GetBytes();
218be691f3bSpatrick if (src == nullptr) {
219be691f3bSpatrick error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_mips64::%s "
220be691f3bSpatrick "DataBuffer::GetBytes() returned a null "
221be691f3bSpatrick "pointer",
222be691f3bSpatrick __FUNCTION__);
223be691f3bSpatrick return error;
224be691f3bSpatrick }
225be691f3bSpatrick ::memcpy(m_reg_data.data(), src, m_reg_data.size());
226be691f3bSpatrick
227*f6aab3d8Srobert error = WriteRegisterSet(GPRegSet);
228*f6aab3d8Srobert if (error.Fail())
229*f6aab3d8Srobert return error;
230*f6aab3d8Srobert
231*f6aab3d8Srobert return WriteRegisterSet(FPRegSet);
232be691f3bSpatrick }
233be691f3bSpatrick
CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD & source)234be691f3bSpatrick llvm::Error NativeRegisterContextFreeBSD_mips64::CopyHardwareWatchpointsFrom(
235be691f3bSpatrick NativeRegisterContextFreeBSD &source) {
236be691f3bSpatrick return llvm::Error::success();
237be691f3bSpatrick }
238be691f3bSpatrick
239be691f3bSpatrick #endif // defined (__mips64__)
240