1 /* Native-dependent code for Alpha BSD's. 2 3 Copyright (C) 2000-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 24 #include "alpha-tdep.h" 25 #include "alpha-bsd-tdep.h" 26 #include "inf-ptrace.h" 27 28 #ifdef __NetBSD__ 29 #include "nbsd-nat.h" 30 #endif 31 32 #include <sys/types.h> 33 #include <sys/ptrace.h> 34 #include <machine/reg.h> 35 36 #ifdef HAVE_SYS_PROCFS_H 37 #include <sys/procfs.h> 38 #endif 39 40 #ifndef HAVE_GREGSET_T 41 typedef struct reg gregset_t; 42 #endif 43 44 #ifndef HAVE_FPREGSET_T 45 typedef struct fpreg fpregset_t; 46 #endif 47 48 #include "gregset.h" 49 50 /* Provide *regset() wrappers around the generic Alpha BSD register 51 supply/fill routines. */ 52 53 void 54 supply_gregset (struct regcache *regcache, const gregset_t *gregsetp) 55 { 56 alphabsd_supply_reg (regcache, (const char *) gregsetp, -1); 57 } 58 59 void 60 fill_gregset (const struct regcache *regcache, gregset_t *gregsetp, int regno) 61 { 62 alphabsd_fill_reg (regcache, (char *) gregsetp, regno); 63 } 64 65 void 66 supply_fpregset (struct regcache *regcache, const fpregset_t *fpregsetp) 67 { 68 alphabsd_supply_fpreg (regcache, (const char *) fpregsetp, -1); 69 } 70 71 void 72 fill_fpregset (const struct regcache *regcache, 73 fpregset_t *fpregsetp, int regno) 74 { 75 alphabsd_fill_fpreg (regcache, (char *) fpregsetp, regno); 76 } 77 78 /* Determine if PT_GETREGS fetches this register. */ 79 80 static int 81 getregs_supplies (int regno) 82 { 83 return ((regno >= ALPHA_V0_REGNUM && regno <= ALPHA_ZERO_REGNUM) 84 || regno >= ALPHA_PC_REGNUM); 85 } 86 87 /* Fetch register REGNO from the inferior. If REGNO is -1, do this 88 for all registers (including the floating point registers). */ 89 90 static void 91 alphabsd_fetch_inferior_registers (struct target_ops *ops, 92 struct regcache *regcache, int regno) 93 { 94 if (regno == -1 || getregs_supplies (regno)) 95 { 96 struct reg gregs; 97 98 if (ptrace (PT_GETREGS, ptid_get_pid (regcache_get_ptid (regcache)), 99 (PTRACE_TYPE_ARG3) &gregs, ptid_get_lwp (inferior_ptid)) == -1) 100 perror_with_name (_("Couldn't get registers")); 101 102 alphabsd_supply_reg (regcache, (char *) &gregs, regno); 103 if (regno != -1) 104 return; 105 } 106 107 if (regno == -1 108 || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) 109 { 110 struct fpreg fpregs; 111 112 if (ptrace (PT_GETFPREGS, ptid_get_pid (regcache_get_ptid (regcache)), 113 (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 114 perror_with_name (_("Couldn't get floating point status")); 115 116 alphabsd_supply_fpreg (regcache, (char *) &fpregs, regno); 117 } 118 } 119 120 /* Store register REGNO back into the inferior. If REGNO is -1, do 121 this for all registers (including the floating point registers). */ 122 123 static void 124 alphabsd_store_inferior_registers (struct target_ops *ops, 125 struct regcache *regcache, int regno) 126 { 127 if (regno == -1 || getregs_supplies (regno)) 128 { 129 struct reg gregs; 130 if (ptrace (PT_GETREGS, ptid_get_pid (regcache_get_ptid (regcache)), 131 (PTRACE_TYPE_ARG3) &gregs, ptid_get_lwp (inferior_ptid)) == -1) 132 perror_with_name (_("Couldn't get registers")); 133 134 alphabsd_fill_reg (regcache, (char *) &gregs, regno); 135 136 if (ptrace (PT_SETREGS, ptid_get_pid (regcache_get_ptid (regcache)), 137 (PTRACE_TYPE_ARG3) &gregs, ptid_get_lwp (inferior_ptid)) == -1) 138 perror_with_name (_("Couldn't write registers")); 139 140 if (regno != -1) 141 return; 142 } 143 144 if (regno == -1 145 || regno >= gdbarch_fp0_regnum (get_regcache_arch (regcache))) 146 { 147 struct fpreg fpregs; 148 149 if (ptrace (PT_GETFPREGS, ptid_get_pid (regcache_get_ptid (regcache)), 150 (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 151 perror_with_name (_("Couldn't get floating point status")); 152 153 alphabsd_fill_fpreg (regcache, (char *) &fpregs, regno); 154 155 if (ptrace (PT_SETFPREGS, ptid_get_pid (regcache_get_ptid (regcache)), 156 (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 157 perror_with_name (_("Couldn't write floating point status")); 158 } 159 } 160 161 162 /* Support for debugging kernel virtual memory images. */ 163 164 #include <sys/signal.h> 165 #include <machine/pcb.h> 166 167 #include "bsd-kvm.h" 168 169 static int 170 alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) 171 { 172 int regnum; 173 174 /* The following is true for OpenBSD 3.9: 175 176 The pcb contains the register state at the context switch inside 177 cpu_switch(). */ 178 179 /* The stack pointer shouldn't be zero. */ 180 if (pcb->pcb_hw.apcb_ksp == 0) 181 return 0; 182 183 regcache_raw_supply (regcache, ALPHA_SP_REGNUM, &pcb->pcb_hw.apcb_ksp); 184 185 for (regnum = ALPHA_S0_REGNUM; regnum < ALPHA_A0_REGNUM; regnum++) 186 regcache_raw_supply (regcache, regnum, 187 &pcb->pcb_context[regnum - ALPHA_S0_REGNUM]); 188 regcache_raw_supply (regcache, ALPHA_RA_REGNUM, &pcb->pcb_context[7]); 189 190 return 1; 191 } 192 193 struct target_ops * 194 alphabsd_target (void) 195 { 196 struct target_ops *t; 197 198 t = inf_ptrace_target (); 199 t->to_fetch_registers = alphabsd_fetch_inferior_registers; 200 t->to_store_registers = alphabsd_store_inferior_registers; 201 202 return t; 203 } 204 205 206 207 /* Provide a prototype to silence -Wmissing-prototypes. */ 208 void _initialize_alphabsd_nat (void); 209 210 void 211 _initialize_alphabsd_nat (void) 212 { 213 struct target_ops *t; 214 215 t = alphabsd_target (); 216 #ifndef __NetBSD__ 217 add_target (t); 218 #else 219 nbsd_nat_add_target (t); 220 #endif 221 222 /* Support debugging kernel virtual memory images. */ 223 bsd_kvm_add_target (alphabsd_supply_pcb); 224 } 225