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