1//===-- RegisterContextDarwin_x86_64.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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H
10#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H
11
12#include "lldb/Target/RegisterContext.h"
13#include "lldb/lldb-private.h"
14
15class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext {
16public:
17  RegisterContextDarwin_x86_64(lldb_private::Thread &thread,
18                               uint32_t concrete_frame_idx);
19
20  ~RegisterContextDarwin_x86_64() override;
21
22  void InvalidateAllRegisters() override;
23
24  size_t GetRegisterCount() override;
25
26  const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
27
28  size_t GetRegisterSetCount() override;
29
30  const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
31
32  bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
33                    lldb_private::RegisterValue &value) override;
34
35  bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
36                     const lldb_private::RegisterValue &value) override;
37
38  bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
39
40  bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
41
42  uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
43                                               uint32_t num) override;
44
45  bool HardwareSingleStep(bool enable) override;
46
47  struct GPR {
48    uint64_t rax;
49    uint64_t rbx;
50    uint64_t rcx;
51    uint64_t rdx;
52    uint64_t rdi;
53    uint64_t rsi;
54    uint64_t rbp;
55    uint64_t rsp;
56    uint64_t r8;
57    uint64_t r9;
58    uint64_t r10;
59    uint64_t r11;
60    uint64_t r12;
61    uint64_t r13;
62    uint64_t r14;
63    uint64_t r15;
64    uint64_t rip;
65    uint64_t rflags;
66    uint64_t cs;
67    uint64_t fs;
68    uint64_t gs;
69  };
70
71  struct MMSReg {
72    uint8_t bytes[10];
73    uint8_t pad[6];
74  };
75
76  struct XMMReg {
77    uint8_t bytes[16];
78  };
79
80  struct FPU {
81    uint32_t pad[2];
82    uint16_t fcw; // "fctrl"
83    uint16_t fsw; // "fstat"
84    uint8_t ftw;  // "ftag"
85    uint8_t pad1;
86    uint16_t fop; // "fop"
87    uint32_t ip;  // "fioff"
88    uint16_t cs;  // "fiseg"
89    uint16_t pad2;
90    uint32_t dp; // "fooff"
91    uint16_t ds; // "foseg"
92    uint16_t pad3;
93    uint32_t mxcsr;
94    uint32_t mxcsrmask;
95    MMSReg stmm[8];
96    XMMReg xmm[16];
97    uint8_t pad4[6 * 16];
98    int pad5;
99  };
100
101  struct EXC {
102    uint32_t trapno;
103    uint32_t err;
104    uint64_t faultvaddr;
105  };
106
107protected:
108  enum { GPRRegSet = 4, FPURegSet = 5, EXCRegSet = 6 };
109
110  enum {
111    GPRWordCount = sizeof(GPR) / sizeof(uint32_t),
112    FPUWordCount = sizeof(FPU) / sizeof(uint32_t),
113    EXCWordCount = sizeof(EXC) / sizeof(uint32_t)
114  };
115
116  enum { Read = 0, Write = 1, kNumErrors = 2 };
117
118  GPR gpr;
119  FPU fpu;
120  EXC exc;
121  int gpr_errs[2]; // Read/Write errors
122  int fpu_errs[2]; // Read/Write errors
123  int exc_errs[2]; // Read/Write errors
124
125  void InvalidateAllRegisterStates() {
126    SetError(GPRRegSet, Read, -1);
127    SetError(FPURegSet, Read, -1);
128    SetError(EXCRegSet, Read, -1);
129  }
130
131  int GetError(int flavor, uint32_t err_idx) const {
132    if (err_idx < kNumErrors) {
133      switch (flavor) {
134      // When getting all errors, just OR all values together to see if
135      // we got any kind of error.
136      case GPRRegSet:
137        return gpr_errs[err_idx];
138      case FPURegSet:
139        return fpu_errs[err_idx];
140      case EXCRegSet:
141        return exc_errs[err_idx];
142      default:
143        break;
144      }
145    }
146    return -1;
147  }
148
149  bool SetError(int flavor, uint32_t err_idx, int err) {
150    if (err_idx < kNumErrors) {
151      switch (flavor) {
152      case GPRRegSet:
153        gpr_errs[err_idx] = err;
154        return true;
155
156      case FPURegSet:
157        fpu_errs[err_idx] = err;
158        return true;
159
160      case EXCRegSet:
161        exc_errs[err_idx] = err;
162        return true;
163
164      default:
165        break;
166      }
167    }
168    return false;
169  }
170
171  bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; }
172
173  void LogGPR(lldb_private::Log *log, const char *format, ...);
174
175  int ReadGPR(bool force);
176
177  int ReadFPU(bool force);
178
179  int ReadEXC(bool force);
180
181  int WriteGPR();
182
183  int WriteFPU();
184
185  int WriteEXC();
186
187  // Subclasses override these to do the actual reading.
188  virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) = 0;
189
190  virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) = 0;
191
192  virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0;
193
194  virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
195
196  virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
197
198  virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0;
199
200  int ReadRegisterSet(uint32_t set, bool force);
201
202  int WriteRegisterSet(uint32_t set);
203
204  static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num);
205
206  static int GetSetForNativeRegNum(int reg_num);
207
208  static size_t GetRegisterInfosCount();
209
210  static const lldb_private::RegisterInfo *GetRegisterInfos();
211};
212
213#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_X86_64_H
214