1//===-- RegisterContextNetBSD_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#include "RegisterContextNetBSD_x86_64.h"
10#include "RegisterContextNetBSD_i386.h"
11#include "RegisterContextPOSIX_x86.h"
12#include "llvm/Support/Compiler.h"
13#include "llvm/TargetParser/Triple.h"
14#include <cassert>
15#include <cstddef>
16
17using namespace lldb_private;
18using namespace lldb;
19
20// src/sys/arch/amd64/include/frame_regs.h
21typedef struct _GPR {
22  uint64_t rdi;    /*  0 */
23  uint64_t rsi;    /*  1 */
24  uint64_t rdx;    /*  2 */
25  uint64_t rcx;    /*  3 */
26  uint64_t r8;     /*  4 */
27  uint64_t r9;     /*  5 */
28  uint64_t r10;    /*  6 */
29  uint64_t r11;    /*  7 */
30  uint64_t r12;    /*  8 */
31  uint64_t r13;    /*  9 */
32  uint64_t r14;    /* 10 */
33  uint64_t r15;    /* 11 */
34  uint64_t rbp;    /* 12 */
35  uint64_t rbx;    /* 13 */
36  uint64_t rax;    /* 14 */
37  uint64_t gs;     /* 15 */
38  uint64_t fs;     /* 16 */
39  uint64_t es;     /* 17 */
40  uint64_t ds;     /* 18 */
41  uint64_t trapno; /* 19 */
42  uint64_t err;    /* 20 */
43  uint64_t rip;    /* 21 */
44  uint64_t cs;     /* 22 */
45  uint64_t rflags; /* 23 */
46  uint64_t rsp;    /* 24 */
47  uint64_t ss;     /* 25 */
48} GPR;
49
50struct DBG {
51  uint64_t dr[16]; /* debug registers */
52                   /* Index 0-3: debug address registers */
53                   /* Index 4-5: reserved */
54                   /* Index 6: debug status */
55                   /* Index 7: debug control */
56                   /* Index 8-15: reserved */
57};
58
59/*
60 * src/sys/arch/amd64/include/mcontext.h
61 *
62 * typedef struct {
63 *       __gregset_t     __gregs;
64 *       __greg_t        _mc_tlsbase;
65 *       __fpregset_t    __fpregs;
66 * } mcontext_t;
67 */
68
69struct UserArea {
70  GPR gpr;
71  uint64_t mc_tlsbase;
72  FPR fpr;
73  DBG dbg;
74};
75
76#define DR_OFFSET(reg_index)                                                   \
77  (LLVM_EXTENSION offsetof(UserArea, dbg) +                                    \
78   LLVM_EXTENSION offsetof(DBG, dr[reg_index]))
79
80
81// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64
82// structure.
83#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
84#include "RegisterInfos_x86_64.h"
85#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
86
87static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
88  static std::vector<lldb_private::RegisterInfo> g_register_infos;
89  return g_register_infos;
90}
91
92static const RegisterInfo *
93GetRegisterInfo_i386(const lldb_private::ArchSpec &arch) {
94  std::vector<lldb_private::RegisterInfo> &g_register_infos =
95      GetPrivateRegisterInfoVector();
96
97  // Allocate RegisterInfo only once
98  if (g_register_infos.empty()) {
99    // Copy the register information from base class
100    std::unique_ptr<RegisterContextNetBSD_i386> reg_interface(
101        new RegisterContextNetBSD_i386(arch));
102    const RegisterInfo *base_info = reg_interface->GetRegisterInfo();
103    g_register_infos.insert(g_register_infos.end(), &base_info[0],
104                            &base_info[k_num_registers_i386]);
105
106// Include RegisterInfos_x86_64 to update the g_register_infos structure
107//  with x86_64 offsets.
108#define UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
109#include "RegisterInfos_x86_64.h"
110#undef UPDATE_REGISTER_INFOS_I386_STRUCT_WITH_X86_64_OFFSETS
111  }
112
113  return &g_register_infos[0];
114}
115
116static const RegisterInfo *
117PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
118  switch (target_arch.GetMachine()) {
119  case llvm::Triple::x86:
120    return GetRegisterInfo_i386(target_arch);
121  case llvm::Triple::x86_64:
122    return g_register_infos_x86_64;
123  default:
124    assert(false && "Unhandled target architecture.");
125    return nullptr;
126  }
127}
128
129static uint32_t
130PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) {
131  switch (target_arch.GetMachine()) {
132  case llvm::Triple::x86: {
133    assert(!GetPrivateRegisterInfoVector().empty() &&
134           "i386 register info not yet filled.");
135    return static_cast<uint32_t>(GetPrivateRegisterInfoVector().size());
136  }
137  case llvm::Triple::x86_64:
138    return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
139                                 sizeof(g_register_infos_x86_64[0]));
140  default:
141    assert(false && "Unhandled target architecture.");
142    return 0;
143  }
144}
145
146static uint32_t
147PrivateGetUserRegisterCount(const lldb_private::ArchSpec &target_arch) {
148  switch (target_arch.GetMachine()) {
149  case llvm::Triple::x86:
150    return static_cast<uint32_t>(k_num_user_registers_i386);
151  case llvm::Triple::x86_64:
152    return static_cast<uint32_t>(k_num_user_registers_x86_64);
153  default:
154    assert(false && "Unhandled target architecture.");
155    return 0;
156  }
157}
158
159RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64(
160    const ArchSpec &target_arch)
161    : lldb_private::RegisterInfoInterface(target_arch),
162      m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)),
163      m_register_count(PrivateGetRegisterCount(target_arch)),
164      m_user_register_count(PrivateGetUserRegisterCount(target_arch)) {}
165
166size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); }
167
168const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const {
169  return m_register_info_p;
170}
171
172uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const {
173  return m_register_count;
174}
175
176uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const {
177  return m_user_register_count;
178}
179