1090 lines · cpp
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-exception6//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 some25// older-but-still-supported ones (e.g. gcc 5.4.0) don't, so we26// 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 & 0x80000000, 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 flag55};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 flag73};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 flag84};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 flag95};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 r8113 x86_64_with_base::lldb_r9d, // Low 32 bits or r9114 x86_64_with_base::lldb_r10d, // Low 32 bits or r10115 x86_64_with_base::lldb_r11d, // Low 32 bits or r11116 x86_64_with_base::lldb_r12d, // Low 32 bits or r12117 x86_64_with_base::lldb_r13d, // Low 32 bits or r13118 x86_64_with_base::lldb_r14d, // Low 32 bits or r14119 x86_64_with_base::lldb_r15d, // Low 32 bits or r15120 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 r8123 x86_64_with_base::lldb_r9w, // Low 16 bits or r9124 x86_64_with_base::lldb_r10w, // Low 16 bits or r10125 x86_64_with_base::lldb_r11w, // Low 16 bits or r11126 x86_64_with_base::lldb_r12w, // Low 16 bits or r12127 x86_64_with_base::lldb_r13w, // Low 16 bits or r13128 x86_64_with_base::lldb_r14w, // Low 16 bits or r14129 x86_64_with_base::lldb_r15w, // Low 16 bits or r15130 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 r8134 x86_64_with_base::lldb_r9l, // Low 8 bits or r9135 x86_64_with_base::lldb_r10l, // Low 8 bits or r10136 x86_64_with_base::lldb_r11l, // Low 8 bits or r11137 x86_64_with_base::lldb_r12l, // Low 8 bits or r12138 x86_64_with_base::lldb_r13l, // Low 8 bits or r13139 x86_64_with_base::lldb_r14l, // Low 8 bits or r14140 x86_64_with_base::lldb_r15l, // Low 8 bits or r15141 LLDB_INVALID_REGNUM // register sets need to end with this flag142};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 flag166};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 flag179};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 flag190};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 {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,202 g_gpr_regnums_i386},203 {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,204 g_fpu_regnums_i386},205 {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,206 g_avx_regnums_i386},207 { "Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,208 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 {"General Purpose Registers", "gpr", x86_64_with_base::k_num_gpr_registers,213 g_gpr_regnums_x86_64},214 {"Floating Point Registers", "fpu", x86_64_with_base::k_num_fpr_registers,215 g_fpu_regnums_x86_64},216 {"Advanced Vector Extensions", "avx", x86_64_with_base::k_num_avx_registers,217 g_avx_regnums_x86_64},218 { "Memory Protection Extensions", "mpx", x86_64_with_base::k_num_mpx_registers,219 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 support226#ifndef NT_X86_XSTATE227#define NT_X86_XSTATE 0x202228#endif229#ifndef NT_PRXFPREG230#define NT_PRXFPREG 0x46e62b7f231#endif232 233// On x86_64 NT_PRFPREG is used to access the FXSAVE area. On i386, we need to234// 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_MPX243#define bit_MPX 0x4000244#endif245 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, 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>(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 the276 // x86_64 register context.277 return std::make_unique<RegisterContextLinux_x86_64>(target_arch);278 }279}280 281// Return the size of the XSTATE area supported on this cpu. It is necessary to282// allocate the full size of the area even if we do not use/recognise all of it283// because ptrace(PTRACE_SETREGSET, NT_X86_XSTATE) will refuse to write to it if284// we do not pass it a buffer of sufficient size. The size is always at least285// 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(1, &eax, &ebx, &ecx, &edx) || !(ecx & bit_XSAVE))290 return sizeof(FPR);291 292 // Then fetch the maximum size of the area.293 if (!get_cpuid_count(0x0d, 0, &eax, &ebx, &ecx, &edx))294 return sizeof(FPR);295 return std::max<std::size_t>(ecx, 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(static_cast<FPR *>(std::malloc(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(m_xstate.get(), 0, xstate_size);370 371 // Store byte offset of fctrl (i.e. first register of FPR)372 const RegisterInfo *reg_info_fctrl = GetRegisterInfoByName("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 can377// 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 416Status417NativeRegisterContextLinux_x86_64::ReadRegister(const RegisterInfo *reg_info,418 RegisterValue ®_value) {419 Status error;420 421 if (!reg_info) {422 error = Status::FromErrorString("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 be429 // directly queried.430 error = Status::FromErrorStringWithFormat(431 "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) || IsAVX(reg) || IsMPX(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(full_reg, reg_value);452 453 if (error.Success()) {454 // If our read was not aligned (for ah,bh,ch,dh), shift our returned455 // value one byte to the right.456 if (is_subreg && (reg_info->byte_offset & 0x1))457 reg_value.SetUInt64(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_t461 // default462 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 m_xstate->fxsave.stmm[reg - m_reg_info.first_st].bytes,475 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 m_xstate->fxsave.stmm[reg - m_reg_info.first_mm].bytes,479 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 m_xstate->fxsave.xmm[reg - m_reg_info.first_xmm].bytes,483 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 and486 // ymmh.bytes487 if (CopyXSTATEtoYMM(reg, byte_order))488 reg_value.SetBytes(m_ymm_set.ymm[reg - m_reg_info.first_ymm].bytes,489 reg_info->byte_size, byte_order);490 else {491 error = Status::FromErrorString("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(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,498 reg_info->byte_size, byte_order);499 else {500 error = Status::FromErrorString("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(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,507 reg_info->byte_size, byte_order);508 else {509 error = Status::FromErrorString("failed to copy mpx register value");510 return error;511 }512 }513 514 if (reg_value.GetType() != RegisterValue::eTypeBytes)515 error = Status::FromErrorString(516 "write failed - type was expected to be RegisterValue::eTypeBytes");517 518 return error;519 }520 521 error = Status::FromErrorString("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 of530 // fpu registers, m_fpr should be read at byte offsets calculated wrt to FPR531 // 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 m_xstate->fxsave.ftag, m_xstate->fxsave.fstat, 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(*(uint32_t *)src);555 break;556 case 8:557 reg_value.SetUInt64(*(uint64_t *)src);558 break;559 default:560 assert(false && "Unhandled data size.");561 error = Status::FromErrorStringWithFormat("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 these574 // 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 ®_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 "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(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_st].bytes,604 reg_value.GetBytes(), reg_value.GetByteSize());605 606 if (reg_index >= m_reg_info.first_mm && reg_index <= m_reg_info.last_mm)607 ::memcpy(m_xstate->fxsave.stmm[reg_index - m_reg_info.first_mm].bytes,608 reg_value.GetBytes(), reg_value.GetByteSize());609 610 if (reg_index >= m_reg_info.first_xmm && reg_index <= m_reg_info.last_xmm)611 ::memcpy(m_xstate->fxsave.xmm[reg_index - m_reg_info.first_xmm].bytes,612 reg_value.GetBytes(), 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 in617 // xmm.bytes and ymmh.bytes618 ::memcpy(m_ymm_set.ymm[reg_index - m_reg_info.first_ymm].bytes,619 reg_value.GetBytes(), reg_value.GetByteSize());620 if (!CopyYMMtoXSTATE(reg_index, GetByteOrder()))621 return Status::FromErrorString("CopyYMMtoXSTATE() failed");622 }623 624 if (reg_index >= m_reg_info.first_mpxr &&625 reg_index <= m_reg_info.last_mpxr) {626 ::memcpy(m_mpx_set.mpxr[reg_index - m_reg_info.first_mpxr].bytes,627 reg_value.GetBytes(), reg_value.GetByteSize());628 if (!CopyMPXtoXSTATE(reg_index))629 return Status::FromErrorString("CopyMPXtoXSTATE() failed");630 }631 632 if (reg_index >= m_reg_info.first_mpxc &&633 reg_index <= m_reg_info.last_mpxc) {634 ::memcpy(m_mpx_set.mpxc[reg_index - m_reg_info.first_mpxc].bytes,635 reg_value.GetBytes(), reg_value.GetByteSize());636 if (!CopyMPXtoXSTATE(reg_index))637 return Status::FromErrorString("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 writes644 // only fpu registers using ptrace(PTRACE_SETFPREGS,..) API. Hence fpu645 // registers should be written in m_fpr at byte offsets calculated wrt646 // 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(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 "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_index, GetByteOrder()))686 return Status::FromErrorString("CopyYMMtoXSTATE() failed");687 }688 689 if (IsMPX(reg_index)) {690 if (!CopyMPXtoXSTATE(reg_index))691 return Status::FromErrorString("CopyMPXtoXSTATE() failed");692 }693 return Status();694 }695 return Status::FromErrorString(696 "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(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(dst, &m_gpr_x86_64, GetRegisterInfoInterface().GetGPRSize());715 dst += GetRegisterInfoInterface().GetGPRSize();716 if (m_xstate_type == XStateType::FXSAVE)717 ::memcpy(dst, &m_xstate->fxsave, sizeof(m_xstate->fxsave));718 else if (m_xstate_type == XStateType::XSAVE) {719 lldb::ByteOrder byte_order = GetByteOrder();720 721 if (IsCPUFeatureAvailable(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, byte_order)) {726 error = Status::FromErrorStringWithFormat(727 "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(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 "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(dst, m_xstate.get(), sizeof(FPR));751 } else {752 assert(false && "how do we save the floating point registers?");753 error = Status::FromErrorString(754 "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 to758 * -1 to solve the bug 23659, such a setting prevents the automatic759 * decrement of the instruction pointer which was causing the SIGILL760 * exception.761 * **/762 763 RegisterValue value((uint64_t)-1);764 const RegisterInfo &info = GetRegisterInfo().GetOrigAxInfo();765 return DoWriteRegisterValue(info.byte_offset, 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 "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 "data_sp contained mismatched data size, expected {0}, actual {1}",784 REG_CONTEXT_SIZE, 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 "NativeRegisterContextLinux_x86_64::%s "792 "DataBuffer::GetBytes() returned a null "793 "pointer",794 __FUNCTION__);795 return error;796 }797 ::memcpy(&m_gpr_x86_64, src, 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(&m_xstate->fxsave, src, sizeof(m_xstate->fxsave));806 else if (m_xstate_type == XStateType::XSAVE)807 ::memcpy(&m_xstate->xsave, src, 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(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 "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(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 "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, by860 // 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, by865 // 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(RegSet::avx);883 case RegSet::mpx:884 return IsCPUFeatureAvailable(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 &m_iovec, sizeof(m_xstate->fxsave),909 fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));910 case XStateType::XSAVE:911 return WriteRegisterSet(&m_iovec, sizeof(m_xstate->xsave), NT_X86_XSTATE);912 default:913 return Status::FromErrorString("Unrecognized FPR type.");914 }915}916 917bool NativeRegisterContextLinux_x86_64::IsAVX(uint32_t reg_index) const {918 if (!IsCPUFeatureAvailable(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 m_xstate->fxsave.xmm[reg_no].bytes,933 m_xstate->xsave.ymmh[reg_no].bytes);934 return true;935 }936 937 return false; // unsupported or invalid byte order938}939 940bool NativeRegisterContextLinux_x86_64::CopyYMMtoXSTATE(941 uint32_t reg, lldb::ByteOrder byte_order) {942 if (!IsAVX(reg))943 return false;944 945 if (byte_order == lldb::eByteOrderLittle) {946 uint32_t reg_no = reg - m_reg_info.first_ymm;947 YMMToXState(m_ymm_set.ymm[reg_no],948 m_xstate->fxsave.xmm[reg_no].bytes,949 m_xstate->xsave.ymmh[reg_no].bytes);950 return true;951 }952 953 return false; // unsupported or invalid byte order954}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(&m_iovec, 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 &m_iovec, sizeof(m_xstate->xsave),991 fxsr_regset(GetRegisterInfoInterface().GetTargetArchitecture()));992 if (!error.Fail()) {993 m_xstate_type = XStateType::FXSAVE;994 return error;995 }996 return Status::FromErrorString("Unrecognized FPR type.");997}998 999bool NativeRegisterContextLinux_x86_64::IsMPX(uint32_t reg_index) const {1000 if (!IsCPUFeatureAvailable(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))1008 return false;1009 1010 if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {1011 ::memcpy(m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes,1012 m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,1013 sizeof(MPXReg));1014 } else {1015 ::memcpy(m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes,1016 m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,1017 sizeof(MPXCsr));1018 }1019 return true;1020}1021 1022bool NativeRegisterContextLinux_x86_64::CopyMPXtoXSTATE(uint32_t reg) {1023 if (!IsMPX(reg))1024 return false;1025 1026 if (reg >= m_reg_info.first_mpxr && reg <= m_reg_info.last_mpxr) {1027 ::memcpy(m_xstate->xsave.mpxr[reg - m_reg_info.first_mpxr].bytes,1028 m_mpx_set.mpxr[reg - m_reg_info.first_mpxr].bytes, sizeof(MPXReg));1029 } else {1030 ::memcpy(m_xstate->xsave.mpxc[reg - m_reg_info.first_mpxc].bytes,1031 m_mpx_set.mpxc[reg - m_reg_info.first_mpxc].bytes, sizeof(MPXCsr));1032 }1033 return true;1034}1035 1036uint32_t1037NativeRegisterContextLinux_x86_64::GetPtraceOffset(uint32_t reg_index) {1038 // If register is MPX, remove extra factor from gdb offset1039 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{Int80, Args, 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{Syscall, Args, 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{192, 91};1070 case llvm::Triple::x86_64:1071 return MmapData{9, 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(lldb_dr0_i386 + num);1082 case llvm::Triple::x86_64:1083 return GetRegisterInfoAtIndex(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