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 
17 using namespace lldb_private;
18 using namespace lldb;
19 
20 // src/sys/arch/amd64/include/frame_regs.h
21 typedef 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 
50 struct 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 
69 struct 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 
GetPrivateRegisterInfoVector()87 static std::vector<lldb_private::RegisterInfo> &GetPrivateRegisterInfoVector() {
88   static std::vector<lldb_private::RegisterInfo> g_register_infos;
89   return g_register_infos;
90 }
91 
92 static const RegisterInfo *
GetRegisterInfo_i386(const lldb_private::ArchSpec & arch)93 GetRegisterInfo_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 
116 static const RegisterInfo *
PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec & target_arch)117 PrivateGetRegisterInfoPtr(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 
129 static uint32_t
PrivateGetRegisterCount(const lldb_private::ArchSpec & target_arch)130 PrivateGetRegisterCount(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 
146 static uint32_t
PrivateGetUserRegisterCount(const lldb_private::ArchSpec & target_arch)147 PrivateGetUserRegisterCount(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 
RegisterContextNetBSD_x86_64(const ArchSpec & target_arch)159 RegisterContextNetBSD_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 
GetGPRSize() const166 size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); }
167 
GetRegisterInfo() const168 const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const {
169   return m_register_info_p;
170 }
171 
GetRegisterCount() const172 uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const {
173   return m_register_count;
174 }
175 
GetUserRegisterCount() const176 uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const {
177   return m_user_register_count;
178 }
179