1 /* Native-dependent code for Motorola 68000 BSD's. 2 3 Copyright (C) 2004-2019 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 "gdbcore.h" 22 #include "inferior.h" 23 #include "regcache.h" 24 25 #include <sys/types.h> 26 #include <sys/ptrace.h> 27 #include <machine/reg.h> 28 29 #include "m68k-tdep.h" 30 #include "inf-ptrace.h" 31 32 #ifdef __NetBSD__ 33 #include "nbsd-nat.h" 34 struct m68k_bsd_nat_target final : public nbsd_nat_target 35 #else 36 struct m68k_bsd_nat_target final : public inf_ptrace_target 37 #endif 38 { 39 void fetch_registers (struct regcache *, int) override; 40 void store_registers (struct regcache *, int) override; 41 }; 42 43 static m68k_bsd_nat_target the_m68k_bsd_nat_target; 44 45 static int 46 m68kbsd_gregset_supplies_p (int regnum) 47 { 48 return (regnum >= M68K_D0_REGNUM && regnum <= M68K_PC_REGNUM); 49 } 50 51 static int 52 m68kbsd_fpregset_supplies_p (int regnum) 53 { 54 return (regnum >= M68K_FP0_REGNUM && regnum <= M68K_FPI_REGNUM); 55 } 56 57 /* Supply the general-purpose registers stored in GREGS to REGCACHE. */ 58 59 static void 60 m68kbsd_supply_gregset (struct regcache *regcache, const void *gregs) 61 { 62 const gdb_byte *regs = (const gdb_byte *)gregs; 63 int regnum; 64 65 for (regnum = M68K_D0_REGNUM; regnum <= M68K_PC_REGNUM; regnum++) 66 regcache->raw_supply (regnum, regs + regnum * 4); 67 } 68 69 /* Supply the floating-point registers stored in FPREGS to REGCACHE. */ 70 71 static void 72 m68kbsd_supply_fpregset (struct regcache *regcache, const void *fpregs) 73 { 74 struct gdbarch *gdbarch = regcache->arch (); 75 const gdb_byte *regs = (const gdb_byte *)fpregs; 76 int regnum; 77 78 for (regnum = M68K_FP0_REGNUM; regnum <= M68K_FPI_REGNUM; regnum++) 79 regcache->raw_supply (regnum, 80 regs + m68kbsd_fpreg_offset (gdbarch, regnum)); 81 } 82 83 /* Collect the general-purpose registers from REGCACHE and store them 84 in GREGS. */ 85 86 static void 87 m68kbsd_collect_gregset (const struct regcache *regcache, 88 void *gregs, int regnum) 89 { 90 gdb_byte *regs = (gdb_byte *)gregs; 91 int i; 92 93 for (i = M68K_D0_REGNUM; i <= M68K_PC_REGNUM; i++) 94 { 95 if (regnum == -1 || regnum == i) 96 regcache->raw_collect (i, regs + i * 4); 97 } 98 } 99 100 /* Collect the floating-point registers from REGCACHE and store them 101 in FPREGS. */ 102 103 static void 104 m68kbsd_collect_fpregset (struct regcache *regcache, 105 void *fpregs, int regnum) 106 { 107 struct gdbarch *gdbarch = regcache->arch (); 108 gdb_byte *regs = (gdb_byte *)fpregs; 109 int i; 110 111 for (i = M68K_FP0_REGNUM; i <= M68K_FPI_REGNUM; i++) 112 { 113 if (regnum == -1 || regnum == i) 114 regcache->raw_collect (i, regs + m68kbsd_fpreg_offset (gdbarch, i)); 115 } 116 } 117 118 119 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 120 for all registers (including the floating-point registers). */ 121 122 void 123 m68k_bsd_nat_target::fetch_registers (struct regcache *regcache, int regnum) 124 { 125 pid_t pid = regcache->ptid ().pid (); 126 127 if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) 128 { 129 struct reg regs; 130 131 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, inferior_ptid.lwp ()) == -1) 132 perror_with_name (_("Couldn't get registers")); 133 134 m68kbsd_supply_gregset (regcache, ®s); 135 } 136 137 if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) 138 { 139 struct fpreg fpregs; 140 141 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, inferior_ptid.lwp ()) == -1) 142 perror_with_name (_("Couldn't get floating point status")); 143 144 m68kbsd_supply_fpregset (regcache, &fpregs); 145 } 146 } 147 148 /* Store register REGNUM back into the inferior. If REGNUM is -1, do 149 this for all registers (including the floating-point registers). */ 150 151 void 152 m68k_bsd_nat_target::store_registers (struct regcache *regcache, int regnum) 153 { 154 pid_t pid = regcache->ptid ().pid (); 155 156 if (regnum == -1 || m68kbsd_gregset_supplies_p (regnum)) 157 { 158 struct reg regs; 159 160 if (ptrace (PT_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, inferior_ptid.lwp ()) == -1) 161 perror_with_name (_("Couldn't get registers")); 162 163 m68kbsd_collect_gregset (regcache, ®s, regnum); 164 165 if (ptrace (PT_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, inferior_ptid.lwp ()) == -1) 166 perror_with_name (_("Couldn't write registers")); 167 } 168 169 if (regnum == -1 || m68kbsd_fpregset_supplies_p (regnum)) 170 { 171 struct fpreg fpregs; 172 173 if (ptrace (PT_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, inferior_ptid.lwp ()) == -1) 174 perror_with_name (_("Couldn't get floating point status")); 175 176 m68kbsd_collect_fpregset (regcache, &fpregs, regnum); 177 178 if (ptrace (PT_SETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, inferior_ptid.lwp ()) == -1) 179 perror_with_name (_("Couldn't write floating point status")); 180 } 181 } 182 183 184 /* Support for debugging kernel virtual memory images. */ 185 186 #include <machine/pcb.h> 187 188 #include "bsd-kvm.h" 189 190 /* OpenBSD doesn't have these. */ 191 #ifndef PCB_REGS_FP 192 #define PCB_REGS_FP 10 193 #endif 194 #ifndef PCB_REGS_SP 195 #define PCB_REGS_SP 11 196 #endif 197 198 static int 199 m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb) 200 { 201 int regnum, tmp; 202 int i = 0; 203 204 /* The following is true for NetBSD 1.6.2: 205 206 The pcb contains %d2...%d7, %a2...%a7 and %ps. This accounts for 207 all callee-saved registers. From this information we reconstruct 208 the register state as it would look when we just returned from 209 cpu_switch(). */ 210 211 /* The stack pointer shouldn't be zero. */ 212 if (pcb->pcb_regs[PCB_REGS_SP] == 0) 213 return 0; 214 215 for (regnum = M68K_D2_REGNUM; regnum <= M68K_D7_REGNUM; regnum++) 216 regcache->raw_supply (regnum, &pcb->pcb_regs[i++]); 217 for (regnum = M68K_A2_REGNUM; regnum <= M68K_SP_REGNUM; regnum++) 218 regcache->raw_supply (regnum, &pcb->pcb_regs[i++]); 219 220 tmp = pcb->pcb_ps & 0xffff; 221 regcache->raw_supply (M68K_PS_REGNUM, &tmp); 222 223 read_memory (pcb->pcb_regs[PCB_REGS_FP] + 4, (gdb_byte *) &tmp, sizeof tmp); 224 regcache->raw_supply (M68K_PC_REGNUM, &tmp); 225 226 return 1; 227 } 228 229 void 230 _initialize_m68kbsd_nat (void) 231 { 232 add_inf_child_target (&the_m68k_bsd_nat_target); 233 234 /* Support debugging kernel virtual memory images. */ 235 bsd_kvm_add_target (m68kbsd_supply_pcb); 236 } 237