1//===-- NativeRegisterContextLinux_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 "NativeRegisterContextLinux_x86_64.h"
12#include "Plugins/Process/Linux/NativeThreadLinux.h"
13#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
14#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
15#include "lldb/Host/HostInfo.h"
16#include "lldb/Utility/DataBufferHeap.h"
17#include "lldb/Utility/Log.h"
18#include "lldb/Utility/RegisterValue.h"
19#include "lldb/Utility/Status.h"
20#include <cpuid.h>
21#include <linux/elf.h>
22#include <optional>
23
24// Newer toolchains define __get_cpuid_count in cpuid.h, but some
25// older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we
26// define it locally here, following the definition in clang/lib/Headers.
27static inline int get_cpuid_count(unsigned int __leaf,
28 unsigned int __subleaf,
29 unsigned int *__eax, unsigned int *__ebx,
30 unsigned int *__ecx, unsigned int *__edx)
31{
32 unsigned int __max_leaf = __get_cpuid_max(leaf: __leaf & 0x80000000, sig: nullptr);
33
34 if (__max_leaf == 0 || __max_leaf < __leaf)
35 return 0;
36
37 __cpuid_count(__leaf, __subleaf, *__eax, *__ebx, *__ecx, *__edx);
38 return 1;
39}
40
41using namespace lldb_private;
42using namespace lldb_private::process_linux;
43
44// x86 32-bit general purpose registers.
45static const uint32_t g_gpr_regnums_i386[] = {
46 lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386, lldb_edx_i386,
47 lldb_edi_i386, lldb_esi_i386, lldb_ebp_i386, lldb_esp_i386,
48 lldb_eip_i386, lldb_eflags_i386, lldb_cs_i386, lldb_fs_i386,
49 lldb_gs_i386, lldb_ss_i386, lldb_ds_i386, lldb_es_i386,
50 lldb_ax_i386, lldb_bx_i386, lldb_cx_i386, lldb_dx_i386,
51 lldb_di_i386, lldb_si_i386, lldb_bp_i386, lldb_sp_i386,
52 lldb_ah_i386, lldb_bh_i386, lldb_ch_i386, lldb_dh_i386,
53 lldb_al_i386, lldb_bl_i386, lldb_cl_i386, lldb_dl_i386,
54 LLDB_INVALID_REGNUM // register sets need to end with this flag
55};
56static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
57 1 ==
58 k_num_gpr_registers_i386,
59 "g_gpr_regnums_i386 has wrong number of register infos");
60
61// x86 32-bit floating point registers.
62static const uint32_t g_fpu_regnums_i386[] = {
63 lldb_fctrl_i386, lldb_fstat_i386, lldb_ftag_i386, lldb_fop_i386,
64 lldb_fiseg_i386, lldb_fioff_i386, lldb_foseg_i386, lldb_fooff_i386,
65 lldb_mxcsr_i386, lldb_mxcsrmask_i386, lldb_st0_i386, lldb_st1_i386,
66 lldb_st2_i386, lldb_st3_i386, lldb_st4_i386, lldb_st5_i386,
67 lldb_st6_i386, lldb_st7_i386, lldb_mm0_i386, lldb_mm1_i386,
68 lldb_mm2_i386, lldb_mm3_i386, lldb_mm4_i386, lldb_mm5_i386,
69 lldb_mm6_i386, lldb_mm7_i386, lldb_xmm0_i386, lldb_xmm1_i386,
70 lldb_xmm2_i386, lldb_xmm3_i386, lldb_xmm4_i386, lldb_xmm5_i386,
71 lldb_xmm6_i386, lldb_xmm7_i386,
72 LLDB_INVALID_REGNUM // register sets need to end with this flag
73};
74static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
75 1 ==
76 k_num_fpr_registers_i386,
77 "g_fpu_regnums_i386 has wrong number of register infos");
78
79// x86 32-bit AVX registers.
80static const uint32_t g_avx_regnums_i386[] = {
81 lldb_ymm0_i386, lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
82 lldb_ymm4_i386, lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
83 LLDB_INVALID_REGNUM // register sets need to end with this flag
84};
85static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
86 1 ==
87 k_num_avx_registers_i386,
88 " g_avx_regnums_i386 has wrong number of register infos");
89
90// x64 32-bit MPX registers.
91static const uint32_t g_mpx_regnums_i386[] = {
92 lldb_bnd0_i386, lldb_bnd1_i386, lldb_bnd2_i386, lldb_bnd3_i386,
93 lldb_bndcfgu_i386, lldb_bndstatus_i386,
94 LLDB_INVALID_REGNUM // register sets need to end with this flag
95};
96static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
97 1 ==
98 k_num_mpx_registers_i386,
99 "g_mpx_regnums_x86_64 has wrong number of register infos");
100
101// x86 64-bit general purpose registers.
102static const uint32_t g_gpr_regnums_x86_64[] = {
103 x86_64_with_base::lldb_rax, x86_64_with_base::lldb_rbx, x86_64_with_base::lldb_rcx, x86_64_with_base::lldb_rdx,
104 x86_64_with_base::lldb_rdi, x86_64_with_base::lldb_rsi, x86_64_with_base::lldb_rbp, x86_64_with_base::lldb_rsp,
105 x86_64_with_base::lldb_r8, x86_64_with_base::lldb_r9, x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r11,
106 x86_64_with_base::lldb_r12, x86_64_with_base::lldb_r13, x86_64_with_base::lldb_r14, x86_64_with_base::lldb_r15,
107 x86_64_with_base::lldb_rip, x86_64_with_base::lldb_rflags, x86_64_with_base::lldb_cs, x86_64_with_base::lldb_fs,
108 x86_64_with_base::lldb_gs, x86_64_with_base::lldb_ss, x86_64_with_base::lldb_fs_base, x86_64_with_base::lldb_gs_base,
109 x86_64_with_base::lldb_ds, x86_64_with_base::lldb_es,
110 x86_64_with_base::lldb_eax, x86_64_with_base::lldb_ebx, x86_64_with_base::lldb_ecx, x86_64_with_base::lldb_edx,
111 x86_64_with_base::lldb_edi, x86_64_with_base::lldb_esi, x86_64_with_base::lldb_ebp, x86_64_with_base::lldb_esp,
112 x86_64_with_base::lldb_r8d, // Low 32 bits or r8
113 x86_64_with_base::lldb_r9d, // Low 32 bits or r9
114 x86_64_with_base::lldb_r10d, // Low 32 bits or r10
115 x86_64_with_base::lldb_r11d, // Low 32 bits or r11
116 x86_64_with_base::lldb_r12d, // Low 32 bits or r12
117 x86_64_with_base::lldb_r13d, // Low 32 bits or r13
118 x86_64_with_base::lldb_r14d, // Low 32 bits or r14
119 x86_64_with_base::lldb_r15d, // Low 32 bits or r15
120 x86_64_with_base::lldb_ax, x86_64_with_base::lldb_bx, x86_64_with_base::lldb_cx, x86_64_with_base::lldb_dx,
121 x86_64_with_base::lldb_di, x86_64_with_base::lldb_si, x86_64_with_base::lldb_bp, x86_64_with_base::lldb_sp,
122 x86_64_with_base::lldb_r8w, // Low 16 bits or r8
123 x86_64_with_base::lldb_r9w, // Low 16 bits or r9
124 x86_64_with_base::lldb_r10w, // Low 16 bits or r10
125 x86_64_with_base::lldb_r11w, // Low 16 bits or r11
126 x86_64_with_base::lldb_r12w, // Low 16 bits or r12
127 x86_64_with_base::lldb_r13w, // Low 16 bits or r13
128 x86_64_with_base::lldb_r14w, // Low 16 bits or r14
129 x86_64_with_base::lldb_r15w, // Low 16 bits or r15
130 x86_64_with_base::lldb_ah, x86_64_with_base::lldb_bh, x86_64_with_base::lldb_ch, x86_64_with_base::lldb_dh,
131 x86_64_with_base::lldb_al, x86_64_with_base::lldb_bl, x86_64_with_base::lldb_cl, x86_64_with_base::lldb_dl,
132 x86_64_with_base::lldb_dil, x86_64_with_base::lldb_sil, x86_64_with_base::lldb_bpl, x86_64_with_base::lldb_spl,
133 x86_64_with_base::lldb_r8l, // Low 8 bits or r8
134 x86_64_with_base::lldb_r9l, // Low 8 bits or r9
135 x86_64_with_base::lldb_r10l, // Low 8 bits or r10
136 x86_64_with_base::lldb_r11l, // Low 8 bits or r11
137 x86_64_with_base::lldb_r12l, // Low 8 bits or r12
138 x86_64_with_base::lldb_r13l, // Low 8 bits or r13
139 x86_64_with_base::lldb_r14l, // Low 8 bits or r14
140 x86_64_with_base::lldb_r15l, // Low 8 bits or r15
141 LLDB_INVALID_REGNUM // register sets need to end with this flag
142};
143static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
144 1 ==
145 x86_64_with_base::k_num_gpr_registers,
146 "g_gpr_regnums_x86_64 has wrong number of register infos");
147
148// x86 64-bit floating point registers.
149static const uint32_t g_fpu_regnums_x86_64[] = {
150 x86_64_with_base::lldb_fctrl, x86_64_with_base::lldb_fstat, x86_64_with_base::lldb_ftag,
151 x86_64_with_base::lldb_fop, x86_64_with_base::lldb_fiseg, x86_64_with_base::lldb_fioff,
152 x86_64_with_base::lldb_fip, x86_64_with_base::lldb_foseg, x86_64_with_base::lldb_fooff,
153 x86_64_with_base::lldb_fdp, x86_64_with_base::lldb_mxcsr, x86_64_with_base::lldb_mxcsrmask,
154 x86_64_with_base::lldb_st0, x86_64_with_base::lldb_st1, x86_64_with_base::lldb_st2,
155 x86_64_with_base::lldb_st3, x86_64_with_base::lldb_st4, x86_64_with_base::lldb_st5,
156 x86_64_with_base::lldb_st6, x86_64_with_base::lldb_st7, x86_64_with_base::lldb_mm0,
157 x86_64_with_base::lldb_mm1, x86_64_with_base::lldb_mm2, x86_64_with_base::lldb_mm3,
158 x86_64_with_base::lldb_mm4, x86_64_with_base::lldb_mm5, x86_64_with_base::lldb_mm6,
159 x86_64_with_base::lldb_mm7, x86_64_with_base::lldb_xmm0, x86_64_with_base::lldb_xmm1,
160 x86_64_with_base::lldb_xmm2, x86_64_with_base::lldb_xmm3, x86_64_with_base::lldb_xmm4,
161 x86_64_with_base::lldb_xmm5, x86_64_with_base::lldb_xmm6, x86_64_with_base::lldb_xmm7,
162 x86_64_with_base::lldb_xmm8, x86_64_with_base::lldb_xmm9, x86_64_with_base::lldb_xmm10,
163 x86_64_with_base::lldb_xmm11, x86_64_with_base::lldb_xmm12, x86_64_with_base::lldb_xmm13,
164 x86_64_with_base::lldb_xmm14, x86_64_with_base::lldb_xmm15,
165 LLDB_INVALID_REGNUM // register sets need to end with this flag
166};
167static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
168 1 ==
169 x86_64_with_base::k_num_fpr_registers,
170 "g_fpu_regnums_x86_64 has wrong number of register infos");
171
172// x86 64-bit AVX registers.
173static const uint32_t g_avx_regnums_x86_64[] = {
174 x86_64_with_base::lldb_ymm0, x86_64_with_base::lldb_ymm1, x86_64_with_base::lldb_ymm2, x86_64_with_base::lldb_ymm3,
175 x86_64_with_base::lldb_ymm4, x86_64_with_base::lldb_ymm5, x86_64_with_base::lldb_ymm6, x86_64_with_base::lldb_ymm7,
176 x86_64_with_base::lldb_ymm8, x86_64_with_base::lldb_ymm9, x86_64_with_base::lldb_ymm10, x86_64_with_base::lldb_ymm11,
177 x86_64_with_base::lldb_ymm12, x86_64_with_base::lldb_ymm13, x86_64_with_base::lldb_ymm14, x86_64_with_base::lldb_ymm15,
178 LLDB_INVALID_REGNUM // register sets need to end with this flag
179};
180static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
181 1 ==
182 x86_64_with_base::k_num_avx_registers,
183 "g_avx_regnums_x86_64 has wrong number of register infos");
184
185// x86 64-bit MPX registers.
186static const uint32_t g_mpx_regnums_x86_64[] = {
187 x86_64_with_base::lldb_bnd0, x86_64_with_base::lldb_bnd1, x86_64_with_base::lldb_bnd2,
188 x86_64_with_base::lldb_bnd3, x86_64_with_base::lldb_bndcfgu, x86_64_with_base::lldb_bndstatus,
189 LLDB_INVALID_REGNUM // register sets need to end with this flag
190};
191static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
192 1 ==
193 x86_64_with_base::k_num_mpx_registers,
194 "g_mpx_regnums_x86_64 has wrong number of register infos");
195
196// Number of register sets provided by this context.
197constexpr unsigned k_num_extended_register_sets = 2, k_num_register_sets = 4;
198
199// Register sets for x86 32-bit.
200static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
201 {.name: "General Purpose Registers", .short_name: "gpr", .num_registers: k_num_gpr_registers_i386,
202 .registers: g_gpr_regnums_i386},
203 {.name: "Floating Point Registers", .short_name: "fpu", .num_registers: k_num_fpr_registers_i386,
204 .registers: g_fpu_regnums_i386},
205 {.name: "Advanced Vector Extensions", .short_name: "avx", .num_registers: k_num_avx_registers_i386,
206 .registers: g_avx_regnums_i386},
207 { .name: "Memory Protection Extensions", .short_name: "mpx", .num_registers: k_num_mpx_registers_i386,
208 .registers: g_mpx_regnums_i386}};
209
210// Register sets for x86 64-bit.
211static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
212 {.name: "General Purpose Registers", .short_name: "gpr", .num_registers: x86_64_with_base::k_num_gpr_registers,
213 .registers: g_gpr_regnums_x86_64},
214 {.name: "Floating Point Registers", .short_name: "fpu", .num_registers: x86_64_with_base::k_num_fpr_registers,
215 .registers: g_fpu_regnums_x86_64},
216 {.name: "Advanced Vector Extensions", .short_name: "avx", .num_registers: x86_64_with_base::k_num_avx_registers,
217 .registers: g_avx_regnums_x86_64},
218 { .name: "Memory Protection Extensions", .short_name: "mpx", .num_registers: x86_64_with_base::k_num_mpx_registers,
219 .registers: g_mpx_regnums_x86_64}};
220
221#define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize() + sizeof(FPR))
222
223// Required ptrace defines.
224
225// Support ptrace extensions even when compiled without required kernel support
226#ifndef NT_X86_XSTATE
227#define NT_X86_XSTATE 0x202
228#endif
229#ifndef NT_PRXFPREG
230#define NT_PRXFPREG 0x46e62b7f
231#endif
232
233// On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to
234// use NT_PRXFPREG.
235static inline unsigned int fxsr_regset(const ArchSpec &arch) {
236 return arch.GetAddressByteSize() == 8 ? NT_PRFPREG : NT_PRXFPREG;
237}
238
239// Required MPX define.
240
241// Support MPX extensions also if compiled with compiler without MPX support.
242#ifndef bit_MPX
243#define bit_MPX 0x4000
244#endif
245
246// XCR0 extended register sets masks.
247#define mask_XSTATE_AVX (1ULL << 2)
248#define mask_XSTATE_BNDREGS (1ULL << 3)
249#define mask_XSTATE_BNDCFG (1ULL << 4)
250#define mask_XSTATE_MPX (mask_XSTATE_BNDREGS | mask_XSTATE_BNDCFG)
251
252std::unique_ptr<NativeRegisterContextLinux>
253NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
254 const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
255 return std::unique_ptr<NativeRegisterContextLinux>(
256 new NativeRegisterContextLinux_x86_64(target_arch, native_thread));
257}
258
259llvm::Expected<ArchSpec>
260NativeRegisterContextLinux::DetermineArchitecture(lldb::tid_t tid) {
261 return DetermineArchitectureViaGPR(
262 tid, gpr64_size: RegisterContextLinux_x86_64::GetGPRSizeStatic());
263}
264
265// NativeRegisterContextLinux_x86_64 members.
266
267static std::unique_ptr<RegisterContextLinux_x86>
268CreateRegisterInfoInterface(const ArchSpec &target_arch) {
269 if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
270 // 32-bit hosts run with a RegisterContextLinux_i386 context.
271 return std::make_unique<RegisterContextLinux_i386>(args: target_arch);
272 } else {
273 assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
274 "Register setting path assumes this is a 64-bit host");
275 // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
276 // x86_64 register context.
277 return std::make_unique<RegisterContextLinux_x86_64>(args: target_arch);
278 }
279}
280
281// Return the size of the XSTATE area supported on this cpu. It is necessary to
282// allocate the full size of the area even if we do not use/recognise all of it
283// because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if
284// we do not pass it a buffer of sufficient size. The size is always at least
285// sizeof(FPR) so that the allocated buffer can be safely cast to FPR*.
286static std::size_t GetXSTATESize() {
287 unsigned int eax, ebx, ecx, edx;
288 // First check whether the XSTATE are is supported at all.
289 if (!__get_cpuid(leaf: 1, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx) || !(ecx & bit_XSAVE))
290 return sizeof(FPR);
291
292 // Then fetch the maximum size of the area.
293 if (!get_cpuid_count(leaf: 0x0d, subleaf: 0, eax: &eax, ebx: &ebx, ecx: &ecx, edx: &edx))
294 return sizeof(FPR);
295 return std::max<std::size_t>(a: ecx, b: sizeof(FPR));
296}
297
298NativeRegisterContextLinux_x86_64::NativeRegisterContextLinux_x86_64(
299 const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
300 : NativeRegisterContextRegisterInfo(
301 native_thread, CreateRegisterInfoInterface(target_arch).release()),
302 NativeRegisterContextLinux(native_thread),
303 NativeRegisterContextDBReg_x86(native_thread),
304 m_xstate_type(XStateType::Invalid), m_ymm_set(), m_mpx_set(),
305 m_reg_info(), m_gpr_x86_64() {
306 // Set up data about ranges of valid registers.
307 switch (target_arch.GetMachine()) {
308 case llvm::Triple::x86:
309 m_reg_info.num_registers = k_num_registers_i386;
310 m_reg_info.num_gpr_registers = k_num_gpr_registers_i386;
311 m_reg_info.num_fpr_registers = k_num_fpr_registers_i386;
312 m_reg_info.num_avx_registers = k_num_avx_registers_i386;
313 m_reg_info.num_mpx_registers = k_num_mpx_registers_i386;
314 m_reg_info.last_gpr = k_last_gpr_i386;
315 m_reg_info.first_fpr = k_first_fpr_i386;
316 m_reg_info.last_fpr = k_last_fpr_i386;
317 m_reg_info.first_st = lldb_st0_i386;
318 m_reg_info.last_st = lldb_st7_i386;
319 m_reg_info.first_mm = lldb_mm0_i386;
320 m_reg_info.last_mm = lldb_mm7_i386;
321 m_reg_info.first_xmm = lldb_xmm0_i386;
322 m_reg_info.last_xmm = lldb_xmm7_i386;
323 m_reg_info.first_ymm = lldb_ymm0_i386;
324 m_reg_info.last_ymm = lldb_ymm7_i386;
325 m_reg_info.first_mpxr = lldb_bnd0_i386;
326 m_reg_info.last_mpxr = lldb_bnd3_i386;
327 m_reg_info.first_mpxc = lldb_bndcfgu_i386;
328 m_reg_info.last_mpxc = lldb_bndstatus_i386;
329 m_reg_info.first_dr = lldb_dr0_i386;
330 m_reg_info.last_dr = lldb_dr7_i386;
331 m_reg_info.gpr_flags = lldb_eflags_i386;
332 break;
333 case llvm::Triple::x86_64:
334 m_reg_info.num_registers = x86_64_with_base::k_num_registers;
335 m_reg_info.num_gpr_registers = x86_64_with_base::k_num_gpr_registers;
336 m_reg_info.num_fpr_registers = x86_64_with_base::k_num_fpr_registers;
337 m_reg_info.num_avx_registers = x86_64_with_base::k_num_avx_registers;
338 m_reg_info.num_mpx_registers = x86_64_with_base::k_num_mpx_registers;
339 m_reg_info.last_gpr = x86_64_with_base::k_last_gpr;
340 m_reg_info.first_fpr = x86_64_with_base::k_first_fpr;
341 m_reg_info.last_fpr = x86_64_with_base::k_last_fpr;
342 m_reg_info.first_st = x86_64_with_base::lldb_st0;
343 m_reg_info.last_st = x86_64_with_base::lldb_st7;
344 m_reg_info.first_mm = x86_64_with_base::lldb_mm0;
345 m_reg_info.last_mm = x86_64_with_base::lldb_mm7;
346 m_reg_info.first_xmm = x86_64_with_base::lldb_xmm0;
347 m_reg_info.last_xmm = x86_64_with_base::lldb_xmm15;
348 m_reg_info.first_ymm = x86_64_with_base::lldb_ymm0;
349 m_reg_info.last_ymm = x86_64_with_base::lldb_ymm15;
350 m_reg_info.first_mpxr = x86_64_with_base::lldb_bnd0;
351 m_reg_info.last_mpxr = x86_64_with_base::lldb_bnd3;
352 m_reg_info.first_mpxc = x86_64_with_base::lldb_bndcfgu;
353 m_reg_info.last_mpxc = x86_64_with_base::lldb_bndstatus;
354 m_reg_info.first_dr = x86_64_with_base::lldb_dr0;
355 m_reg_info.last_dr = x86_64_with_base::lldb_dr7;
356 m_reg_info.gpr_flags = x86_64_with_base::lldb_rflags;
357 break;
358 default:
359 assert(false && "Unhandled target architecture.");
360 break;
361 }
362
363 std::size_t xstate_size = GetXSTATESize();
364 m_xstate.reset(p: static_cast<FPR *>(std::malloc(size: xstate_size)));
365 m_iovec.iov_base = m_xstate.get();
366 m_iovec.iov_len = xstate_size;
367
368 // Clear out the FPR state.
369 ::memset(s: m_xstate.get(), c: 0, n: xstate_size);
370
371 // Store byte offset of fctrl (i.e. first register of FPR)
372 const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName(reg_name: "fctrl");
373 m_fctrl_offset_in_userarea = reg_info_fctrl->byte_offset;
374}
375
376// CONSIDER after local and llgs debugging are merged, register set support can
377// be moved into a base x86-64 class with IsRegisterSetAvailable made virtual.
378uint32_t NativeRegisterContextLinux_x86_64::GetRegisterSetCount() const {
379 uint32_t sets = 0;
380 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
381 if (IsRegisterSetAvailable(set_index))
382 ++sets;
383 }
384
385 return sets;
386}
387
388uint32_t NativeRegisterContextLinux_x86_64::GetUserRegisterCount() const {
389 uint32_t count = 0;
390 for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index) {
391 const RegisterSet *set = GetRegisterSet(set_index);
392 if (set)
393 count += set->num_registers;
394 }
395 return count;
396}
397
398const RegisterSet *
399NativeRegisterContextLinux_x86_64::GetRegisterSet(uint32_t set_index) const {
400 if (!IsRegisterSetAvailable(set_index))
401 return nullptr;
402
403 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
404 case llvm::Triple::x86:
405 return &g_reg_sets_i386[set_index];
406 case llvm::Triple::x86_64:
407 return &g_reg_sets_x86_64[set_index];
408 default:
409 assert(false && "Unhandled target architecture.");
410 return nullptr;
411 }
412
413 return nullptr;
414}
415
416Status
417NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,
418 RegisterValue &reg_value) {
419 Status error;
420
421 if (!reg_info) {
422 error = Status::FromErrorString(str: "reg_info NULL");
423 return error;
424 }
425
426 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
427 if (reg == LLDB_INVALID_REGNUM) {
428 // This is likely an internal register for lldb use only and should not be
429 // directly queried.
430 error = Status::FromErrorStringWithFormat(
431 format: "register \"%s\" is an internal-only lldb "
432 "register, cannot read directly",
433 reg_info->name);
434 return error;
435 }
436
437 if (IsFPR(reg_index: reg) || IsAVX(reg_index: reg) || IsMPX(reg_index: reg)) {
438 error = ReadFPR();
439 if (error.Fail())
440 return error;
441 } else {
442 uint32_t full_reg = reg;
443 bool is_subreg = reg_info->invalidate_regs &&
444 (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
445
446 if (is_subreg) {
447 // Read the full aligned 64-bit register.
448 full_reg = reg_info->invalidate_regs[0];
449 }
450
451 error = ReadRegisterRaw(reg_index: full_reg, reg_value);
452
453 if (error.Success()) {
454 // If our read was not aligned (for ah,bh,ch,dh), shift our returned
455 // value one byte to the right.
456 if (is_subreg && (reg_info->byte_offset & 0x1))
457 reg_value.SetUInt64(uint: reg_value.GetAsUInt64() >> 8);
458
459 // If our return byte size was greater than the return value reg size,
460 // then use the type specified by reg_info rather than the uint64_t
461 // default
462 if (reg_value.GetByteSize() > reg_info->byte_size)
463 reg_value.SetType(*reg_info);
464 }
465 return error;
466 }
467
468 if (reg_info->encoding == lldb::eEncodingVector) {
469 lldb::ByteOrder byte_order = GetByteOrder();
470
471 if (byte_order != lldb::eByteOrderInvalid) {
472 if (reg >= m_reg_info.first_st && reg <= m_reg_info.last_st)
473 reg_value.SetBytes(
474 bytes: m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes,
475 length: reg_info->byte_size, byte_order);
476 if (reg >= m_reg_info.first_mm && reg <= m_reg_info.last_mm)
477 reg_value.SetBytes(
478 bytes: m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes,
479 length: reg_info->byte_size, byte_order);
480 if (reg >= m_reg_info.first_xmm && reg <= m_reg_info.last_xmm)
481 reg_value.SetBytes(
482 bytes: m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes,
483 length: reg_info->byte_size, byte_order);
484 if (reg >= m_reg_info.first_ymm && reg <= m_reg_info.last_ymm) {
485 // Concatenate ymm using the register halves in xmm.bytes and
486 // ymmh.bytes
487 if (CopyXSTATEtoYMM(reg_index: reg, byte_order))
488 reg_value.SetBytes(bytes: m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,
489 length: reg_info->byte_size, byte_order);
490 else {
491 error = Status::FromErrorString(str: "failed to copy ymm register value");
492 return error;
493 }
494 }
495 if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
496 if (CopyXSTATEtoMPX(reg))
497 reg_value.SetBytes(bytes: m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
498 length: reg_info->byte_size, byte_order);
499 else {
500 error = Status::FromErrorString(str: "failed to copy mpx register value");
501 return error;
502 }
503 }
504 if (reg >= m_reg_info.first_mpxc && reg <= m_reg_info.last_mpxc) {
505 if (CopyXSTATEtoMPX(reg))
506 reg_value.SetBytes(bytes: m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
507 length: reg_info->byte_size, byte_order);
508 else {
509 error = Status::FromErrorString(str: "failed to copy mpx register value");
510 return error;
511 }
512 }
513
514 if (reg_value.GetType() != RegisterValue::eTypeBytes)
515 error = Status::FromErrorString(
516 str: "write failed - type was expected to be RegisterValue::eTypeBytes");
517
518 return error;
519 }
520
521 error = Status::FromErrorString(str: "byte order is invalid");
522 return error;
523 }
524
525 // Get pointer to m_xstate->fxsave variable and set the data from it.
526
527 // Byte offsets of all registers are calculated wrt 'UserArea' structure.
528 // However, ReadFPR() reads fpu registers {using ptrace(PTRACE_GETFPREGS,..)}
529 // and stores them in 'm_fpr' (of type FPR structure). To extract values of
530 // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR
531 // structure.
532
533 // Since, FPR structure is also one of the member of UserArea structure.
534 // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
535 // byte_offset(fctrl wrt UserArea)
536 assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) < sizeof(FPR));
537 uint8_t *src = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
538 m_fctrl_offset_in_userarea;
539
540 if (src == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag)) {
541 reg_value.SetUInt16(AbridgedToFullTagWord(
542 abridged_tw: m_xstate->fxsave.ftag, sw: m_xstate->fxsave.fstat, st_regs: m_xstate->fxsave.stmm));
543 return error;
544 }
545
546 switch (reg_info->byte_size) {
547 case 1:
548 reg_value.SetUInt8(*(uint8_t *)src);
549 break;
550 case 2:
551 reg_value.SetUInt16(*(uint16_t *)src);
552 break;
553 case 4:
554 reg_value.SetUInt32(uint: *(uint32_t *)src);
555 break;
556 case 8:
557 reg_value.SetUInt64(uint: *(uint64_t *)src);
558 break;
559 default:
560 assert(false && "Unhandled data size.");
561 error = Status::FromErrorStringWithFormat(format: "unhandled byte size: %" PRIu32,
562 reg_info->byte_size);
563 break;
564 }
565
566 return error;
567}
568
569void NativeRegisterContextLinux_x86_64::UpdateXSTATEforWrite(
570 uint32_t reg_index) {
571 XSAVE_HDR::XFeature &xstate_bv = m_xstate->xsave.header.xstate_bv;
572 if (IsFPR(reg_index)) {
573 // IsFPR considers both %st and %xmm registers as floating point, but these
574 // map to two features. Set both flags, just in case.
575 xstate_bv |= XSAVE_HDR::XFeature::FP | XSAVE_HDR::XFeature::SSE;
576 } else if (IsAVX(reg_index)) {
577 // Lower bytes of some %ymm registers are shared with %xmm registers.
578 xstate_bv |= XSAVE_HDR::XFeature::YMM | XSAVE_HDR::XFeature::SSE;
579 } else if (IsMPX(reg_index)) {
580 // MPX registers map to two XSAVE features.
581 xstate_bv |= XSAVE_HDR::XFeature::BNDREGS | XSAVE_HDR::XFeature::BNDCSR;
582 }
583}
584
585Status NativeRegisterContextLinux_x86_64::WriteRegister(
586 const RegisterInfo *reg_info, const RegisterValue &reg_value) {
587 assert(reg_info && "reg_info is null");
588
589 const uint32_t reg_index = reg_info->kinds[lldb::eRegisterKindLLDB];
590 if (reg_index == LLDB_INVALID_REGNUM)
591 return Status::FromErrorStringWithFormat(
592 format: "no lldb regnum for %s",
593 reg_info && reg_info->name ? reg_info->name : "<unknown register>");
594
595 UpdateXSTATEforWrite(reg_index);
596
597 if (IsGPR(reg_index) || IsDR(reg_index))
598 return WriteRegisterRaw(reg_index, reg_value);
599
600 if (IsFPR(reg_index) || IsAVX(reg_index) || IsMPX(reg_index)) {
601 if (reg_info->encoding == lldb::eEncodingVector) {
602 if (reg_index >= m_reg_info.first_st && reg_index <= m_reg_info.last_st)
603 ::memcpy(dest: m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes,
604 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
605
606 if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)
607 ::memcpy(dest: m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,
608 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
609
610 if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)
611 ::memcpy(dest: m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,
612 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
613
614 if (reg_index >= m_reg_info.first_ymm &&
615 reg_index <= m_reg_info.last_ymm) {
616 // Store ymm register content, and split into the register halves in
617 // xmm.bytes and ymmh.bytes
618 ::memcpy(dest: m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,
619 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
620 if (!CopyYMMtoXSTATE(reg: reg_index, byte_order: GetByteOrder()))
621 return Status::FromErrorString(str: "CopyYMMtoXSTATE() failed");
622 }
623
624 if (reg_index >= m_reg_info.first_mpxr &&
625 reg_index <= m_reg_info.last_mpxr) {
626 ::memcpy(dest: m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,
627 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
628 if (!CopyMPXtoXSTATE(reg: reg_index))
629 return Status::FromErrorString(str: "CopyMPXtoXSTATE() failed");
630 }
631
632 if (reg_index >= m_reg_info.first_mpxc &&
633 reg_index <= m_reg_info.last_mpxc) {
634 ::memcpy(dest: m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,
635 src: reg_value.GetBytes(), n: reg_value.GetByteSize());
636 if (!CopyMPXtoXSTATE(reg: reg_index))
637 return Status::FromErrorString(str: "CopyMPXtoXSTATE() failed");
638 }
639 } else {
640 // Get pointer to m_xstate->fxsave variable and set the data to it.
641
642 // Byte offsets of all registers are calculated wrt 'UserArea' structure.
643 // However, WriteFPR() takes m_fpr (of type FPR structure) and writes
644 // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu
645 // registers should be written in m_fpr at byte offsets calculated wrt
646 // FPR structure.
647
648 // Since, FPR structure is also one of the member of UserArea structure.
649 // byte_offset(fpu wrt FPR) = byte_offset(fpu wrt UserArea) -
650 // byte_offset(fctrl wrt UserArea)
651 assert((reg_info->byte_offset - m_fctrl_offset_in_userarea) <
652 sizeof(FPR));
653 uint8_t *dst = (uint8_t *)m_xstate.get() + reg_info->byte_offset -
654 m_fctrl_offset_in_userarea;
655
656 if (dst == reinterpret_cast<uint8_t *>(&m_xstate->fxsave.ftag))
657 m_xstate->fxsave.ftag = FullToAbridgedTagWord(tw: reg_value.GetAsUInt16());
658 else {
659 switch (reg_info->byte_size) {
660 case 1:
661 *(uint8_t *)dst = reg_value.GetAsUInt8();
662 break;
663 case 2:
664 *(uint16_t *)dst = reg_value.GetAsUInt16();
665 break;
666 case 4:
667 *(uint32_t *)dst = reg_value.GetAsUInt32();
668 break;
669 case 8:
670 *(uint64_t *)dst = reg_value.GetAsUInt64();
671 break;
672 default:
673 assert(false && "Unhandled data size.");
674 return Status::FromErrorStringWithFormat(
675 format: "unhandled register data size %" PRIu32, reg_info->byte_size);
676 }
677 }
678 }
679
680 Status error = WriteFPR();
681 if (error.Fail())
682 return error;
683
684 if (IsAVX(reg_index)) {
685 if (!CopyYMMtoXSTATE(reg: reg_index, byte_order: GetByteOrder()))
686 return Status::FromErrorString(str: "CopyYMMtoXSTATE() failed");
687 }
688
689 if (IsMPX(reg_index)) {
690 if (!CopyMPXtoXSTATE(reg: reg_index))
691 return Status::FromErrorString(str: "CopyMPXtoXSTATE() failed");
692 }
693 return Status();
694 }
695 return Status::FromErrorString(
696 str: "failed - register wasn't recognized to be a GPR or an FPR, "
697 "write strategy unknown");
698}
699
700Status NativeRegisterContextLinux_x86_64::ReadAllRegisterValues(
701 lldb::WritableDataBufferSP &data_sp) {
702 Status error;
703
704 data_sp.reset(p: new DataBufferHeap(REG_CONTEXT_SIZE, 0));
705 error = ReadGPR();
706 if (error.Fail())
707 return error;
708
709 error = ReadFPR();
710 if (error.Fail())
711 return error;
712
713 uint8_t *dst = data_sp->GetBytes();
714 ::memcpy(dest: dst, src: &m_gpr_x86_64, n: GetRegisterInfoInterface().GetGPRSize());
715 dst += GetRegisterInfoInterface().GetGPRSize();
716 if (m_xstate_type == XStateType::FXSAVE)
717 ::memcpy(dest: dst, src: &m_xstate->fxsave, n: sizeof(m_xstate->fxsave));
718 else if (m_xstate_type == XStateType::XSAVE) {
719 lldb::ByteOrder byte_order = GetByteOrder();
720
721 if (IsCPUFeatureAvailable(feature_code: RegSet::avx)) {
722 // Assemble the YMM register content from the register halves.
723 for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
724 ++reg) {
725 if (!CopyXSTATEtoYMM(reg_index: reg, byte_order)) {
726 error = Status::FromErrorStringWithFormat(
727 format: "NativeRegisterContextLinux_x86_64::%s "
728 "CopyXSTATEtoYMM() failed for reg num "
729 "%" PRIu32,
730 __FUNCTION__, reg);
731 return error;
732 }
733 }
734 }
735
736 if (IsCPUFeatureAvailable(feature_code: RegSet::mpx)) {
737 for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
738 ++reg) {
739 if (!CopyXSTATEtoMPX(reg)) {
740 error = Status::FromErrorStringWithFormat(
741 format: "NativeRegisterContextLinux_x86_64::%s "
742 "CopyXSTATEtoMPX() failed for reg num "
743 "%" PRIu32,
744 __FUNCTION__, reg);
745 return error;
746 }
747 }
748 }
749 // Copy the extended register state including the assembled ymm registers.
750 ::memcpy(dest: dst, src: m_xstate.get(), n: sizeof(FPR));
751 } else {
752 assert(false && "how do we save the floating point registers?");
753 error = Status::FromErrorString(
754 str: "unsure how to save the floating point registers");
755 }
756 /** The following code is specific to Linux x86 based architectures,
757 * where the register orig_eax (32 bit)/orig_rax (64 bit) is set to
758 * -1 to solve the bug 23659, such a setting prevents the automatic
759 * decrement of the instruction pointer which was causing the SIGILL
760 * exception.
761 * **/
762
763 RegisterValue value((uint64_t)-1);
764 const RegisterInfo &info = GetRegisterInfo().GetOrigAxInfo();
765 return DoWriteRegisterValue(offset: info.byte_offset, reg_name: info.name, value);
766
767 return error;
768}
769
770Status NativeRegisterContextLinux_x86_64::WriteAllRegisterValues(
771 const lldb::DataBufferSP &data_sp) {
772 Status error;
773
774 if (!data_sp) {
775 error = Status::FromErrorStringWithFormat(
776 format: "NativeRegisterContextLinux_x86_64::%s invalid data_sp provided",
777 __FUNCTION__);
778 return error;
779 }
780
781 if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
782 error = Status::FromErrorStringWithFormatv(
783 format: "data_sp contained mismatched data size, expected {0}, actual {1}",
784 REG_CONTEXT_SIZE, args: data_sp->GetByteSize());
785 return error;
786 }
787
788 const uint8_t *src = data_sp->GetBytes();
789 if (src == nullptr) {
790 error = Status::FromErrorStringWithFormat(
791 format: "NativeRegisterContextLinux_x86_64::%s "
792 "DataBuffer::GetBytes() returned a null "
793 "pointer",
794 __FUNCTION__);
795 return error;
796 }
797 ::memcpy(dest: &m_gpr_x86_64, src: src, n: GetRegisterInfoInterface().GetGPRSize());
798
799 error = WriteGPR();
800 if (error.Fail())
801 return error;
802
803 src += GetRegisterInfoInterface().GetGPRSize();
804 if (m_xstate_type == XStateType::FXSAVE)
805 ::memcpy(dest: &m_xstate->fxsave, src: src, n: sizeof(m_xstate->fxsave));
806 else if (m_xstate_type == XStateType::XSAVE)
807 ::memcpy(dest: &m_xstate->xsave, src: src, n: sizeof(m_xstate->xsave));
808
809 error = WriteFPR();
810 if (error.Fail())
811 return error;
812
813 if (m_xstate_type == XStateType::XSAVE) {
814 lldb::ByteOrder byte_order = GetByteOrder();
815
816 if (IsCPUFeatureAvailable(feature_code: RegSet::avx)) {
817 // Parse the YMM register content from the register halves.
818 for (uint32_t reg = m_reg_info.first_ymm; reg <= m_reg_info.last_ymm;
819 ++reg) {
820 if (!CopyYMMtoXSTATE(reg, byte_order)) {
821 error = Status::FromErrorStringWithFormat(
822 format: "NativeRegisterContextLinux_x86_64::%s "
823 "CopyYMMtoXSTATE() failed for reg num "
824 "%" PRIu32,
825 __FUNCTION__, reg);
826 return error;
827 }
828 }
829 }
830
831 if (IsCPUFeatureAvailable(feature_code: RegSet::mpx)) {
832 for (uint32_t reg = m_reg_info.first_mpxr; reg <= m_reg_info.last_mpxc;
833 ++reg) {
834 if (!CopyMPXtoXSTATE(reg)) {
835 error = Status::FromErrorStringWithFormat(
836 format: "NativeRegisterContextLinux_x86_64::%s "
837 "CopyMPXtoXSTATE() failed for reg num "
838 "%" PRIu32,
839 __FUNCTION__, reg);
840 return error;
841 }
842 }
843 }
844 }
845
846 return error;
847}
848
849bool NativeRegisterContextLinux_x86_64::IsCPUFeatureAvailable(
850 RegSet feature_code) const {
851 if (m_xstate_type == XStateType::Invalid) {
852 if (const_cast<NativeRegisterContextLinux_x86_64 *>(this)->ReadFPR().Fail())
853 return false;
854 }
855 switch (feature_code) {
856 case RegSet::gpr:
857 case RegSet::fpu:
858 return true;
859 case RegSet::avx: // Check if CPU has AVX and if there is kernel support, by
860 // reading in the XCR0 area of XSAVE.
861 if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_AVX) == mask_XSTATE_AVX)
862 return true;
863 break;
864 case RegSet::mpx: // Check if CPU has MPX and if there is kernel support, by
865 // reading in the XCR0 area of XSAVE.
866 if ((m_xstate->xsave.i387.xcr0 & mask_XSTATE_MPX) == mask_XSTATE_MPX)
867 return true;
868 break;
869 }
870 return false;
871}
872
873bool NativeRegisterContextLinux_x86_64::IsRegisterSetAvailable(
874 uint32_t set_index) const {
875 uint32_t num_sets = k_num_register_sets - k_num_extended_register_sets;
876
877 switch (static_cast<RegSet>(set_index)) {
878 case RegSet::gpr:
879 case RegSet::fpu:
880 return (set_index < num_sets);
881 case RegSet::avx:
882 return IsCPUFeatureAvailable(feature_code: RegSet::avx);
883 case RegSet::mpx:
884 return IsCPUFeatureAvailable(feature_code: RegSet::mpx);
885 }
886 return false;
887}
888
889bool NativeRegisterContextLinux_x86_64::IsGPR(uint32_t reg_index) const {
890 // GPRs come first.
891 return reg_index <= m_reg_info.last_gpr;
892}
893
894bool NativeRegisterContextLinux_x86_64::IsFPR(uint32_t reg_index) const {
895 return (m_reg_info.first_fpr <= reg_index &&
896 reg_index <= m_reg_info.last_fpr);
897}
898
899bool NativeRegisterContextLinux_x86_64::IsDR(uint32_t reg_index) const {
900 return (m_reg_info.first_dr <= reg_index &&
901 reg_index <= m_reg_info.last_dr);
902}
903
904Status NativeRegisterContextLinux_x86_64::WriteFPR() {
905 switch (m_xstate_type) {
906 case XStateType::FXSAVE:
907 return WriteRegisterSet(
908 buf: &m_iovec, buf_size: sizeof(m_xstate->fxsave),
909 regset: fxsr_regset(arch: GetRegisterInfoInterface().GetTargetArchitecture()));
910 case XStateType::XSAVE:
911 return WriteRegisterSet(buf: &m_iovec, buf_size: sizeof(m_xstate->xsave), NT_X86_XSTATE);
912 default:
913 return Status::FromErrorString(str: "Unrecognized FPR type.");
914 }
915}
916
917bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {
918 if (!IsCPUFeatureAvailable(feature_code: RegSet::avx))
919 return false;
920 return (m_reg_info.first_ymm <= reg_index &&
921 reg_index <= m_reg_info.last_ymm);
922}
923
924bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoYMM(
925 uint32_t reg_index, lldb::ByteOrder byte_order) {
926 if (!IsAVX(reg_index))
927 return false;
928
929 if (byte_order == lldb::eByteOrderLittle) {
930 uint32_t reg_no = reg_index - m_reg_info.first_ymm;
931 m_ymm_set.ymm[reg_no] = XStateToYMM(
932 xmm_bytes: m_xstate->fxsave.xmm[reg_no].bytes,
933 ymmh_bytes: m_xstate->xsave.ymmh[reg_no].bytes);
934 return true;
935 }
936
937 return false; // unsupported or invalid byte order
938}
939
940bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(
941 uint32_t reg, lldb::ByteOrder byte_order) {
942 if (!IsAVX(reg_index: reg))
943 return false;
944
945 if (byte_order == lldb::eByteOrderLittle) {
946 uint32_t reg_no = reg - m_reg_info.first_ymm;
947 YMMToXState(input: m_ymm_set.ymm[reg_no],
948 xmm_bytes: m_xstate->fxsave.xmm[reg_no].bytes,
949 ymmh_bytes: m_xstate->xsave.ymmh[reg_no].bytes);
950 return true;
951 }
952
953 return false; // unsupported or invalid byte order
954}
955
956void *NativeRegisterContextLinux_x86_64::GetFPRBuffer() {
957 switch (m_xstate_type) {
958 case XStateType::FXSAVE:
959 return &m_xstate->fxsave;
960 case XStateType::XSAVE:
961 return &m_iovec;
962 default:
963 return nullptr;
964 }
965}
966
967size_t NativeRegisterContextLinux_x86_64::GetFPRSize() {
968 switch (m_xstate_type) {
969 case XStateType::FXSAVE:
970 return sizeof(m_xstate->fxsave);
971 case XStateType::XSAVE:
972 return sizeof(m_iovec);
973 default:
974 return 0;
975 }
976}
977
978Status NativeRegisterContextLinux_x86_64::ReadFPR() {
979 Status error;
980
981 // Probe XSAVE and if it is not supported fall back to FXSAVE.
982 if (m_xstate_type != XStateType::FXSAVE) {
983 error = ReadRegisterSet(buf: &m_iovec, buf_size: sizeof(m_xstate->xsave), NT_X86_XSTATE);
984 if (!error.Fail()) {
985 m_xstate_type = XStateType::XSAVE;
986 return error;
987 }
988 }
989 error = ReadRegisterSet(
990 buf: &m_iovec, buf_size: sizeof(m_xstate->xsave),
991 regset: fxsr_regset(arch: GetRegisterInfoInterface().GetTargetArchitecture()));
992 if (!error.Fail()) {
993 m_xstate_type = XStateType::FXSAVE;
994 return error;
995 }
996 return Status::FromErrorString(str: "Unrecognized FPR type.");
997}
998
999bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {
1000 if (!IsCPUFeatureAvailable(feature_code: RegSet::mpx))
1001 return false;
1002 return (m_reg_info.first_mpxr <= reg_index &&
1003 reg_index <= m_reg_info.last_mpxc);
1004}
1005
1006bool NativeRegisterContextLinux_x86_64::CopyXSTATEtoMPX(uint32_t reg) {
1007 if (!IsMPX(reg_index: reg))
1008 return false;
1009
1010 if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1011 ::memcpy(dest: m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,
1012 src: m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1013 n: sizeof(MPXReg));
1014 } else {
1015 ::memcpy(dest: m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,
1016 src: m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1017 n: sizeof(MPXCsr));
1018 }
1019 return true;
1020}
1021
1022bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {
1023 if (!IsMPX(reg_index: reg))
1024 return false;
1025
1026 if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {
1027 ::memcpy(dest: m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,
1028 src: m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, n: sizeof(MPXReg));
1029 } else {
1030 ::memcpy(dest: m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,
1031 src: m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, n: sizeof(MPXCsr));
1032 }
1033 return true;
1034}
1035
1036uint32_t
1037NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {
1038 // If register is MPX, remove extra factor from gdb offset
1039 return GetRegisterInfoAtIndex(reg_index)->byte_offset -
1040 (IsMPX(reg_index) ? 128 : 0);
1041}
1042
1043std::optional<NativeRegisterContextLinux::SyscallData>
1044NativeRegisterContextLinux_x86_64::GetSyscallData() {
1045 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1046 case llvm::Triple::x86: {
1047 static const uint8_t Int80[] = {0xcd, 0x80};
1048 static const uint32_t Args[] = {lldb_eax_i386, lldb_ebx_i386, lldb_ecx_i386,
1049 lldb_edx_i386, lldb_esi_i386, lldb_edi_i386,
1050 lldb_ebp_i386};
1051 return SyscallData{.Insn: Int80, .Args: Args, .Result: lldb_eax_i386};
1052 }
1053 case llvm::Triple::x86_64: {
1054 static const uint8_t Syscall[] = {0x0f, 0x05};
1055 static const uint32_t Args[] = {
1056 x86_64_with_base::lldb_rax, x86_64_with_base::lldb_rdi, x86_64_with_base::lldb_rsi, x86_64_with_base::lldb_rdx,
1057 x86_64_with_base::lldb_r10, x86_64_with_base::lldb_r8, x86_64_with_base::lldb_r9};
1058 return SyscallData{.Insn: Syscall, .Args: Args, .Result: x86_64_with_base::lldb_rax};
1059 }
1060 default:
1061 llvm_unreachable("Unhandled architecture!");
1062 }
1063}
1064
1065std::optional<NativeRegisterContextLinux::MmapData>
1066NativeRegisterContextLinux_x86_64::GetMmapData() {
1067 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1068 case llvm::Triple::x86:
1069 return MmapData{.SysMmap: 192, .SysMunmap: 91};
1070 case llvm::Triple::x86_64:
1071 return MmapData{.SysMmap: 9, .SysMunmap: 11};
1072 default:
1073 llvm_unreachable("Unhandled architecture!");
1074 }
1075}
1076
1077const RegisterInfo *NativeRegisterContextLinux_x86_64::GetDR(int num) const {
1078 assert(num >= 0 && num <= 7);
1079 switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
1080 case llvm::Triple::x86:
1081 return GetRegisterInfoAtIndex(reg_index: lldb_dr0_i386 + num);
1082 case llvm::Triple::x86_64:
1083 return GetRegisterInfoAtIndex(reg_index: x86_64_with_base::lldb_dr0 + num);
1084 default:
1085 llvm_unreachable("Unhandled target architecture.");
1086 }
1087}
1088
1089#endif // defined(__i386__) || defined(__x86_64__)
1090

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp