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