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/ADT/Triple.h" 13 #include "llvm/Support/Compiler.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 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 * 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 * 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 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 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 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 166 size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } 167 168 const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const { 169 return m_register_info_p; 170 } 171 172 uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { 173 return m_register_count; 174 } 175 176 uint32_t RegisterContextNetBSD_x86_64::GetUserRegisterCount() const { 177 return m_user_register_count; 178 } 179