1 /* Native-dependent code for AMD64 BSD's. 2 3 Copyright (C) 2003-2017 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "inferior.h" 22 #include "regcache.h" 23 #include "target.h" 24 25 /* We include <signal.h> to make sure `struct fxsave64' is defined on 26 NetBSD, since NetBSD's <machine/reg.h> needs it. */ 27 #include <signal.h> 28 #include <sys/types.h> 29 #include <sys/ptrace.h> 30 #include <machine/reg.h> 31 32 #include "amd64-tdep.h" 33 #include "amd64-nat.h" 34 #include "x86-bsd-nat.h" 35 #include "inf-ptrace.h" 36 37 38 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 39 for all registers (including the floating-point registers). */ 40 41 static void 42 amd64bsd_fetch_inferior_registers (struct target_ops *ops, 43 struct regcache *regcache, int regnum) 44 { 45 struct gdbarch *gdbarch = get_regcache_arch (regcache); 46 pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); 47 48 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) 49 { 50 struct reg regs; 51 52 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 53 perror_with_name (_("Couldn't get registers")); 54 55 amd64_supply_native_gregset (regcache, ®s, -1); 56 if (regnum != -1) 57 return; 58 } 59 60 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) 61 { 62 struct fpreg fpregs; 63 #ifdef PT_GETXSTATE_INFO 64 void *xstateregs; 65 66 if (x86bsd_xsave_len != 0) 67 { 68 xstateregs = alloca (x86bsd_xsave_len); 69 if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, ptid_get_lwp (inferior_ptid)) 70 == -1) 71 perror_with_name (_("Couldn't get extended state status")); 72 73 amd64_supply_xsave (regcache, -1, xstateregs); 74 return; 75 } 76 #endif 77 78 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 79 perror_with_name (_("Couldn't get floating point status")); 80 81 amd64_supply_fxsave (regcache, -1, &fpregs); 82 } 83 } 84 85 /* Store register REGNUM back into the inferior. If REGNUM is -1, do 86 this for all registers (including the floating-point registers). */ 87 88 static void 89 amd64bsd_store_inferior_registers (struct target_ops *ops, 90 struct regcache *regcache, int regnum) 91 { 92 struct gdbarch *gdbarch = get_regcache_arch (regcache); 93 pid_t pid = get_ptrace_pid (regcache_get_ptid (regcache)); 94 95 if (regnum == -1 || amd64_native_gregset_supplies_p (gdbarch, regnum)) 96 { 97 struct reg regs; 98 99 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 100 perror_with_name (_("Couldn't get registers")); 101 102 amd64_collect_native_gregset (regcache, ®s, regnum); 103 104 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 105 perror_with_name (_("Couldn't write registers")); 106 107 if (regnum != -1) 108 return; 109 } 110 111 if (regnum == -1 || !amd64_native_gregset_supplies_p (gdbarch, regnum)) 112 { 113 struct fpreg fpregs; 114 #ifdef PT_GETXSTATE_INFO 115 void *xstateregs; 116 117 if (x86bsd_xsave_len != 0) 118 { 119 xstateregs = alloca (x86bsd_xsave_len); 120 if (ptrace (PT_GETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, ptid_get_lwp (inferior_ptid)) 121 == -1) 122 perror_with_name (_("Couldn't get extended state status")); 123 124 amd64_collect_xsave (regcache, regnum, xstateregs, ptid_get_lwp (inferior_ptid)); 125 126 if (ptrace (PT_SETXSTATE, pid, (PTRACE_TYPE_ARG3) xstateregs, 127 x86bsd_xsave_len) == -1) 128 perror_with_name (_("Couldn't write extended state status")); 129 return; 130 } 131 #endif 132 133 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 134 perror_with_name (_("Couldn't get floating point status")); 135 136 amd64_collect_fxsave (regcache, regnum, &fpregs); 137 138 if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 139 perror_with_name (_("Couldn't write floating point status")); 140 } 141 } 142 143 /* Create a prototype *BSD/amd64 target. The client can override it 144 with local methods. */ 145 146 struct target_ops * 147 amd64bsd_target (void) 148 { 149 struct target_ops *t; 150 151 t = x86bsd_target (); 152 t->to_fetch_registers = amd64bsd_fetch_inferior_registers; 153 t->to_store_registers = amd64bsd_store_inferior_registers; 154 return t; 155 } 156