1//===-- RegisterContextLinux_i386.cpp --------------------------*- 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-exception
6//
7//===---------------------------------------------------------------------===//
8
9#include "RegisterContextLinux_i386.h"
10#include "RegisterContextPOSIX_x86.h"
11
12using namespace lldb_private;
13using namespace lldb;
14
15struct GPR {
16  uint32_t ebx;
17  uint32_t ecx;
18  uint32_t edx;
19  uint32_t esi;
20  uint32_t edi;
21  uint32_t ebp;
22  uint32_t eax;
23  uint32_t ds;
24  uint32_t es;
25  uint32_t fs;
26  uint32_t gs;
27  uint32_t orig_eax;
28  uint32_t eip;
29  uint32_t cs;
30  uint32_t eflags;
31  uint32_t esp;
32  uint32_t ss;
33};
34
35struct FPR_i386 {
36  uint16_t fctrl;     // FPU Control Word (fcw)
37  uint16_t fstat;     // FPU Status Word (fsw)
38  uint16_t ftag;      // FPU Tag Word (ftw)
39  uint16_t fop;       // Last Instruction Opcode (fop)
40  union {
41    struct {
42      uint64_t fip; // Instruction Pointer
43      uint64_t fdp; // Data Pointer
44    } x86_64;
45    struct {
46      uint32_t fioff; // FPU IP Offset (fip)
47      uint32_t fiseg; // FPU IP Selector (fcs)
48      uint32_t fooff; // FPU Operand Pointer Offset (foo)
49      uint32_t foseg; // FPU Operand Pointer Selector (fos)
50    } i386_; // Added _ in the end to avoid error with gcc defining i386 in some
51             // cases
52  } ptr;
53  uint32_t mxcsr;     // MXCSR Register State
54  uint32_t mxcsrmask; // MXCSR Mask
55  MMSReg stmm[8];     // 8*16 bytes for each FP-reg = 128 bytes
56  XMMReg xmm[8];      // 8*16 bytes for each XMM-reg = 128 bytes
57  uint32_t padding[56];
58};
59
60struct UserArea {
61  GPR regs;               // General purpose registers.
62  int32_t fpvalid;        // True if FPU is being used.
63  FPR_i386 i387;          // FPU registers.
64  uint32_t tsize;         // Text segment size.
65  uint32_t dsize;         // Data segment size.
66  uint32_t ssize;         // Stack segment size.
67  uint32_t start_code;    // VM address of text.
68  uint32_t start_stack;   // VM address of stack bottom (top in rsp).
69  int32_t signal;         // Signal causing core dump.
70  int32_t reserved;       // Unused.
71  uint32_t ar0;           // Location of GPR's.
72  uint32_t fpstate;       // Location of FPR's. Should be a FXSTATE *, but this
73                          //  has to be 32-bits even on 64-bit systems.
74  uint32_t magic;         // Identifier for core dumps.
75  char u_comm[32];        // Command causing core dump.
76  uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
77};
78
79#define DR_SIZE sizeof(((UserArea *)NULL)->u_debugreg[0])
80#define DR_0_OFFSET 0xFC
81#define DR_OFFSET(reg_index) (DR_0_OFFSET + (reg_index * 4))
82#define FPR_SIZE(reg) sizeof(((FPR_i386 *)NULL)->reg)
83
84// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
85#define DECLARE_REGISTER_INFOS_I386_STRUCT
86#include "RegisterInfos_i386.h"
87#undef DECLARE_REGISTER_INFOS_I386_STRUCT
88
89RegisterContextLinux_i386::RegisterContextLinux_i386(
90    const ArchSpec &target_arch)
91    : RegisterInfoInterface(target_arch) {
92  RegisterInfo orig_ax = {"orig_eax",
93                          nullptr,
94                          sizeof(((GPR *)nullptr)->orig_eax),
95                          (LLVM_EXTENSION offsetof(GPR, orig_eax)),
96                          eEncodingUint,
97                          eFormatHex,
98                          {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
99                           LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
100                           LLDB_INVALID_REGNUM},
101                          nullptr,
102                          nullptr,
103                          nullptr,
104                          0};
105  d_register_infos.push_back(orig_ax);
106}
107
108size_t RegisterContextLinux_i386::GetGPRSize() const { return sizeof(GPR); }
109
110const RegisterInfo *RegisterContextLinux_i386::GetRegisterInfo() const {
111  switch (m_target_arch.GetMachine()) {
112  case llvm::Triple::x86:
113  case llvm::Triple::x86_64:
114    return g_register_infos_i386;
115  default:
116    assert(false && "Unhandled target architecture.");
117    return nullptr;
118  }
119}
120
121uint32_t RegisterContextLinux_i386::GetRegisterCount() const {
122  return static_cast<uint32_t>(sizeof(g_register_infos_i386) /
123                               sizeof(g_register_infos_i386[0]));
124}
125
126uint32_t RegisterContextLinux_i386::GetUserRegisterCount() const {
127  return static_cast<uint32_t>(k_num_user_registers_i386);
128}
129
130const std::vector<lldb_private::RegisterInfo> *
131RegisterContextLinux_i386::GetDynamicRegisterInfoP() const {
132  return &d_register_infos;
133}
134