1 //===-- RegisterContextNetBSD_x86_64.cpp ----------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===---------------------------------------------------------------------===// 9 10 #include <cstddef> 11 #include <vector> 12 13 #include "llvm/Support/Compiler.h" 14 15 #include "RegisterContextNetBSD_x86_64.h" 16 #include "RegisterContextPOSIX_x86.h" 17 18 using namespace lldb_private; 19 using namespace lldb; 20 21 // src/sys/arch/amd64/include/frame_regs.h 22 typedef struct _GPR { 23 uint64_t rdi; /* 0 */ 24 uint64_t rsi; /* 1 */ 25 uint64_t rdx; /* 2 */ 26 uint64_t rcx; /* 3 */ 27 uint64_t r8; /* 4 */ 28 uint64_t r9; /* 5 */ 29 uint64_t r10; /* 6 */ 30 uint64_t r11; /* 7 */ 31 uint64_t r12; /* 8 */ 32 uint64_t r13; /* 9 */ 33 uint64_t r14; /* 10 */ 34 uint64_t r15; /* 11 */ 35 uint64_t rbp; /* 12 */ 36 uint64_t rbx; /* 13 */ 37 uint64_t rax; /* 14 */ 38 uint64_t gs; /* 15 */ 39 uint64_t fs; /* 16 */ 40 uint64_t es; /* 17 */ 41 uint64_t ds; /* 18 */ 42 uint64_t trapno; /* 19 */ 43 uint64_t err; /* 20 */ 44 uint64_t rip; /* 21 */ 45 uint64_t cs; /* 22 */ 46 uint64_t rflags; /* 23 */ 47 uint64_t rsp; /* 24 */ 48 uint64_t ss; /* 25 */ 49 } GPR; 50 51 /* 52 * As of NetBSD-7.99.25 there is no support for debug registers 53 * https://en.wikipedia.org/wiki/X86_debug_register 54 */ 55 56 /* 57 * src/sys/arch/amd64/include/mcontext.h 58 * 59 * typedef struct { 60 * __gregset_t __gregs; 61 * __greg_t _mc_tlsbase; 62 * __fpregset_t __fpregs; 63 * } mcontext_t; 64 */ 65 66 struct UserArea { 67 GPR gpr; 68 uint64_t mc_tlsbase; 69 FPR fpr; 70 }; 71 72 //--------------------------------------------------------------------------- 73 // Cherry-pick parts of RegisterInfos_x86_64.h, without debug registers 74 //--------------------------------------------------------------------------- 75 // Computes the offset of the given GPR in the user data area. 76 #define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname)) 77 78 // Computes the offset of the given FPR in the extended data area. 79 #define FPR_OFFSET(regname) \ 80 (LLVM_EXTENSION offsetof(UserArea, fpr) + \ 81 LLVM_EXTENSION offsetof(FPR, xstate) + \ 82 LLVM_EXTENSION offsetof(FXSAVE, regname)) 83 84 // Computes the offset of the YMM register assembled from register halves. 85 // Based on DNBArchImplX86_64.cpp from debugserver 86 #define YMM_OFFSET(reg_index) \ 87 (LLVM_EXTENSION offsetof(UserArea, fpr) + \ 88 LLVM_EXTENSION offsetof(FPR, xstate) + \ 89 LLVM_EXTENSION offsetof(XSAVE, ymmh[0]) + (32 * reg_index)) 90 91 // Number of bytes needed to represent a FPR. 92 #define FPR_SIZE(reg) sizeof(((FXSAVE *)NULL)->reg) 93 94 // Number of bytes needed to represent the i'th FP register. 95 #define FP_SIZE sizeof(((MMSReg *)NULL)->bytes) 96 97 // Number of bytes needed to represent an XMM register. 98 #define XMM_SIZE sizeof(XMMReg) 99 100 // Number of bytes needed to represent a YMM register. 101 #define YMM_SIZE sizeof(YMMReg) 102 103 // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB 104 105 // Note that the size and offset will be updated by platform-specific classes. 106 #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \ 107 { \ 108 #reg, alt, sizeof(((GPR *) NULL)->reg), \ 109 GPR_OFFSET(reg), eEncodingUint, eFormatHex, \ 110 {kind1, kind2, kind3, kind4, \ 111 lldb_##reg##_x86_64 }, \ 112 NULL, NULL \ 113 } 114 115 #define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4) \ 116 { \ 117 #name, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \ 118 {kind1, kind2, kind3, kind4, \ 119 lldb_##name##_x86_64 }, \ 120 NULL, NULL \ 121 } 122 123 #define DEFINE_FP_ST(reg, i) \ 124 { \ 125 #reg #i, NULL, FP_SIZE, \ 126 LLVM_EXTENSION FPR_OFFSET( \ 127 stmm[i]), eEncodingVector, eFormatVectorOfUInt8, \ 128 {dwarf_st##i##_x86_64, dwarf_st##i##_x86_64, LLDB_INVALID_REGNUM, \ 129 LLDB_INVALID_REGNUM, lldb_st##i##_x86_64 }, \ 130 NULL, NULL \ 131 } 132 133 #define DEFINE_FP_MM(reg, i) \ 134 { \ 135 #reg #i, NULL, sizeof(uint64_t), \ 136 LLVM_EXTENSION FPR_OFFSET( \ 137 stmm[i]), eEncodingUint, eFormatHex, \ 138 {dwarf_mm##i##_x86_64, dwarf_mm##i##_x86_64, \ 139 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 140 lldb_mm##i##_x86_64 }, \ 141 NULL, NULL \ 142 } 143 144 #define DEFINE_XMM(reg, i) \ 145 { \ 146 #reg #i, NULL, XMM_SIZE, \ 147 LLVM_EXTENSION FPR_OFFSET( \ 148 reg[i]), eEncodingVector, eFormatVectorOfUInt8, \ 149 {dwarf_##reg##i##_x86_64, dwarf_##reg##i##_x86_64, \ 150 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 151 lldb_##reg##i##_x86_64 }, \ 152 NULL, NULL \ 153 } 154 155 #define DEFINE_YMM(reg, i) \ 156 { \ 157 #reg #i, NULL, YMM_SIZE, \ 158 LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8, \ 159 {dwarf_##reg##i##h_x86_64, \ 160 dwarf_##reg##i##h_x86_64, \ 161 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 162 lldb_##reg##i##_x86_64 }, \ 163 NULL, NULL \ 164 } 165 166 #define DEFINE_GPR_PSEUDO_32(reg32, reg64) \ 167 { \ 168 #reg32, NULL, 4, \ 169 GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ 170 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 171 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 172 lldb_##reg32##_x86_64 }, \ 173 RegisterContextPOSIX_x86::g_contained_##reg64, \ 174 RegisterContextPOSIX_x86::g_invalidate_##reg64 \ 175 } 176 #define DEFINE_GPR_PSEUDO_16(reg16, reg64) \ 177 { \ 178 #reg16, NULL, 2, \ 179 GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ 180 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 181 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 182 lldb_##reg16##_x86_64 }, \ 183 RegisterContextPOSIX_x86::g_contained_##reg64, \ 184 RegisterContextPOSIX_x86::g_invalidate_##reg64 \ 185 } 186 #define DEFINE_GPR_PSEUDO_8H(reg8, reg64) \ 187 { \ 188 #reg8, NULL, 1, GPR_OFFSET(reg64) + 1, eEncodingUint, eFormatHex, \ 189 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 190 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 191 lldb_##reg8##_x86_64 }, \ 192 RegisterContextPOSIX_x86::g_contained_##reg64, \ 193 RegisterContextPOSIX_x86::g_invalidate_##reg64 \ 194 } 195 #define DEFINE_GPR_PSEUDO_8L(reg8, reg64) \ 196 { \ 197 #reg8, NULL, 1, GPR_OFFSET(reg64), eEncodingUint, eFormatHex, \ 198 {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 199 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \ 200 lldb_##reg8##_x86_64 }, \ 201 RegisterContextPOSIX_x86::g_contained_##reg64, \ 202 RegisterContextPOSIX_x86::g_invalidate_##reg64 \ 203 } 204 205 static RegisterInfo g_register_infos_x86_64[] = { 206 // General purpose registers. EH_Frame, DWARF, 207 // Generic, Process Plugin 208 DEFINE_GPR(rax, nullptr, dwarf_rax_x86_64, dwarf_rax_x86_64, 209 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 210 DEFINE_GPR(rbx, nullptr, dwarf_rbx_x86_64, dwarf_rbx_x86_64, 211 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 212 DEFINE_GPR(rcx, "arg4", dwarf_rcx_x86_64, dwarf_rcx_x86_64, 213 LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM), 214 DEFINE_GPR(rdx, "arg3", dwarf_rdx_x86_64, dwarf_rdx_x86_64, 215 LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM), 216 DEFINE_GPR(rdi, "arg1", dwarf_rdi_x86_64, dwarf_rdi_x86_64, 217 LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM), 218 DEFINE_GPR(rsi, "arg2", dwarf_rsi_x86_64, dwarf_rsi_x86_64, 219 LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM), 220 DEFINE_GPR(rbp, "fp", dwarf_rbp_x86_64, dwarf_rbp_x86_64, 221 LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM), 222 DEFINE_GPR(rsp, "sp", dwarf_rsp_x86_64, dwarf_rsp_x86_64, 223 LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM), 224 DEFINE_GPR(r8, "arg5", dwarf_r8_x86_64, dwarf_r8_x86_64, 225 LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM), 226 DEFINE_GPR(r9, "arg6", dwarf_r9_x86_64, dwarf_r9_x86_64, 227 LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM), 228 DEFINE_GPR(r10, nullptr, dwarf_r10_x86_64, dwarf_r10_x86_64, 229 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 230 DEFINE_GPR(r11, nullptr, dwarf_r11_x86_64, dwarf_r11_x86_64, 231 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 232 DEFINE_GPR(r12, nullptr, dwarf_r12_x86_64, dwarf_r12_x86_64, 233 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 234 DEFINE_GPR(r13, nullptr, dwarf_r13_x86_64, dwarf_r13_x86_64, 235 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 236 DEFINE_GPR(r14, nullptr, dwarf_r14_x86_64, dwarf_r14_x86_64, 237 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 238 DEFINE_GPR(r15, nullptr, dwarf_r15_x86_64, dwarf_r15_x86_64, 239 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 240 DEFINE_GPR(rip, "pc", dwarf_rip_x86_64, dwarf_rip_x86_64, 241 LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM), 242 DEFINE_GPR(rflags, "flags", dwarf_rflags_x86_64, dwarf_rflags_x86_64, 243 LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM), 244 DEFINE_GPR(cs, nullptr, dwarf_cs_x86_64, dwarf_cs_x86_64, 245 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 246 DEFINE_GPR(fs, nullptr, dwarf_fs_x86_64, dwarf_fs_x86_64, 247 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 248 DEFINE_GPR(gs, nullptr, dwarf_gs_x86_64, dwarf_gs_x86_64, 249 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 250 DEFINE_GPR(ss, nullptr, dwarf_ss_x86_64, dwarf_ss_x86_64, 251 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 252 DEFINE_GPR(ds, nullptr, dwarf_ds_x86_64, dwarf_ds_x86_64, 253 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 254 DEFINE_GPR(es, nullptr, dwarf_es_x86_64, dwarf_es_x86_64, 255 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 256 257 DEFINE_GPR_PSEUDO_32(eax, rax), DEFINE_GPR_PSEUDO_32(ebx, rbx), 258 DEFINE_GPR_PSEUDO_32(ecx, rcx), DEFINE_GPR_PSEUDO_32(edx, rdx), 259 DEFINE_GPR_PSEUDO_32(edi, rdi), DEFINE_GPR_PSEUDO_32(esi, rsi), 260 DEFINE_GPR_PSEUDO_32(ebp, rbp), DEFINE_GPR_PSEUDO_32(esp, rsp), 261 DEFINE_GPR_PSEUDO_32(r8d, r8), DEFINE_GPR_PSEUDO_32(r9d, r9), 262 DEFINE_GPR_PSEUDO_32(r10d, r10), DEFINE_GPR_PSEUDO_32(r11d, r11), 263 DEFINE_GPR_PSEUDO_32(r12d, r12), DEFINE_GPR_PSEUDO_32(r13d, r13), 264 DEFINE_GPR_PSEUDO_32(r14d, r14), DEFINE_GPR_PSEUDO_32(r15d, r15), 265 DEFINE_GPR_PSEUDO_16(ax, rax), DEFINE_GPR_PSEUDO_16(bx, rbx), 266 DEFINE_GPR_PSEUDO_16(cx, rcx), DEFINE_GPR_PSEUDO_16(dx, rdx), 267 DEFINE_GPR_PSEUDO_16(di, rdi), DEFINE_GPR_PSEUDO_16(si, rsi), 268 DEFINE_GPR_PSEUDO_16(bp, rbp), DEFINE_GPR_PSEUDO_16(sp, rsp), 269 DEFINE_GPR_PSEUDO_16(r8w, r8), DEFINE_GPR_PSEUDO_16(r9w, r9), 270 DEFINE_GPR_PSEUDO_16(r10w, r10), DEFINE_GPR_PSEUDO_16(r11w, r11), 271 DEFINE_GPR_PSEUDO_16(r12w, r12), DEFINE_GPR_PSEUDO_16(r13w, r13), 272 DEFINE_GPR_PSEUDO_16(r14w, r14), DEFINE_GPR_PSEUDO_16(r15w, r15), 273 DEFINE_GPR_PSEUDO_8H(ah, rax), DEFINE_GPR_PSEUDO_8H(bh, rbx), 274 DEFINE_GPR_PSEUDO_8H(ch, rcx), DEFINE_GPR_PSEUDO_8H(dh, rdx), 275 DEFINE_GPR_PSEUDO_8L(al, rax), DEFINE_GPR_PSEUDO_8L(bl, rbx), 276 DEFINE_GPR_PSEUDO_8L(cl, rcx), DEFINE_GPR_PSEUDO_8L(dl, rdx), 277 DEFINE_GPR_PSEUDO_8L(dil, rdi), DEFINE_GPR_PSEUDO_8L(sil, rsi), 278 DEFINE_GPR_PSEUDO_8L(bpl, rbp), DEFINE_GPR_PSEUDO_8L(spl, rsp), 279 DEFINE_GPR_PSEUDO_8L(r8l, r8), DEFINE_GPR_PSEUDO_8L(r9l, r9), 280 DEFINE_GPR_PSEUDO_8L(r10l, r10), DEFINE_GPR_PSEUDO_8L(r11l, r11), 281 DEFINE_GPR_PSEUDO_8L(r12l, r12), DEFINE_GPR_PSEUDO_8L(r13l, r13), 282 DEFINE_GPR_PSEUDO_8L(r14l, r14), DEFINE_GPR_PSEUDO_8L(r15l, r15), 283 284 // i387 Floating point registers. EH_frame, 285 // DWARF, Generic, Process Plugin 286 DEFINE_FPR(fctrl, fctrl, dwarf_fctrl_x86_64, dwarf_fctrl_x86_64, 287 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 288 DEFINE_FPR(fstat, fstat, dwarf_fstat_x86_64, dwarf_fstat_x86_64, 289 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 290 DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 291 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 292 DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 293 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 294 DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 295 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 296 DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 297 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 298 DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 299 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 300 DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 301 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 302 DEFINE_FPR(mxcsr, mxcsr, dwarf_mxcsr_x86_64, dwarf_mxcsr_x86_64, 303 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 304 DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 305 LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM), 306 307 // FP registers. 308 DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2), 309 DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5), 310 DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7), DEFINE_FP_MM(mm, 0), 311 DEFINE_FP_MM(mm, 1), DEFINE_FP_MM(mm, 2), DEFINE_FP_MM(mm, 3), 312 DEFINE_FP_MM(mm, 4), DEFINE_FP_MM(mm, 5), DEFINE_FP_MM(mm, 6), 313 DEFINE_FP_MM(mm, 7), 314 315 // XMM registers 316 DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2), 317 DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5), 318 DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7), DEFINE_XMM(xmm, 8), 319 DEFINE_XMM(xmm, 9), DEFINE_XMM(xmm, 10), DEFINE_XMM(xmm, 11), 320 DEFINE_XMM(xmm, 12), DEFINE_XMM(xmm, 13), DEFINE_XMM(xmm, 14), 321 DEFINE_XMM(xmm, 15), 322 323 // Copy of YMM registers assembled from xmm and ymmh 324 DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2), 325 DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5), 326 DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7), DEFINE_YMM(ymm, 8), 327 DEFINE_YMM(ymm, 9), DEFINE_YMM(ymm, 10), DEFINE_YMM(ymm, 11), 328 DEFINE_YMM(ymm, 12), DEFINE_YMM(ymm, 13), DEFINE_YMM(ymm, 14), 329 DEFINE_YMM(ymm, 15), 330 }; 331 332 //--------------------------------------------------------------------------- 333 // End of cherry-pick of RegisterInfos_x86_64.h 334 //--------------------------------------------------------------------------- 335 336 static const RegisterInfo * 337 PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) { 338 switch (target_arch.GetMachine()) { 339 case llvm::Triple::x86_64: 340 return g_register_infos_x86_64; 341 default: 342 assert(false && "Unhandled target architecture."); 343 return nullptr; 344 } 345 } 346 347 static uint32_t 348 PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) { 349 switch (target_arch.GetMachine()) { 350 case llvm::Triple::x86_64: 351 return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) / 352 sizeof(g_register_infos_x86_64[0])); 353 default: 354 assert(false && "Unhandled target architecture."); 355 return 0; 356 } 357 } 358 359 RegisterContextNetBSD_x86_64::RegisterContextNetBSD_x86_64( 360 const ArchSpec &target_arch) 361 : lldb_private::RegisterInfoInterface(target_arch), 362 m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)), 363 m_register_count(PrivateGetRegisterCount(target_arch)) {} 364 365 size_t RegisterContextNetBSD_x86_64::GetGPRSize() const { return sizeof(GPR); } 366 367 const RegisterInfo *RegisterContextNetBSD_x86_64::GetRegisterInfo() const { 368 return m_register_info_p; 369 } 370 371 uint32_t RegisterContextNetBSD_x86_64::GetRegisterCount() const { 372 return m_register_count; 373 } 374