1 /* Native-dependent code for OpenBSD/powerpc. 2 3 Copyright (C) 2004, 2005, 2006 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 2 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, write to the Free Software 19 Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 Boston, MA 02110-1301, USA. */ 21 22 #include "defs.h" 23 #include "gdbcore.h" 24 #include "inferior.h" 25 #include "regcache.h" 26 27 #include "gdb_assert.h" 28 #include <stddef.h> 29 #include <sys/types.h> 30 #include <sys/ptrace.h> 31 #include <sys/signal.h> 32 #include <machine/frame.h> 33 #include <machine/pcb.h> 34 #include <machine/reg.h> 35 36 #include "obsd-nat.h" 37 #include "ppc-tdep.h" 38 #include "ppcobsd-tdep.h" 39 #include "inf-ptrace.h" 40 #include "bsd-kvm.h" 41 42 /* OpenBSD/powerpc didn't have PT_GETFPREGS/PT_SETFPREGS until release 43 4.0. On older releases the floating-point registers are handled by 44 PT_GETREGS/PT_SETREGS, but fpscr wasn't available.. */ 45 46 #ifdef PT_GETFPREGS 47 48 /* Returns true if PT_GETFPREGS fetches this register. */ 49 50 static int 51 getfpregs_supplies (int regnum) 52 { 53 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); 54 55 /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating 56 point registers. Traditionally, GDB's register set has still 57 listed the floating point registers for such machines, so this 58 code is harmless. However, the new E500 port actually omits the 59 floating point registers entirely from the register set --- they 60 don't even have register numbers assigned to them. 61 62 It's not clear to me how best to update this code, so this assert 63 will alert the first person to encounter the NetBSD/E500 64 combination to the problem. */ 65 gdb_assert (ppc_floating_point_unit_p (current_gdbarch)); 66 67 return ((regnum >= tdep->ppc_fp0_regnum 68 && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs) 69 || regnum == tdep->ppc_fpscr_regnum); 70 } 71 72 #endif /* PT_GETFPREGS */ 73 74 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 75 for all registers. */ 76 77 static void 78 ppcobsd_fetch_registers (int regnum) 79 { 80 struct reg regs; 81 int pid; 82 83 /* Cater for systems like OpenBSD, that implement threads as 84 separate processes. */ 85 pid = ptid_get_lwp (inferior_ptid); 86 if (pid == 0) 87 pid = ptid_get_pid (inferior_ptid); 88 89 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 90 perror_with_name (_("Couldn't get registers")); 91 92 ppc_supply_gregset (&ppcobsd_gregset, current_regcache, -1, 93 ®s, sizeof regs); 94 #ifndef PT_GETFPREGS 95 ppc_supply_fpregset (&ppcobsd_gregset, current_regcache, -1, 96 ®s, sizeof regs); 97 #endif 98 99 #ifdef PT_GETFPREGS 100 if (regnum == -1 || getfpregs_supplies (regnum)) 101 { 102 struct fpreg fpregs; 103 104 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 105 perror_with_name (_("Couldn't get floating point status")); 106 107 ppc_supply_fpregset (&ppcobsd_fpregset, current_regcache, -1, 108 &fpregs, sizeof fpregs); 109 } 110 #endif 111 } 112 113 /* Store register REGNUM back into the inferior. If REGNUM is -1, do 114 this for all registers. */ 115 116 static void 117 ppcobsd_store_registers (int regnum) 118 { 119 struct reg regs; 120 int pid; 121 122 /* Cater for systems like OpenBSD, that implement threads as 123 separate processes. */ 124 pid = ptid_get_lwp (inferior_ptid); 125 if (pid == 0) 126 pid = ptid_get_pid (inferior_ptid); 127 128 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 129 perror_with_name (_("Couldn't get registers")); 130 131 ppc_collect_gregset (&ppcobsd_gregset, current_regcache, 132 regnum, ®s, sizeof regs); 133 #ifndef PT_GETFPREGS 134 ppc_collect_fpregset (&ppcobsd_gregset, current_regcache, 135 regnum, ®s, sizeof regs); 136 #endif 137 138 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 139 perror_with_name (_("Couldn't write registers")); 140 141 #ifdef PT_GETFPREGS 142 if (regnum == -1 || getfpregs_supplies (regnum)) 143 { 144 struct fpreg fpregs; 145 146 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 147 perror_with_name (_("Couldn't get floating point status")); 148 149 ppc_collect_fpregset (&ppcobsd_fpregset, current_regcache, 150 regnum, &fpregs, sizeof fpregs); 151 152 if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 153 perror_with_name (_("Couldn't write floating point status")); 154 } 155 #endif 156 } 157 158 159 static int 160 ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) 161 { 162 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache)); 163 struct switchframe sf; 164 struct callframe cf; 165 int i, regnum; 166 167 /* The following is true for OpenBSD 3.7: 168 169 The pcb contains %r1 (the stack pointer) at the point of the 170 context switch in cpu_switch(). At that point we have a stack 171 frame as described by `struct switchframe', and below that a call 172 frame as described by `struct callframe'. From this information 173 we reconstruct the register state as it would look when we are in 174 cpu_switch(). */ 175 176 /* The stack pointer shouldn't be zero. */ 177 if (pcb->pcb_sp == 0) 178 return 0; 179 180 read_memory (pcb->pcb_sp, (char *)&sf, sizeof sf); 181 regcache_raw_supply (regcache, tdep->ppc_cr_regnum, &sf.cr); 182 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 2, &sf.fixreg2); 183 for (i = 0, regnum = tdep->ppc_gp0_regnum + 13; i < 19; i++, regnum++) 184 regcache_raw_supply (regcache, regnum, &sf.fixreg[i]); 185 186 read_memory (sf.sp, (char *)&cf, sizeof cf); 187 regcache_raw_supply (regcache, SP_REGNUM, &cf.sp); 188 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 30, &cf.r30); 189 regcache_raw_supply (regcache, tdep->ppc_gp0_regnum + 31, &cf.r31); 190 191 read_memory (cf.sp, (char *)&cf, sizeof cf); 192 regcache_raw_supply (regcache, PC_REGNUM, &cf.lr); 193 194 return 1; 195 } 196 197 198 /* Provide a prototype to silence -Wmissing-prototypes. */ 199 void _initialize_ppcobsd_nat (void); 200 201 void 202 _initialize_ppcobsd_nat (void) 203 { 204 struct target_ops *t; 205 206 /* Add in local overrides. */ 207 t = inf_ptrace_target (); 208 t->to_fetch_registers = ppcobsd_fetch_registers; 209 t->to_store_registers = ppcobsd_store_registers; 210 t->to_pid_to_str = obsd_pid_to_str; 211 t->to_find_new_threads = obsd_find_new_threads; 212 t->to_wait = obsd_wait; 213 add_target (t); 214 215 /* General-purpose registers. */ 216 ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr); 217 ppcobsd_reg_offsets.pc_offset = offsetof (struct reg, pc); 218 ppcobsd_reg_offsets.ps_offset = offsetof (struct reg, ps); 219 ppcobsd_reg_offsets.cr_offset = offsetof (struct reg, cnd); 220 ppcobsd_reg_offsets.lr_offset = offsetof (struct reg, lr); 221 ppcobsd_reg_offsets.ctr_offset = offsetof (struct reg, cnt); 222 ppcobsd_reg_offsets.xer_offset = offsetof (struct reg, xer); 223 ppcobsd_reg_offsets.mq_offset = offsetof (struct reg, mq); 224 225 /* Floating-point registers. */ 226 ppcobsd_reg_offsets.f0_offset = offsetof (struct reg, fpr); 227 ppcobsd_reg_offsets.fpscr_offset = -1; 228 #ifdef PT_GETFPREGS 229 ppcobsd_fpreg_offsets.f0_offset = offsetof (struct fpreg, fpr); 230 ppcobsd_fpreg_offsets.fpscr_offset = offsetof (struct fpreg, fpscr); 231 #endif 232 233 /* AltiVec registers. */ 234 ppcobsd_reg_offsets.vr0_offset = offsetof (struct vreg, vreg); 235 ppcobsd_reg_offsets.vscr_offset = offsetof (struct vreg, vscr); 236 ppcobsd_reg_offsets.vrsave_offset = offsetof (struct vreg, vrsave); 237 238 /* Support debugging kernel virtual memory images. */ 239 bsd_kvm_add_target (ppcobsd_supply_pcb); 240 } 241