GDB (API)
|
00001 /* Native-dependent code for SPARC. 00002 00003 Copyright (C) 2003-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "inferior.h" 00022 #include "regcache.h" 00023 #include "target.h" 00024 00025 #include "gdb_assert.h" 00026 #include <signal.h> 00027 #include "gdb_string.h" 00028 #include <sys/ptrace.h> 00029 #include "gdb_wait.h" 00030 #ifdef HAVE_MACHINE_REG_H 00031 #include <machine/reg.h> 00032 #endif 00033 00034 #include "sparc-tdep.h" 00035 #include "sparc-nat.h" 00036 #include "inf-ptrace.h" 00037 00038 /* With some trickery we can use the code in this file for most (if 00039 not all) ptrace(2) based SPARC systems, which includes SunOS 4, 00040 GNU/Linux and the various SPARC BSD's. 00041 00042 First, we need a data structure for use with ptrace(2). SunOS has 00043 `struct regs' and `struct fp_status' in <machine/reg.h>. BSD's 00044 have `struct reg' and `struct fpreg' in <machine/reg.h>. GNU/Linux 00045 has the same structures as SunOS 4, but they're in <asm/reg.h>, 00046 which is a kernel header. As a general rule we avoid including 00047 GNU/Linux kernel headers. Fortunately GNU/Linux has a `gregset_t' 00048 and a `fpregset_t' that are equivalent to `struct regs' and `struct 00049 fp_status' in <sys/ucontext.h>, which is automatically included by 00050 <signal.h>. Settling on using the `gregset_t' and `fpregset_t' 00051 typedefs, providing them for the other systems, therefore solves 00052 the puzzle. */ 00053 00054 #ifdef HAVE_MACHINE_REG_H 00055 #ifdef HAVE_STRUCT_REG 00056 typedef struct reg gregset_t; 00057 typedef struct fpreg fpregset_t; 00058 #else 00059 typedef struct regs gregset_t; 00060 typedef struct fp_status fpregset_t; 00061 #endif 00062 #endif 00063 00064 /* Second, we need to remap the BSD ptrace(2) requests to their SunOS 00065 equivalents. GNU/Linux already follows SunOS here. */ 00066 00067 #ifndef PTRACE_GETREGS 00068 #define PTRACE_GETREGS PT_GETREGS 00069 #endif 00070 00071 #ifndef PTRACE_SETREGS 00072 #define PTRACE_SETREGS PT_SETREGS 00073 #endif 00074 00075 #ifndef PTRACE_GETFPREGS 00076 #define PTRACE_GETFPREGS PT_GETFPREGS 00077 #endif 00078 00079 #ifndef PTRACE_SETFPREGS 00080 #define PTRACE_SETFPREGS PT_SETFPREGS 00081 #endif 00082 00083 /* Register set description. */ 00084 const struct sparc_gregset *sparc_gregset; 00085 const struct sparc_fpregset *sparc_fpregset; 00086 void (*sparc_supply_gregset) (const struct sparc_gregset *, 00087 struct regcache *, int , const void *); 00088 void (*sparc_collect_gregset) (const struct sparc_gregset *, 00089 const struct regcache *, int, void *); 00090 void (*sparc_supply_fpregset) (const struct sparc_fpregset *, 00091 struct regcache *, int , const void *); 00092 void (*sparc_collect_fpregset) (const struct sparc_fpregset *, 00093 const struct regcache *, int , void *); 00094 int (*sparc_gregset_supplies_p) (struct gdbarch *, int); 00095 int (*sparc_fpregset_supplies_p) (struct gdbarch *, int); 00096 00097 /* Determine whether `gregset_t' contains register REGNUM. */ 00098 00099 int 00100 sparc32_gregset_supplies_p (struct gdbarch *gdbarch, int regnum) 00101 { 00102 /* Integer registers. */ 00103 if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM) 00104 || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM) 00105 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM) 00106 || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM)) 00107 return 1; 00108 00109 /* Control registers. */ 00110 if (regnum == SPARC32_PC_REGNUM 00111 || regnum == SPARC32_NPC_REGNUM 00112 || regnum == SPARC32_PSR_REGNUM 00113 || regnum == SPARC32_Y_REGNUM) 00114 return 1; 00115 00116 return 0; 00117 } 00118 00119 /* Determine whether `fpregset_t' contains register REGNUM. */ 00120 00121 int 00122 sparc32_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum) 00123 { 00124 /* Floating-point registers. */ 00125 if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM) 00126 return 1; 00127 00128 /* Control registers. */ 00129 if (regnum == SPARC32_FSR_REGNUM) 00130 return 1; 00131 00132 return 0; 00133 } 00134 00135 /* Fetch register REGNUM from the inferior. If REGNUM is -1, do this 00136 for all registers (including the floating-point registers). */ 00137 00138 void 00139 sparc_fetch_inferior_registers (struct target_ops *ops, 00140 struct regcache *regcache, int regnum) 00141 { 00142 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00143 int pid; 00144 00145 /* NOTE: cagney/2002-12-03: This code assumes that the currently 00146 selected light weight processes' registers can be written 00147 directly into the selected thread's register cache. This works 00148 fine when given an 1:1 LWP:thread model (such as found on 00149 GNU/Linux) but will, likely, have problems when used on an N:1 00150 (userland threads) or N:M (userland multiple LWP) model. In the 00151 case of the latter two, the LWP's registers do not necessarily 00152 belong to the selected thread (the LWP could be in the middle of 00153 executing the thread switch code). 00154 00155 These functions should instead be paramaterized with an explicit 00156 object (struct regcache, struct thread_info?) into which the LWPs 00157 registers can be written. */ 00158 pid = ptid_get_lwp (inferior_ptid); 00159 if (pid == 0) 00160 pid = ptid_get_pid (inferior_ptid); 00161 00162 if (regnum == SPARC_G0_REGNUM) 00163 { 00164 gdb_byte zero[8] = { 0 }; 00165 00166 regcache_raw_supply (regcache, SPARC_G0_REGNUM, &zero); 00167 return; 00168 } 00169 00170 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) 00171 { 00172 gregset_t regs; 00173 00174 if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00175 perror_with_name (_("Couldn't get registers")); 00176 00177 sparc_supply_gregset (sparc_gregset, regcache, -1, ®s); 00178 if (regnum != -1) 00179 return; 00180 } 00181 00182 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) 00183 { 00184 fpregset_t fpregs; 00185 00186 if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00187 perror_with_name (_("Couldn't get floating point status")); 00188 00189 sparc_supply_fpregset (sparc_fpregset, regcache, -1, &fpregs); 00190 } 00191 } 00192 00193 void 00194 sparc_store_inferior_registers (struct target_ops *ops, 00195 struct regcache *regcache, int regnum) 00196 { 00197 struct gdbarch *gdbarch = get_regcache_arch (regcache); 00198 int pid; 00199 00200 /* NOTE: cagney/2002-12-02: See comment in fetch_inferior_registers 00201 about threaded assumptions. */ 00202 pid = ptid_get_lwp (inferior_ptid); 00203 if (pid == 0) 00204 pid = ptid_get_pid (inferior_ptid); 00205 00206 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum)) 00207 { 00208 gregset_t regs; 00209 00210 if (ptrace (PTRACE_GETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00211 perror_with_name (_("Couldn't get registers")); 00212 00213 sparc_collect_gregset (sparc_gregset, regcache, regnum, ®s); 00214 00215 if (ptrace (PTRACE_SETREGS, pid, (PTRACE_TYPE_ARG3) ®s, 0) == -1) 00216 perror_with_name (_("Couldn't write registers")); 00217 00218 /* Deal with the stack regs. */ 00219 if (regnum == -1 || regnum == SPARC_SP_REGNUM 00220 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM)) 00221 { 00222 ULONGEST sp; 00223 00224 regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp); 00225 sparc_collect_rwindow (regcache, sp, regnum); 00226 } 00227 00228 if (regnum != -1) 00229 return; 00230 } 00231 00232 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum)) 00233 { 00234 fpregset_t fpregs, saved_fpregs; 00235 00236 if (ptrace (PTRACE_GETFPREGS, pid, (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00237 perror_with_name (_("Couldn't get floating-point registers")); 00238 00239 memcpy (&saved_fpregs, &fpregs, sizeof (fpregs)); 00240 sparc_collect_fpregset (sparc_fpregset, regcache, regnum, &fpregs); 00241 00242 /* Writing the floating-point registers will fail on NetBSD with 00243 EINVAL if the inferior process doesn't have an FPU state 00244 (i.e. if it didn't use the FPU yet). Therefore we don't try 00245 to write the registers if nothing changed. */ 00246 if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0) 00247 { 00248 if (ptrace (PTRACE_SETFPREGS, pid, 00249 (PTRACE_TYPE_ARG3) &fpregs, 0) == -1) 00250 perror_with_name (_("Couldn't write floating-point registers")); 00251 } 00252 00253 if (regnum != -1) 00254 return; 00255 } 00256 } 00257 00258 00259 /* Fetch StackGhost Per-Process XOR cookie. */ 00260 00261 static LONGEST 00262 sparc_xfer_wcookie (struct target_ops *ops, enum target_object object, 00263 const char *annex, gdb_byte *readbuf, 00264 const gdb_byte *writebuf, ULONGEST offset, LONGEST len) 00265 { 00266 unsigned long wcookie = 0; 00267 char *buf = (char *)&wcookie; 00268 00269 gdb_assert (object == TARGET_OBJECT_WCOOKIE); 00270 gdb_assert (readbuf && writebuf == NULL); 00271 00272 if (offset == sizeof (unsigned long)) 00273 return 0; /* Signal EOF. */ 00274 if (offset > sizeof (unsigned long)) 00275 return -1; 00276 00277 #ifdef PT_WCOOKIE 00278 /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're 00279 running on an OpenBSD release that uses StackGhost (3.1 or 00280 later). Since release 3.6, OpenBSD uses a fully randomized 00281 cookie. */ 00282 { 00283 int pid; 00284 00285 pid = ptid_get_lwp (inferior_ptid); 00286 if (pid == 0) 00287 pid = ptid_get_pid (inferior_ptid); 00288 00289 /* Sanity check. The proper type for a cookie is register_t, but 00290 we can't assume that this type exists on all systems supported 00291 by the code in this file. */ 00292 gdb_assert (sizeof (wcookie) == sizeof (register_t)); 00293 00294 /* Fetch the cookie. */ 00295 if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1) 00296 { 00297 if (errno != EINVAL) 00298 perror_with_name (_("Couldn't get StackGhost cookie")); 00299 00300 /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later, 00301 the request wasn't implemented until after OpenBSD 3.4. If 00302 the kernel doesn't support the PT_WCOOKIE request, assume 00303 we're running on a kernel that uses non-randomized cookies. */ 00304 wcookie = 0x3; 00305 } 00306 } 00307 #endif /* PT_WCOOKIE */ 00308 00309 if (len > sizeof (unsigned long) - offset) 00310 len = sizeof (unsigned long) - offset; 00311 00312 memcpy (readbuf, buf + offset, len); 00313 return len; 00314 } 00315 00316 LONGEST (*inf_ptrace_xfer_partial) (struct target_ops *, enum target_object, 00317 const char *, gdb_byte *, const gdb_byte *, 00318 ULONGEST, LONGEST); 00319 00320 static LONGEST 00321 sparc_xfer_partial (struct target_ops *ops, enum target_object object, 00322 const char *annex, gdb_byte *readbuf, 00323 const gdb_byte *writebuf, ULONGEST offset, LONGEST len) 00324 { 00325 if (object == TARGET_OBJECT_WCOOKIE) 00326 return sparc_xfer_wcookie (ops, object, annex, readbuf, writebuf, 00327 offset, len); 00328 00329 return inf_ptrace_xfer_partial (ops, object, annex, readbuf, writebuf, 00330 offset, len); 00331 } 00332 00333 /* Create a prototype generic SPARC target. The client can override 00334 it with local methods. */ 00335 00336 struct target_ops * 00337 sparc_target (void) 00338 { 00339 struct target_ops *t; 00340 00341 t = inf_ptrace_target (); 00342 t->to_fetch_registers = sparc_fetch_inferior_registers; 00343 t->to_store_registers = sparc_store_inferior_registers; 00344 inf_ptrace_xfer_partial = t->to_xfer_partial; 00345 t->to_xfer_partial = sparc_xfer_partial; 00346 return t; 00347 } 00348 00349 00350 /* Provide a prototype to silence -Wmissing-prototypes. */ 00351 void _initialize_sparc_nat (void); 00352 00353 void 00354 _initialize_sparc_nat (void) 00355 { 00356 /* Deafult to using SunOS 4 register sets. */ 00357 if (sparc_gregset == NULL) 00358 sparc_gregset = &sparc32_sunos4_gregset; 00359 if (sparc_fpregset == NULL) 00360 sparc_fpregset = &sparc32_sunos4_fpregset; 00361 if (sparc_supply_gregset == NULL) 00362 sparc_supply_gregset = sparc32_supply_gregset; 00363 if (sparc_collect_gregset == NULL) 00364 sparc_collect_gregset = sparc32_collect_gregset; 00365 if (sparc_supply_fpregset == NULL) 00366 sparc_supply_fpregset = sparc32_supply_fpregset; 00367 if (sparc_collect_fpregset == NULL) 00368 sparc_collect_fpregset = sparc32_collect_fpregset; 00369 if (sparc_gregset_supplies_p == NULL) 00370 sparc_gregset_supplies_p = sparc32_gregset_supplies_p; 00371 if (sparc_fpregset_supplies_p == NULL) 00372 sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p; 00373 }