1 /* Native-dependent code for SPARC. 2 3 Copyright (C) 2003-2016 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 #include <signal.h> 26 #include <sys/ptrace.h> 27 #include "gdb_wait.h" 28 #ifdef HAVE_MACHINE_REG_H 29 #include <machine/reg.h> 30 #endif 31 32 #include "sparc-tdep.h" 33 #include "sparc-nat.h" 34 #include "inf-ptrace.h" 35 36 /* With some trickery we can use the code in this file for most (if 37 not all) ptrace(2) based SPARC systems, which includes SunOS 4, 38 GNU/Linux and the various SPARC BSD's. 39 40 First, we need a data structure for use with ptrace(2). SunOS has 41 `struct regs' and `struct fp_status' in <machine/reg.h>. BSD's 42 have `struct reg' and `struct fpreg' in <machine/reg.h>. GNU/Linux 43 has the same structures as SunOS 4, but they're in <asm/reg.h>, 44 which is a kernel header. As a general rule we avoid including 45 GNU/Linux kernel headers. Fortunately GNU/Linux has a `gregset_t' 46 and a `fpregset_t' that are equivalent to `struct regs' and `struct 47 fp_status' in <sys/ucontext.h>, which is automatically included by 48 <signal.h>. Settling on using the `gregset_t' and `fpregset_t' 49 typedefs, providing them for the other systems, therefore solves 50 the puzzle. */ 51 52 #ifdef HAVE_MACHINE_REG_H 53 #ifdef HAVE_STRUCT_REG 54 typedef struct reg gregset_t; 55 typedef struct fpreg fpregset_t; 56 #else 57 typedef struct regs gregset_t; 58 typedef struct fp_status fpregset_t; 59 #endif 60 #endif 61 62 /* Second, we need to remap the BSD ptrace(2) requests to their SunOS 63 equivalents. GNU/Linux already follows SunOS here. */ 64 65 #ifndef PTRACE_GETREGS 66 #define PTRACE_GETREGS PT_GETREGS 67 #endif 68 69 #ifndef PTRACE_SETREGS 70 #define PTRACE_SETREGS PT_SETREGS 71 #endif 72 73 #ifndef PTRACE_GETFPREGS 74 #define PTRACE_GETFPREGS PT_GETFPREGS 75 #endif 76 77 #ifndef PTRACE_SETFPREGS 78 #define PTRACE_SETFPREGS PT_SETFPREGS 79 #endif 80 81 /* Register set description. */ 82 const struct sparc_gregmap *sparc_gregmap; 83 const struct sparc_fpregmap *sparc_fpregmap; 84 void (*sparc_supply_gregset) (const struct sparc_gregmap *, 85 struct regcache *, int , const void *); 86 void (*sparc_collect_gregset) (const struct sparc_gregmap *, 87 const struct regcache *, int, void *); 88 void (*sparc_supply_fpregset) (const struct sparc_fpregmap *, 89 struct regcache *, int , const void *); 90 void (*sparc_collect_fpregset) (const struct sparc_fpregmap *, 91 const struct regcache *, int , void *); 92 int (*sparc_gregset_supplies_p) (struct gdbarch *, int); 93 int (*sparc_fpregset_supplies_p) (struct gdbarch *, int); 94 95 /* Determine whether `gregset_t' contains register REGNUM. */ 96 97 int 98 sparc32_gregset_supplies_p (struct gdbarch *gdbarch, int regnum) 99 { 100 /* Integer registers. */ 101 if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) 102 || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) 103 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) 104 || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM)) 105 return 1; 106 107 /* Control registers. */ 108 if (regnum == SPARC32_PC_REGNUM 109 || regnum == SPARC32_NPC_REGNUM 110 || regnum == SPARC32_PSR_REGNUM 111 || regnum == SPARC32_Y_REGNUM) 112 return 1; 113 114 return 0; 115 } 116 117 /* Determine whether `fpregset_t' contains register REGNUM. */ 118 119 int 120 sparc32_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum) 121 { 122 /* Floating-point registers. */ 123 if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM) 124 return 1; 125 126 /* Control registers. */ 127 if (regnum == SPARC32_FSR_REGNUM) 128 return 1; 129 130 return 0; 131 } 132 133 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 134 for all registers (including the floating-point registers). */ 135 136 void 137 sparc_fetch_inferior_registers (struct target_ops *ops, 138 struct regcache *regcache, int regnum) 139 { 140 struct gdbarch *gdbarch = get_regcache_arch (regcache); 141 int pid; 142 143 pid = ptid_get_pid (inferior_ptid); 144 145 if (regnum == SPARC_G0_REGNUM) 146 { 147 gdb_byte zero[8] = { 0 }; 148 149 regcache_raw_supply (regcache, SPARC_G0_REGNUM, &zero); 150 return; 151 } 152 153 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) 154 { 155 gregset_t regs; 156 157 if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 158 perror_with_name (_("Couldn't get registers")); 159 160 sparc_supply_gregset (sparc_gregmap, regcache, -1, ®s); 161 if (regnum != -1) 162 return; 163 } 164 165 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) 166 { 167 fpregset_t fpregs; 168 169 if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 170 perror_with_name (_("Couldn't get floating point status")); 171 172 sparc_supply_fpregset (sparc_fpregmap, regcache, -1, &fpregs); 173 } 174 } 175 176 void 177 sparc_store_inferior_registers (struct target_ops *ops, 178 struct regcache *regcache, int regnum) 179 { 180 struct gdbarch *gdbarch = get_regcache_arch (regcache); 181 int pid; 182 183 pid = ptid_get_pid (inferior_ptid); 184 185 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) 186 { 187 gregset_t regs; 188 189 if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 190 perror_with_name (_("Couldn't get registers")); 191 192 sparc_collect_gregset (sparc_gregmap, regcache, regnum, ®s); 193 194 if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, ptid_get_lwp (inferior_ptid)) == -1) 195 perror_with_name (_("Couldn't write registers")); 196 197 /* Deal with the stack regs. */ 198 if (regnum == -1 || regnum == SPARC_SP_REGNUM 199 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM)) 200 { 201 ULONGEST sp; 202 203 regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); 204 sparc_collect_rwindow (regcache, sp, regnum); 205 } 206 207 if (regnum != -1) 208 return; 209 } 210 211 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) 212 { 213 fpregset_t fpregs, saved_fpregs; 214 215 if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 216 perror_with_name (_("Couldn't get floating-point registers")); 217 218 memcpy (&saved_fpregs, &fpregs, sizeof (fpregs)); 219 sparc_collect_fpregset (sparc_fpregmap, regcache, regnum, &fpregs); 220 221 /* Writing the floating-point registers will fail on NetBSD with 222 EINVAL if the inferior process doesn't have an FPU state 223 (i.e. if it didn't use the FPU yet). Therefore we don't try 224 to write the registers if nothing changed. */ 225 if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0) 226 { 227 if (ptrace (PTRACE_SETFPREGS, pid, 228 (PTRACE_TYPE_ARG3) &fpregs, ptid_get_lwp (inferior_ptid)) == -1) 229 perror_with_name (_("Couldn't write floating-point registers")); 230 } 231 232 if (regnum != -1) 233 return; 234 } 235 } 236 237 238 /* Implement the to_xfer_partial target_ops method for 239 TARGET_OBJECT_WCOOKIE. Fetch StackGhost Per-Process XOR cookie. */ 240 241 static enum target_xfer_status 242 sparc_xfer_wcookie (struct target_ops *ops, enum target_object object, 243 const char *annex, gdb_byte *readbuf, 244 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, 245 ULONGEST *xfered_len) 246 { 247 unsigned long wcookie = 0; 248 char *buf = (char *)&wcookie; 249 250 gdb_assert (object == TARGET_OBJECT_WCOOKIE); 251 gdb_assert (readbuf && writebuf == NULL); 252 253 if (offset == sizeof (unsigned long)) 254 return TARGET_XFER_EOF; /* Signal EOF. */ 255 if (offset > sizeof (unsigned long)) 256 return TARGET_XFER_E_IO; 257 258 #ifdef PT_WCOOKIE 259 /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're 260 running on an OpenBSD release that uses StackGhost (3.1 or 261 later). Since release 3.6, OpenBSD uses a fully randomized 262 cookie. */ 263 { 264 int pid = ptid_get_pid (inferior_ptid); 265 266 /* Sanity check. The proper type for a cookie is register_t, but 267 we can't assume that this type exists on all systems supported 268 by the code in this file. */ 269 gdb_assert (sizeof (wcookie) == sizeof (register_t)); 270 271 /* Fetch the cookie. */ 272 if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1) 273 { 274 if (errno != EINVAL) 275 perror_with_name (_("Couldn't get StackGhost cookie")); 276 277 /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later, 278 the request wasn't implemented until after OpenBSD 3.4. If 279 the kernel doesn't support the PT_WCOOKIE request, assume 280 we're running on a kernel that uses non-randomized cookies. */ 281 wcookie = 0x3; 282 } 283 } 284 #endif /* PT_WCOOKIE */ 285 286 if (len > sizeof (unsigned long) - offset) 287 len = sizeof (unsigned long) - offset; 288 289 memcpy (readbuf, buf + offset, len); 290 *xfered_len = (ULONGEST) len; 291 return TARGET_XFER_OK; 292 } 293 294 target_xfer_partial_ftype *inf_ptrace_xfer_partial; 295 296 static enum target_xfer_status 297 sparc_xfer_partial (struct target_ops *ops, enum target_object object, 298 const char *annex, gdb_byte *readbuf, 299 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, 300 ULONGEST *xfered_len) 301 { 302 if (object == TARGET_OBJECT_WCOOKIE) 303 return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf, 304 offset, len, xfered_len); 305 306 return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf, 307 offset, len, xfered_len); 308 } 309 310 /* Create a prototype generic SPARC target. The client can override 311 it with local methods. */ 312 313 struct target_ops * 314 sparc_target (void) 315 { 316 struct target_ops *t; 317 318 t = inf_ptrace_target (); 319 t->to_fetch_registers = sparc_fetch_inferior_registers; 320 t->to_store_registers = sparc_store_inferior_registers; 321 inf_ptrace_xfer_partial = t->to_xfer_partial; 322 t->to_xfer_partial = sparc_xfer_partial; 323 return t; 324 } 325 326 327 /* Provide a prototype to silence -Wmissing-prototypes. */ 328 void _initialize_sparc_nat (void); 329 330 void 331 _initialize_sparc_nat (void) 332 { 333 /* Deafult to using SunOS 4 register sets. */ 334 if (sparc_gregmap == NULL) 335 sparc_gregmap = &sparc32_sunos4_gregmap; 336 if (sparc_fpregmap == NULL) 337 sparc_fpregmap = &sparc32_sunos4_fpregmap; 338 if (sparc_supply_gregset == NULL) 339 sparc_supply_gregset = sparc32_supply_gregset; 340 if (sparc_collect_gregset == NULL) 341 sparc_collect_gregset = sparc32_collect_gregset; 342 if (sparc_supply_fpregset == NULL) 343 sparc_supply_fpregset = sparc32_supply_fpregset; 344 if (sparc_collect_fpregset == NULL) 345 sparc_collect_fpregset = sparc32_collect_fpregset; 346 if (sparc_gregset_supplies_p == NULL) 347 sparc_gregset_supplies_p = sparc32_gregset_supplies_p; 348 if (sparc_fpregset_supplies_p == NULL) 349 sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p; 350 } 351