1 //===-- NativeRegisterContextNetBSD_x86_64.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(__i386__) || defined(__x86_64__)
10
11 #include "NativeRegisterContextNetBSD_x86_64.h"
12
13 #include "lldb/Host/HostInfo.h"
14 #include "lldb/Utility/DataBufferHeap.h"
15 #include "lldb/Utility/Log.h"
16 #include "lldb/Utility/RegisterValue.h"
17 #include "lldb/Utility/Status.h"
18
19 #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
20 #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
21
22 // clang-format off
23 #include <sys/types.h>
24 #include <sys/ptrace.h>
25 #include <sys/sysctl.h>
26 #include <sys/uio.h>
27 #include <x86/cpu.h>
28 #include <x86/cpu_extended_state.h>
29 #include <x86/specialreg.h>
30 #include <elf.h>
31 #include <err.h>
32 #include <cstdint>
33 #include <cstdlib>
34 // clang-format on
35
36 using namespace lldb_private;
37 using namespace lldb_private::process_netbsd;
38
39 // x86 64-bit general purpose registers.
40 static const uint32_t g_gpr_regnums_x86_64[] = {
41 lldb_rax_x86_64, lldb_rbx_x86_64, lldb_rcx_x86_64, lldb_rdx_x86_64,
42 lldb_rdi_x86_64, lldb_rsi_x86_64, lldb_rbp_x86_64, lldb_rsp_x86_64,
43 lldb_r8_x86_64, lldb_r9_x86_64, lldb_r10_x86_64, lldb_r11_x86_64,
44 lldb_r12_x86_64, lldb_r13_x86_64, lldb_r14_x86_64, lldb_r15_x86_64,
45 lldb_rip_x86_64, lldb_rflags_x86_64, lldb_cs_x86_64, lldb_fs_x86_64,
46 lldb_gs_x86_64, lldb_ss_x86_64, lldb_ds_x86_64, lldb_es_x86_64,
47 lldb_eax_x86_64, lldb_ebx_x86_64, lldb_ecx_x86_64, lldb_edx_x86_64,
48 lldb_edi_x86_64, lldb_esi_x86_64, lldb_ebp_x86_64, lldb_esp_x86_64,
49 lldb_r8d_x86_64, // Low 32 bits or r8
50 lldb_r9d_x86_64, // Low 32 bits or r9
51 lldb_r10d_x86_64, // Low 32 bits or r10
52 lldb_r11d_x86_64, // Low 32 bits or r11
53 lldb_r12d_x86_64, // Low 32 bits or r12
54 lldb_r13d_x86_64, // Low 32 bits or r13
55 lldb_r14d_x86_64, // Low 32 bits or r14
56 lldb_r15d_x86_64, // Low 32 bits or r15
57 lldb_ax_x86_64, lldb_bx_x86_64, lldb_cx_x86_64, lldb_dx_x86_64,
58 lldb_di_x86_64, lldb_si_x86_64, lldb_bp_x86_64, lldb_sp_x86_64,
59 lldb_r8w_x86_64, // Low 16 bits or r8
60 lldb_r9w_x86_64, // Low 16 bits or r9
61 lldb_r10w_x86_64, // Low 16 bits or r10
62 lldb_r11w_x86_64, // Low 16 bits or r11
63 lldb_r12w_x86_64, // Low 16 bits or r12
64 lldb_r13w_x86_64, // Low 16 bits or r13
65 lldb_r14w_x86_64, // Low 16 bits or r14
66 lldb_r15w_x86_64, // Low 16 bits or r15
67 lldb_ah_x86_64, lldb_bh_x86_64, lldb_ch_x86_64, lldb_dh_x86_64,
68 lldb_al_x86_64, lldb_bl_x86_64, lldb_cl_x86_64, lldb_dl_x86_64,
69 lldb_dil_x86_64, lldb_sil_x86_64, lldb_bpl_x86_64, lldb_spl_x86_64,
70 lldb_r8l_x86_64, // Low 8 bits or r8
71 lldb_r9l_x86_64, // Low 8 bits or r9
72 lldb_r10l_x86_64, // Low 8 bits or r10
73 lldb_r11l_x86_64, // Low 8 bits or r11
74 lldb_r12l_x86_64, // Low 8 bits or r12
75 lldb_r13l_x86_64, // Low 8 bits or r13
76 lldb_r14l_x86_64, // Low 8 bits or r14
77 lldb_r15l_x86_64, // Low 8 bits or r15
78 LLDB_INVALID_REGNUM // register sets need to end with this flag
79 };
80 static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
81 1 ==
82 k_num_gpr_registers_x86_64,
83 "g_gpr_regnums_x86_64 has wrong number of register infos");
84
85 // x86 64-bit floating point registers.
86 static const uint32_t g_fpu_regnums_x86_64[] = {
87 lldb_fctrl_x86_64, lldb_fstat_x86_64, lldb_ftag_x86_64,
88 lldb_fop_x86_64, lldb_fiseg_x86_64, lldb_fioff_x86_64,
89 lldb_fip_x86_64, lldb_foseg_x86_64, lldb_fooff_x86_64,
90 lldb_fdp_x86_64, lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64,
91 lldb_st0_x86_64, lldb_st1_x86_64, lldb_st2_x86_64,
92 lldb_st3_x86_64, lldb_st4_x86_64, lldb_st5_x86_64,
93 lldb_st6_x86_64, lldb_st7_x86_64, lldb_mm0_x86_64,
94 lldb_mm1_x86_64, lldb_mm2_x86_64, lldb_mm3_x86_64,
95 lldb_mm4_x86_64, lldb_mm5_x86_64, lldb_mm6_x86_64,
96 lldb_mm7_x86_64, lldb_xmm0_x86_64, lldb_xmm1_x86_64,
97 lldb_xmm2_x86_64, lldb_xmm3_x86_64, lldb_xmm4_x86_64,
98 lldb_xmm5_x86_64, lldb_xmm6_x86_64, lldb_xmm7_x86_64,
99 lldb_xmm8_x86_64, lldb_xmm9_x86_64, lldb_xmm10_x86_64,
100 lldb_xmm11_x86_64, lldb_xmm12_x86_64, lldb_xmm13_x86_64,
101 lldb_xmm14_x86_64, lldb_xmm15_x86_64,
102 LLDB_INVALID_REGNUM // register sets need to end with this flag
103 };
104 static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
105 1 ==
106 k_num_fpr_registers_x86_64,
107 "g_fpu_regnums_x86_64 has wrong number of register infos");
108
109 static const uint32_t g_avx_regnums_x86_64[] = {
110 lldb_ymm0_x86_64, lldb_ymm1_x86_64, lldb_ymm2_x86_64, lldb_ymm3_x86_64,
111 lldb_ymm4_x86_64, lldb_ymm5_x86_64, lldb_ymm6_x86_64, lldb_ymm7_x86_64,
112 lldb_ymm8_x86_64, lldb_ymm9_x86_64, lldb_ymm10_x86_64, lldb_ymm11_x86_64,
113 lldb_ymm12_x86_64, lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
114 LLDB_INVALID_REGNUM // register sets need to end with this flag
115 };
116 static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
117 1 ==
118 k_num_avx_registers_x86_64,
119 "g_avx_regnums_x86_64 has wrong number of register infos");
120
121 static const uint32_t g_mpx_regnums_x86_64[] = {
122 // Note: we currently do not provide them but this is needed to avoid
123 // unnamed groups in SBFrame::GetRegisterContext().
124 lldb_bnd0_x86_64, lldb_bnd1_x86_64, lldb_bnd2_x86_64,
125 lldb_bnd3_x86_64, lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
126 LLDB_INVALID_REGNUM // register sets need to end with this flag
127 };
128 static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
129 1 ==
130 k_num_mpx_registers_x86_64,
131 "g_mpx_regnums_x86_64 has wrong number of register infos");
132
133 // x86 debug registers.
134 static const uint32_t g_dbr_regnums_x86_64[] = {
135 lldb_dr0_x86_64, lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64,
136 lldb_dr4_x86_64, lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64,
137 LLDB_INVALID_REGNUM // register sets need to end with this flag
138 };
139 static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
140 1 ==
141 k_num_dbr_registers_x86_64,
142 "g_dbr_regnums_x86_64 has wrong number of register infos");
143
144 // x86 32-bit general purpose registers.
145 static const uint32_t g_gpr_regnums_i386[] = {
146 lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386,
147 lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386,
148 lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386,
149 lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386,
150 lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386,
151 lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386,
152 lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386,
153 lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386,
154 LLDB_INVALID_REGNUM // register sets need to end with this flag
155 };
156 static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
157 1 ==
158 k_num_gpr_registers_i386,
159 "g_gpr_regnums_i386 has wrong number of register infos");
160
161 // x86 32-bit floating point registers.
162 static const uint32_t g_fpu_regnums_i386[] = {
163 lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386,
164 lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386,
165 lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386,
166 lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386,
167 lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386,
168 lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386,
169 lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386,
170 lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386,
171 lldb_xmm6_i386, lldb_xmm7_i386,
172 LLDB_INVALID_REGNUM // register sets need to end with this flag
173 };
174 static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
175 1 ==
176 k_num_fpr_registers_i386,
177 "g_fpu_regnums_i386 has wrong number of register infos");
178
179 static const uint32_t g_avx_regnums_i386[] = {
180 lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
181 lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
182 LLDB_INVALID_REGNUM // register sets need to end with this flag
183 };
184 static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
185 1 ==
186 k_num_avx_registers_i386,
187 "g_avx_regnums_i386 has wrong number of register infos");
188
189 static const uint32_t g_mpx_regnums_i386[] = {
190 // Note: we currently do not provide them but this is needed to avoid
191 // unnamed groups in SBFrame::GetRegisterContext().
192 lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386,
193 lldb_bnd3_i386, lldb_bndcfgu_i386, lldb_bndstatus_i386,
194 LLDB_INVALID_REGNUM // register sets need to end with this flag
195 };
196 static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
197 1 ==
198 k_num_mpx_registers_i386,
199 "g_mpx_regnums_i386 has wrong number of register infos");
200
201 // x86 debug registers.
202 static const uint32_t g_dbr_regnums_i386[] = {
203 lldb_dr0_i386, lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386,
204 lldb_dr4_i386, lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386,
205 LLDB_INVALID_REGNUM // register sets need to end with this flag
206 };
207 static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) -
208 1 ==
209 k_num_dbr_registers_i386,
210 "g_dbr_regnums_i386 has wrong number of register infos");
211
212 // Number of register sets provided by this context.
213 enum { k_num_register_sets = 5 };
214
215 // Register sets for x86 32-bit.
216 static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
217 {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
218 g_gpr_regnums_i386},
219 {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
220 g_fpu_regnums_i386},
221 {"Debug Registers", "dbr", k_num_dbr_registers_i386, g_dbr_regnums_i386},
222 {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
223 g_avx_regnums_i386},
224 {"Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
225 g_mpx_regnums_i386},
226 };
227
228 // Register sets for x86 64-bit.
229 static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
230 {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
231 g_gpr_regnums_x86_64},
232 {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
233 g_fpu_regnums_x86_64},
234 {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
235 g_dbr_regnums_x86_64},
236 {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
237 g_avx_regnums_x86_64},
238 {"Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
239 g_mpx_regnums_x86_64},
240 };
241
242 #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
243
244 NativeRegisterContextNetBSD *
CreateHostNativeRegisterContextNetBSD(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)245 NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
246 const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
247 return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread);
248 }
249
250 // NativeRegisterContextNetBSD_x86_64 members.
251
252 static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)253 CreateRegisterInfoInterface(const ArchSpec &target_arch) {
254 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
255 // 32-bit hosts run with a RegisterContextNetBSD_i386 context.
256 return new RegisterContextNetBSD_i386(target_arch);
257 } else {
258 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
259 "Register setting path assumes this is a 64-bit host");
260 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
261 // x86_64 register context.
262 return new RegisterContextNetBSD_x86_64(target_arch);
263 }
264 }
265
NativeRegisterContextNetBSD_x86_64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)266 NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
267 const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
268 : NativeRegisterContextRegisterInfo(
269 native_thread, CreateRegisterInfoInterface(target_arch)),
270 NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
271 assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
272 std::array<uint32_t, MaxRegularRegSet + 1> first_regnos;
273
274 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
275 case llvm::Triple::x86:
276 first_regnos[FPRegSet] = lldb_fctrl_i386;
277 first_regnos[DBRegSet] = lldb_dr0_i386;
278 break;
279 case llvm::Triple::x86_64:
280 first_regnos[FPRegSet] = lldb_fctrl_x86_64;
281 first_regnos[DBRegSet] = lldb_dr0_x86_64;
282 break;
283 default:
284 llvm_unreachable("Unhandled target architecture.");
285 }
286
287 for (int i : {FPRegSet, DBRegSet})
288 m_regset_offsets[i] = GetRegisterInfoInterface()
289 .GetRegisterInfo()[first_regnos[i]]
290 .byte_offset;
291 }
292
GetRegisterSetCount() const293 uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const {
294 return k_num_register_sets;
295 }
296
297 const RegisterSet *
GetRegisterSet(uint32_t set_index) const298 NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
299 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
300 case llvm::Triple::x86:
301 return &g_reg_sets_i386[set_index];
302 case llvm::Triple::x86_64:
303 return &g_reg_sets_x86_64[set_index];
304 default:
305 llvm_unreachable("Unhandled target architecture.");
306 }
307 }
308
309 llvm::Optional<NativeRegisterContextNetBSD_x86_64::RegSetKind>
GetSetForNativeRegNum(uint32_t reg_num) const310 NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
311 uint32_t reg_num) const {
312 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
313 case llvm::Triple::x86:
314 if (reg_num >= k_first_gpr_i386 && reg_num <= k_last_gpr_i386)
315 return GPRegSet;
316 if (reg_num >= k_first_fpr_i386 && reg_num <= k_last_fpr_i386)
317 return FPRegSet;
318 if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386)
319 return YMMRegSet;
320 if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386)
321 return llvm::None; // MPXR
322 if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386)
323 return llvm::None; // MPXC
324 if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386)
325 return DBRegSet; // DBR
326 break;
327 case llvm::Triple::x86_64:
328 if (reg_num >= k_first_gpr_x86_64 && reg_num <= k_last_gpr_x86_64)
329 return GPRegSet;
330 if (reg_num >= k_first_fpr_x86_64 && reg_num <= k_last_fpr_x86_64)
331 return FPRegSet;
332 if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64)
333 return YMMRegSet;
334 if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64)
335 return llvm::None; // MPXR
336 if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64)
337 return llvm::None; // MPXC
338 if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64)
339 return DBRegSet; // DBR
340 break;
341 default:
342 llvm_unreachable("Unhandled target architecture.");
343 }
344
345 llvm_unreachable("Register does not belong to any register set");
346 }
347
ReadRegisterSet(RegSetKind set)348 Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(RegSetKind set) {
349 switch (set) {
350 case GPRegSet:
351 return DoRegisterSet(PT_GETREGS, m_gpr.data());
352 case DBRegSet:
353 return DoRegisterSet(PT_GETDBREGS, m_dbr.data());
354 case FPRegSet:
355 case YMMRegSet:
356 case MPXRegSet: {
357 struct iovec iov = {m_xstate.data(), m_xstate.size()};
358 Status ret = DoRegisterSet(PT_GETXSTATE, &iov);
359 assert(reinterpret_cast<xstate *>(m_xstate.data())->xs_rfbm & XCR0_X87);
360 return ret;
361 }
362 }
363 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
364 }
365
WriteRegisterSet(RegSetKind set)366 Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(RegSetKind set) {
367 switch (set) {
368 case GPRegSet:
369 return DoRegisterSet(PT_SETREGS, m_gpr.data());
370 case DBRegSet:
371 return DoRegisterSet(PT_SETDBREGS, m_dbr.data());
372 case FPRegSet:
373 case YMMRegSet:
374 case MPXRegSet: {
375 struct iovec iov = {&m_xstate, sizeof(m_xstate)};
376 return DoRegisterSet(PT_SETXSTATE, &iov);
377 }
378 }
379 llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
380 }
381
382 Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)383 NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info,
384 RegisterValue ®_value) {
385 Status error;
386
387 if (!reg_info) {
388 error.SetErrorString("reg_info NULL");
389 return error;
390 }
391
392 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
393 if (reg == LLDB_INVALID_REGNUM) {
394 // This is likely an internal register for lldb use only and should not be
395 // directly queried.
396 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
397 "register, cannot read directly",
398 reg_info->name);
399 return error;
400 }
401
402 llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
403 if (!opt_set) {
404 // This is likely an internal register for lldb use only and should not be
405 // directly queried.
406 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
407 reg_info->name);
408 return error;
409 }
410
411 RegSetKind set = opt_set.getValue();
412 error = ReadRegisterSet(set);
413 if (error.Fail())
414 return error;
415
416 switch (set) {
417 case GPRegSet:
418 case FPRegSet:
419 case DBRegSet: {
420 void *data = GetOffsetRegSetData(set, reg_info->byte_offset);
421 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() +
422 offsetof(xstate, xs_fxsave));
423 if (data == &fpr->ftag) // ftag
424 reg_value.SetUInt16(
425 AbridgedToFullTagWord(fpr->ftag, fpr->fstat, fpr->stmm));
426 else
427 reg_value.SetBytes(data, reg_info->byte_size, endian::InlHostByteOrder());
428 break;
429 }
430 case YMMRegSet: {
431 llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg);
432 if (!ymm_reg) {
433 error.SetErrorStringWithFormat(
434 "register \"%s\" not supported by CPU/kernel", reg_info->name);
435 } else {
436 YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi);
437 reg_value.SetBytes(ymm.bytes, reg_info->byte_size,
438 endian::InlHostByteOrder());
439 }
440 break;
441 }
442 case MPXRegSet:
443 llvm_unreachable("MPX regset should have returned error");
444 }
445
446 return error;
447 }
448
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)449 Status NativeRegisterContextNetBSD_x86_64::WriteRegister(
450 const RegisterInfo *reg_info, const RegisterValue ®_value) {
451
452 Status error;
453
454 if (!reg_info) {
455 error.SetErrorString("reg_info NULL");
456 return error;
457 }
458
459 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
460 if (reg == LLDB_INVALID_REGNUM) {
461 // This is likely an internal register for lldb use only and should not be
462 // directly queried.
463 error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
464 "register, cannot read directly",
465 reg_info->name);
466 return error;
467 }
468
469 llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
470 if (!opt_set) {
471 // This is likely an internal register for lldb use only and should not be
472 // directly queried.
473 error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
474 reg_info->name);
475 return error;
476 }
477
478 RegSetKind set = opt_set.getValue();
479 uint64_t new_xstate_bv = 0;
480
481 error = ReadRegisterSet(set);
482 if (error.Fail())
483 return error;
484
485 switch (set) {
486 case GPRegSet:
487 case DBRegSet:
488 ::memcpy(GetOffsetRegSetData(set, reg_info->byte_offset),
489 reg_value.GetBytes(), reg_value.GetByteSize());
490 break;
491 case FPRegSet: {
492 void *data = GetOffsetRegSetData(set, reg_info->byte_offset);
493 FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() +
494 offsetof(xstate, xs_fxsave));
495 if (data == &fpr->ftag) // ftag
496 fpr->ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16());
497 else
498 ::memcpy(data, reg_value.GetBytes(), reg_value.GetByteSize());
499 if (data >= &fpr->xmm)
500 new_xstate_bv |= XCR0_SSE;
501 else if (data >= &fpr->mxcsr && data < &fpr->stmm)
502 new_xstate_bv |= XCR0_SSE;
503 else
504 new_xstate_bv |= XCR0_X87;
505 break;
506 }
507 case YMMRegSet: {
508 llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg);
509 if (!ymm_reg) {
510 error.SetErrorStringWithFormat(
511 "register \"%s\" not supported by CPU/kernel", reg_info->name);
512 } else {
513 YMMReg ymm;
514 ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize());
515 YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi);
516 new_xstate_bv |= XCR0_SSE | XCR0_YMM_Hi128;
517 }
518 break;
519 }
520 case MPXRegSet:
521 llvm_unreachable("MPX regset should have returned error");
522 }
523
524 if (new_xstate_bv != 0)
525 reinterpret_cast<xstate *>(m_xstate.data())->xs_xstate_bv |= new_xstate_bv;
526 return WriteRegisterSet(set);
527 }
528
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)529 Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
530 lldb::WritableDataBufferSP &data_sp) {
531 Status error;
532
533 data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
534 error = ReadRegisterSet(GPRegSet);
535 if (error.Fail())
536 return error;
537
538 uint8_t *dst = data_sp->GetBytes();
539 ::memcpy(dst, m_gpr.data(), GetRegisterInfoInterface().GetGPRSize());
540 dst += GetRegisterInfoInterface().GetGPRSize();
541
542 return error;
543 }
544
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)545 Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
546 const lldb::DataBufferSP &data_sp) {
547 Status error;
548
549 if (!data_sp) {
550 error.SetErrorStringWithFormat(
551 "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided",
552 __FUNCTION__);
553 return error;
554 }
555
556 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
557 error.SetErrorStringWithFormat(
558 "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched "
559 "data size, expected %zu, actual %" PRIu64,
560 __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
561 return error;
562 }
563
564 const uint8_t *src = data_sp->GetBytes();
565 if (src == nullptr) {
566 error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s "
567 "DataBuffer::GetBytes() returned a null "
568 "pointer",
569 __FUNCTION__);
570 return error;
571 }
572 ::memcpy(m_gpr.data(), src, GetRegisterInfoInterface().GetGPRSize());
573
574 error = WriteRegisterSet(GPRegSet);
575 if (error.Fail())
576 return error;
577 src += GetRegisterInfoInterface().GetGPRSize();
578
579 return error;
580 }
581
CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD & source)582 llvm::Error NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
583 NativeRegisterContextNetBSD &source) {
584 auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64 &>(source);
585 // NB: This implicitly reads the whole dbreg set.
586 RegisterValue dr7;
587 Status res = r_source.ReadRegister(GetDR(7), dr7);
588 if (!res.Fail()) {
589 // copy dbregs only if any watchpoints were set
590 if ((dr7.GetAsUInt64() & 0xFF) == 0)
591 return llvm::Error::success();
592
593 m_dbr = r_source.m_dbr;
594 res = WriteRegisterSet(DBRegSet);
595 }
596 return res.ToError();
597 }
598
599 uint8_t *
GetOffsetRegSetData(RegSetKind set,size_t reg_offset)600 NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set,
601 size_t reg_offset) {
602 uint8_t *base;
603 switch (set) {
604 case GPRegSet:
605 base = m_gpr.data();
606 break;
607 case FPRegSet:
608 base = m_xstate.data() + offsetof(xstate, xs_fxsave);
609 break;
610 case DBRegSet:
611 base = m_dbr.data();
612 break;
613 case YMMRegSet:
614 llvm_unreachable("GetRegSetData() is unsuitable for this regset.");
615 case MPXRegSet:
616 llvm_unreachable("MPX regset should have returned error");
617 }
618 assert(reg_offset >= m_regset_offsets[set]);
619 return base + (reg_offset - m_regset_offsets[set]);
620 }
621
622 llvm::Optional<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr>
GetYMMSplitReg(uint32_t reg)623 NativeRegisterContextNetBSD_x86_64::GetYMMSplitReg(uint32_t reg) {
624 auto xst = reinterpret_cast<xstate *>(m_xstate.data());
625 if (!(xst->xs_rfbm & XCR0_SSE) || !(xst->xs_rfbm & XCR0_YMM_Hi128))
626 return llvm::None;
627
628 uint32_t reg_index;
629 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
630 case llvm::Triple::x86:
631 reg_index = reg - lldb_ymm0_i386;
632 break;
633 case llvm::Triple::x86_64:
634 reg_index = reg - lldb_ymm0_x86_64;
635 break;
636 default:
637 llvm_unreachable("Unhandled target architecture.");
638 }
639
640 return YMMSplitPtr{&xst->xs_fxsave.fx_xmm[reg_index],
641 &xst->xs_ymm_hi128.xs_ymm[reg_index]};
642 }
643
644 #endif // defined(__x86_64__)
645