396 lines · c
1//===-- RegisterContext_x86.h -----------------------------------*- C++ -*-===//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#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H10#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H11 12#include <cstddef>13#include <cstdint>14 15#include "llvm/ADT/ArrayRef.h"16#include "llvm/ADT/BitmaskEnum.h"17#include "llvm/Support/Compiler.h"18 19namespace lldb_private {20// i386 ehframe, dwarf regnums21 22// Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems23// (non-Darwin)24//25enum {26 ehframe_eax_i386 = 0,27 ehframe_ecx_i386,28 ehframe_edx_i386,29 ehframe_ebx_i386,30 31 // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus32 // dwarf's reg numbering).33 // To be specific:34 // i386+darwin eh_frame: 4 is ebp, 5 is esp35 // i386+everyone else eh_frame: 4 is esp, 5 is ebp36 // i386 dwarf: 4 is esp, 5 is ebp37 // lldb will get the darwin-specific eh_frame reg numberings from debugserver,38 // or the ABI, so we39 // only encode the generally correct 4 == esp, 5 == ebp numbers in this40 // generic header.41 42 ehframe_esp_i386,43 ehframe_ebp_i386,44 ehframe_esi_i386,45 ehframe_edi_i386,46 ehframe_eip_i386,47 ehframe_eflags_i386,48 ehframe_st0_i386 = 12,49 ehframe_st1_i386,50 ehframe_st2_i386,51 ehframe_st3_i386,52 ehframe_st4_i386,53 ehframe_st5_i386,54 ehframe_st6_i386,55 ehframe_st7_i386,56 ehframe_xmm0_i386 = 21,57 ehframe_xmm1_i386,58 ehframe_xmm2_i386,59 ehframe_xmm3_i386,60 ehframe_xmm4_i386,61 ehframe_xmm5_i386,62 ehframe_xmm6_i386,63 ehframe_xmm7_i386,64 ehframe_mm0_i386 = 29,65 ehframe_mm1_i386,66 ehframe_mm2_i386,67 ehframe_mm3_i386,68 ehframe_mm4_i386,69 ehframe_mm5_i386,70 ehframe_mm6_i386,71 ehframe_mm7_i386,72};73 74// DWARF register numbers (eRegisterKindDWARF)75// Intel's x86 or IA-3276enum {77 // General Purpose Registers.78 dwarf_eax_i386 = 0,79 dwarf_ecx_i386,80 dwarf_edx_i386,81 dwarf_ebx_i386,82 dwarf_esp_i386,83 dwarf_ebp_i386,84 dwarf_esi_i386,85 dwarf_edi_i386,86 dwarf_eip_i386,87 dwarf_eflags_i386,88 // Floating Point Registers89 dwarf_st0_i386 = 11,90 dwarf_st1_i386,91 dwarf_st2_i386,92 dwarf_st3_i386,93 dwarf_st4_i386,94 dwarf_st5_i386,95 dwarf_st6_i386,96 dwarf_st7_i386,97 // SSE Registers98 dwarf_xmm0_i386 = 21,99 dwarf_xmm1_i386,100 dwarf_xmm2_i386,101 dwarf_xmm3_i386,102 dwarf_xmm4_i386,103 dwarf_xmm5_i386,104 dwarf_xmm6_i386,105 dwarf_xmm7_i386,106 // MMX Registers107 dwarf_mm0_i386 = 29,108 dwarf_mm1_i386,109 dwarf_mm2_i386,110 dwarf_mm3_i386,111 dwarf_mm4_i386,112 dwarf_mm5_i386,113 dwarf_mm6_i386,114 dwarf_mm7_i386,115 dwarf_fctrl_i386 = 37, // x87 control word116 dwarf_fstat_i386 = 38, // x87 status word117 dwarf_mxcsr_i386 = 39,118 dwarf_es_i386 = 40,119 dwarf_cs_i386 = 41,120 dwarf_ss_i386 = 42,121 dwarf_ds_i386 = 43,122 dwarf_fs_i386 = 44,123 dwarf_gs_i386 = 45,124 125 // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and126 // then differentiate based on size of the register.127 dwarf_bnd0_i386 = 101,128 dwarf_bnd1_i386,129 dwarf_bnd2_i386,130 dwarf_bnd3_i386,131};132 133// AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums134 135// EHFrame and DWARF Register numbers (eRegisterKindEHFrame &136// eRegisterKindDWARF)137// This is the spec I used (as opposed to x86-64-abi-0.99.pdf):138// http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf139enum {140 // GP Registers141 dwarf_rax_x86_64 = 0,142 dwarf_rdx_x86_64,143 dwarf_rcx_x86_64,144 dwarf_rbx_x86_64,145 dwarf_rsi_x86_64,146 dwarf_rdi_x86_64,147 dwarf_rbp_x86_64,148 dwarf_rsp_x86_64,149 // Extended GP Registers150 dwarf_r8_x86_64 = 8,151 dwarf_r9_x86_64,152 dwarf_r10_x86_64,153 dwarf_r11_x86_64,154 dwarf_r12_x86_64,155 dwarf_r13_x86_64,156 dwarf_r14_x86_64,157 dwarf_r15_x86_64,158 // Return Address (RA) mapped to RIP159 dwarf_rip_x86_64 = 16,160 // SSE Vector Registers161 dwarf_xmm0_x86_64 = 17,162 dwarf_xmm1_x86_64,163 dwarf_xmm2_x86_64,164 dwarf_xmm3_x86_64,165 dwarf_xmm4_x86_64,166 dwarf_xmm5_x86_64,167 dwarf_xmm6_x86_64,168 dwarf_xmm7_x86_64,169 dwarf_xmm8_x86_64,170 dwarf_xmm9_x86_64,171 dwarf_xmm10_x86_64,172 dwarf_xmm11_x86_64,173 dwarf_xmm12_x86_64,174 dwarf_xmm13_x86_64,175 dwarf_xmm14_x86_64,176 dwarf_xmm15_x86_64,177 // Floating Point Registers178 dwarf_st0_x86_64 = 33,179 dwarf_st1_x86_64,180 dwarf_st2_x86_64,181 dwarf_st3_x86_64,182 dwarf_st4_x86_64,183 dwarf_st5_x86_64,184 dwarf_st6_x86_64,185 dwarf_st7_x86_64,186 // MMX Registers187 dwarf_mm0_x86_64 = 41,188 dwarf_mm1_x86_64,189 dwarf_mm2_x86_64,190 dwarf_mm3_x86_64,191 dwarf_mm4_x86_64,192 dwarf_mm5_x86_64,193 dwarf_mm6_x86_64,194 dwarf_mm7_x86_64,195 // Control and Status Flags Register196 dwarf_rflags_x86_64 = 49,197 // selector registers198 dwarf_es_x86_64 = 50,199 dwarf_cs_x86_64,200 dwarf_ss_x86_64,201 dwarf_ds_x86_64,202 dwarf_fs_x86_64,203 dwarf_gs_x86_64,204 // Base registers205 dwarf_fs_base_x86_64 = 58,206 dwarf_gs_base_x86_64 = 59,207 // Floating point control registers208 dwarf_mxcsr_x86_64 = 64, // Media Control and Status209 dwarf_fctrl_x86_64, // x87 control word210 dwarf_fstat_x86_64, // x87 status word211 // Upper Vector Registers212 dwarf_ymm0h_x86_64 = 67,213 dwarf_ymm1h_x86_64,214 dwarf_ymm2h_x86_64,215 dwarf_ymm3h_x86_64,216 dwarf_ymm4h_x86_64,217 dwarf_ymm5h_x86_64,218 dwarf_ymm6h_x86_64,219 dwarf_ymm7h_x86_64,220 dwarf_ymm8h_x86_64,221 dwarf_ymm9h_x86_64,222 dwarf_ymm10h_x86_64,223 dwarf_ymm11h_x86_64,224 dwarf_ymm12h_x86_64,225 dwarf_ymm13h_x86_64,226 dwarf_ymm14h_x86_64,227 dwarf_ymm15h_x86_64,228 // MPX registers229 dwarf_bnd0_x86_64 = 126,230 dwarf_bnd1_x86_64,231 dwarf_bnd2_x86_64,232 dwarf_bnd3_x86_64,233 // AVX2 Vector Mask Registers234 // dwarf_k0_x86_64 = 118,235 // dwarf_k1_x86_64,236 // dwarf_k2_x86_64,237 // dwarf_k3_x86_64,238 // dwarf_k4_x86_64,239 // dwarf_k5_x86_64,240 // dwarf_k6_x86_64,241 // dwarf_k7_x86_64,242};243 244// Generic floating-point registers245 246LLVM_PACKED_START247struct MMSRegComp {248 uint64_t mantissa;249 uint16_t sign_exp;250};251 252struct MMSReg {253 union {254 uint8_t bytes[10];255 MMSRegComp comp;256 };257 uint8_t pad[6];258};259LLVM_PACKED_END260 261static_assert(sizeof(MMSRegComp) == 10, "MMSRegComp is not 10 bytes of size");262static_assert(sizeof(MMSReg) == 16, "MMSReg is not 16 bytes of size");263 264struct XMMReg {265 uint8_t bytes[16]; // 128-bits for each XMM register266};267 268// i387_fxsave_struct269struct FXSAVE {270 uint16_t fctrl; // FPU Control Word (fcw)271 uint16_t fstat; // FPU Status Word (fsw)272 uint16_t ftag; // FPU Tag Word (ftw)273 uint16_t fop; // Last Instruction Opcode (fop)274 union {275 struct {276 uint64_t fip; // Instruction Pointer277 uint64_t fdp; // Data Pointer278 } x86_64;279 struct {280 uint32_t fioff; // FPU IP Offset (fip)281 uint32_t fiseg; // FPU IP Selector (fcs)282 uint32_t fooff; // FPU Operand Pointer Offset (foo)283 uint32_t foseg; // FPU Operand Pointer Selector (fos)284 } i386_; // Added _ in the end to avoid error with gcc defining i386 in some285 // cases286 } ptr;287 uint32_t mxcsr; // MXCSR Register State288 uint32_t mxcsrmask; // MXCSR Mask289 MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes290 XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes291 uint8_t padding1[48];292 uint64_t xcr0;293 uint8_t padding2[40];294};295 296// Extended floating-point registers297 298struct YMMHReg {299 uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register300};301 302struct YMMReg {303 uint8_t bytes[32]; // 16 * 16 bits for each YMM register304};305 306struct YMM {307 YMMReg ymm[16]; // assembled from ymmh and xmm registers308};309 310struct MPXReg {311 uint8_t bytes[16]; // MPX 128 bit bound registers312};313 314struct MPXCsr {315 uint8_t bytes[8]; // MPX 64 bit bndcfgu and bndstatus registers (collectively316 // BNDCSR state)317};318 319struct MPX {320 MPXReg mpxr[4];321 MPXCsr mpxc[2];322};323 324LLVM_PACKED_START325struct XSAVE_HDR {326 enum class XFeature : uint64_t {327 FP = 1,328 SSE = FP << 1,329 YMM = SSE << 1,330 BNDREGS = YMM << 1,331 BNDCSR = BNDREGS << 1,332 OPMASK = BNDCSR << 1,333 ZMM_Hi256 = OPMASK << 1,334 Hi16_ZMM = ZMM_Hi256 << 1,335 PT = Hi16_ZMM << 1,336 PKRU = PT << 1,337 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ PKRU)338 };339 340 XFeature xstate_bv; // OS enabled xstate mask to determine the extended states341 // supported by the processor342 XFeature xcomp_bv; // Mask to indicate the format of the XSAVE area and of343 // the XRSTOR instruction344 uint64_t reserved1[1];345 uint64_t reserved2[5];346};347static_assert(sizeof(XSAVE_HDR) == 64, "XSAVE_HDR layout incorrect");348LLVM_PACKED_END349 350// x86 extensions to FXSAVE (i.e. for AVX and MPX processors)351LLVM_PACKED_START352struct XSAVE {353 FXSAVE i387; // floating point registers typical in i387_fxsave_struct354 XSAVE_HDR header; // The xsave_hdr_struct can be used to determine if the355 // following extensions are usable356 YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes357 // are in FXSAVE.xmm for compatibility with SSE)358 uint64_t reserved3[16];359 MPXReg mpxr[4]; // MPX BNDREG state, containing 128-bit bound registers360 MPXCsr mpxc[2]; // MPX BNDCSR state, containing 64-bit BNDCFGU and361 // BNDSTATUS registers362};363LLVM_PACKED_END364 365// Floating-point registers366union FPR {367 FXSAVE fxsave; // Generic floating-point registers.368 XSAVE xsave; // x86 extended processor state.369};370 371LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();372 373// Convenience function to combine YMM register data from XSAVE-style input.374inline YMMReg XStateToYMM(const void* xmm_bytes, const void* ymmh_bytes) {375 YMMReg ret;376 377 ::memcpy(ret.bytes, xmm_bytes, sizeof(XMMReg));378 ::memcpy(ret.bytes + sizeof(XMMReg), ymmh_bytes, sizeof(YMMHReg));379 380 return ret;381}382 383// Convenience function to copy YMM register data into XSAVE-style output.384inline void YMMToXState(const YMMReg& input, void* xmm_bytes, void* ymmh_bytes) {385 ::memcpy(xmm_bytes, input.bytes, sizeof(XMMReg));386 ::memcpy(ymmh_bytes, input.bytes + sizeof(XMMReg), sizeof(YMMHReg));387}388 389uint16_t AbridgedToFullTagWord(uint8_t abridged_tw, uint16_t sw,390 llvm::ArrayRef<MMSReg> st_regs);391uint8_t FullToAbridgedTagWord(uint16_t tw);392 393} // namespace lldb_private394 395#endif396