Automatic date update in version.in
[deliverable/binutils-gdb.git] / gdb / sparc-nat.c
CommitLineData
386c036b 1/* Native-dependent code for SPARC.
2555fe1a 2
3666a048 3 Copyright (C) 2003-2021 Free Software Foundation, Inc.
c906108c 4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c5aa993b 10 (at your option) any later version.
c906108c 11
c5aa993b
JM
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.
c906108c 16
c5aa993b 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
19
20#include "defs.h"
21#include "inferior.h"
4e052eda 22#include "regcache.h"
baf92889 23#include "target.h"
c906108c
SS
24
25#include <signal.h>
26#include <sys/ptrace.h>
268a13a5 27#include "gdbsupport/gdb_wait.h"
386c036b 28#ifdef HAVE_MACHINE_REG_H
c906108c
SS
29#include <machine/reg.h>
30#endif
c906108c 31
386c036b
MK
32#include "sparc-tdep.h"
33#include "sparc-nat.h"
1b9445c2 34#include "inf-ptrace.h"
386c036b
MK
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,
1a111ce3 38 GNU/Linux and the various SPARC BSD's.
386c036b
MK
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
54typedef struct reg gregset_t;
55typedef struct fpreg fpregset_t;
56#else
57typedef struct regs gregset_t;
58typedef 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. */
c906108c 64
386c036b
MK
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
c906108c 72
386c036b
MK
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
1ff700c2 81static PTRACE_TYPE_RET
2108a63a
KR
82gdb_ptrace (PTRACE_TYPE_ARG1 request, ptid_t ptid, PTRACE_TYPE_ARG3 addr)
83{
84#ifdef __NetBSD__
85 /* Support for NetBSD threads: unlike other ptrace implementations in this
86 file, NetBSD requires that we pass both the pid and lwp. */
87 return ptrace (request, ptid.pid (), addr, ptid.lwp ());
88#else
89 pid_t pid = get_ptrace_pid (ptid);
90 return ptrace (request, pid, addr, 0);
91#endif
92}
93
386c036b 94/* Register set description. */
b4fd25c9
AA
95const struct sparc_gregmap *sparc_gregmap;
96const struct sparc_fpregmap *sparc_fpregmap;
97void (*sparc_supply_gregset) (const struct sparc_gregmap *,
386c036b 98 struct regcache *, int , const void *);
b4fd25c9 99void (*sparc_collect_gregset) (const struct sparc_gregmap *,
386c036b 100 const struct regcache *, int, void *);
b4fd25c9 101void (*sparc_supply_fpregset) (const struct sparc_fpregmap *,
db75c717 102 struct regcache *, int , const void *);
b4fd25c9 103void (*sparc_collect_fpregset) (const struct sparc_fpregmap *,
db75c717 104 const struct regcache *, int , void *);
ec22ec34
UW
105int (*sparc_gregset_supplies_p) (struct gdbarch *, int);
106int (*sparc_fpregset_supplies_p) (struct gdbarch *, int);
386c036b
MK
107
108/* Determine whether `gregset_t' contains register REGNUM. */
109
110int
ec22ec34 111sparc32_gregset_supplies_p (struct gdbarch *gdbarch, int regnum)
386c036b
MK
112{
113 /* Integer registers. */
114 if ((regnum >= SPARC_G1_REGNUM && regnum <= SPARC_G7_REGNUM)
115 || (regnum >= SPARC_O0_REGNUM && regnum <= SPARC_O7_REGNUM)
116 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_L7_REGNUM)
117 || (regnum >= SPARC_I0_REGNUM && regnum <= SPARC_I7_REGNUM))
118 return 1;
119
120 /* Control registers. */
121 if (regnum == SPARC32_PC_REGNUM
122 || regnum == SPARC32_NPC_REGNUM
123 || regnum == SPARC32_PSR_REGNUM
124 || regnum == SPARC32_Y_REGNUM)
125 return 1;
126
127 return 0;
128}
129
130/* Determine whether `fpregset_t' contains register REGNUM. */
131
132int
ec22ec34 133sparc32_fpregset_supplies_p (struct gdbarch *gdbarch, int regnum)
386c036b
MK
134{
135 /* Floating-point registers. */
136 if (regnum >= SPARC_F0_REGNUM && regnum <= SPARC_F31_REGNUM)
137 return 1;
138
139 /* Control registers. */
140 if (regnum == SPARC32_FSR_REGNUM)
141 return 1;
142
143 return 0;
144}
145
146/* Fetch register REGNUM from the inferior. If REGNUM is -1, do this
147 for all registers (including the floating-point registers). */
c906108c
SS
148
149void
d1e93af6
SM
150sparc_fetch_inferior_registers (process_stratum_target *proc_target,
151 regcache *regcache, int regnum)
c906108c 152{
ac7936df 153 struct gdbarch *gdbarch = regcache->arch ();
2108a63a 154 ptid_t ptid = regcache->ptid ();
02ae7771 155
386c036b 156 if (regnum == SPARC_G0_REGNUM)
c906108c 157 {
22e74ef9
MK
158 gdb_byte zero[8] = { 0 };
159
73e1c03f 160 regcache->raw_supply (SPARC_G0_REGNUM, &zero);
386c036b 161 return;
c906108c
SS
162 }
163
ec22ec34 164 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum))
c906108c 165 {
386c036b 166 gregset_t regs;
c906108c 167
2108a63a 168 if (gdb_ptrace (PTRACE_GETREGS, ptid, (PTRACE_TYPE_ARG3) &regs) == -1)
e2e0b3e5 169 perror_with_name (_("Couldn't get registers"));
386c036b 170
d1e93af6
SM
171 /* Deep down, sparc_supply_rwindow reads memory, so needs the global
172 thread context to be set. */
cfa8e270
SM
173 scoped_restore restore_inferior_ptid
174 = make_scoped_restore (&inferior_ptid, ptid);
d1e93af6 175
b4fd25c9 176 sparc_supply_gregset (sparc_gregmap, regcache, -1, &regs);
386c036b
MK
177 if (regnum != -1)
178 return;
c906108c 179 }
386c036b 180
ec22ec34 181 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum))
c906108c 182 {
386c036b
MK
183 fpregset_t fpregs;
184
2108a63a 185 if (gdb_ptrace (PTRACE_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs) == -1)
e2e0b3e5 186 perror_with_name (_("Couldn't get floating point status"));
386c036b 187
b4fd25c9 188 sparc_supply_fpregset (sparc_fpregmap, regcache, -1, &fpregs);
c906108c
SS
189 }
190}
191
c906108c 192void
d1e93af6
SM
193sparc_store_inferior_registers (process_stratum_target *proc_target,
194 regcache *regcache, int regnum)
c906108c 195{
ac7936df 196 struct gdbarch *gdbarch = regcache->arch ();
2108a63a 197 ptid_t ptid = regcache->ptid ();
c906108c 198
ec22ec34 199 if (regnum == -1 || sparc_gregset_supplies_p (gdbarch, regnum))
e1925118 200 {
386c036b 201 gregset_t regs;
c906108c 202
2108a63a 203 if (gdb_ptrace (PTRACE_GETREGS, ptid, (PTRACE_TYPE_ARG3) &regs) == -1)
e2e0b3e5 204 perror_with_name (_("Couldn't get registers"));
c906108c 205
b4fd25c9 206 sparc_collect_gregset (sparc_gregmap, regcache, regnum, &regs);
c906108c 207
2108a63a 208 if (gdb_ptrace (PTRACE_SETREGS, ptid, (PTRACE_TYPE_ARG3) &regs) == -1)
e2e0b3e5 209 perror_with_name (_("Couldn't write registers"));
c5aa993b 210
386c036b
MK
211 /* Deal with the stack regs. */
212 if (regnum == -1 || regnum == SPARC_SP_REGNUM
213 || (regnum >= SPARC_L0_REGNUM && regnum <= SPARC_I7_REGNUM))
214 {
215 ULONGEST sp;
c906108c 216
386c036b 217 regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
d1e93af6
SM
218
219 /* Deep down, sparc_collect_rwindow writes memory, so needs the global
220 thread context to be set. */
cfa8e270
SM
221 scoped_restore restore_inferior_ptid
222 = make_scoped_restore (&inferior_ptid, ptid);
d1e93af6 223
386c036b
MK
224 sparc_collect_rwindow (regcache, sp, regnum);
225 }
c906108c 226
386c036b
MK
227 if (regnum != -1)
228 return;
c906108c 229 }
c906108c 230
ec22ec34 231 if (regnum == -1 || sparc_fpregset_supplies_p (gdbarch, regnum))
c5aa993b 232 {
386c036b 233 fpregset_t fpregs, saved_fpregs;
c906108c 234
2108a63a 235 if (gdb_ptrace (PTRACE_GETFPREGS, ptid, (PTRACE_TYPE_ARG3) &fpregs) == -1)
e2e0b3e5 236 perror_with_name (_("Couldn't get floating-point registers"));
c906108c 237
386c036b 238 memcpy (&saved_fpregs, &fpregs, sizeof (fpregs));
b4fd25c9 239 sparc_collect_fpregset (sparc_fpregmap, regcache, regnum, &fpregs);
c906108c 240
386c036b
MK
241 /* Writing the floating-point registers will fail on NetBSD with
242 EINVAL if the inferior process doesn't have an FPU state
243 (i.e. if it didn't use the FPU yet). Therefore we don't try
244 to write the registers if nothing changed. */
245 if (memcmp (&saved_fpregs, &fpregs, sizeof (fpregs)) != 0)
c5aa993b 246 {
2108a63a
KR
247 if (gdb_ptrace (PTRACE_SETFPREGS, ptid,
248 (PTRACE_TYPE_ARG3) &fpregs) == -1)
e2e0b3e5 249 perror_with_name (_("Couldn't write floating-point registers"));
c5aa993b 250 }
c906108c 251
386c036b
MK
252 if (regnum != -1)
253 return;
254 }
c906108c 255}
baf92889 256
c906108c 257\f
edcc890f
YQ
258/* Implement the to_xfer_partial target_ops method for
259 TARGET_OBJECT_WCOOKIE. Fetch StackGhost Per-Process XOR cookie. */
baf92889 260
f6ac5f3d 261enum target_xfer_status
cadc9cb8 262sparc_xfer_wcookie (enum target_object object,
961cb7b5 263 const char *annex, gdb_byte *readbuf,
9b409511
YQ
264 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
265 ULONGEST *xfered_len)
baf92889
MK
266{
267 unsigned long wcookie = 0;
268 char *buf = (char *)&wcookie;
269
270 gdb_assert (object == TARGET_OBJECT_WCOOKIE);
271 gdb_assert (readbuf && writebuf == NULL);
272
2c9771d3 273 if (offset == sizeof (unsigned long))
9b409511 274 return TARGET_XFER_EOF; /* Signal EOF. */
2c9771d3 275 if (offset > sizeof (unsigned long))
2ed4b548 276 return TARGET_XFER_E_IO;
c5aa993b 277
baf92889
MK
278#ifdef PT_WCOOKIE
279 /* If PT_WCOOKIE is defined (by <sys/ptrace.h>), assume we're
280 running on an OpenBSD release that uses StackGhost (3.1 or
2c9771d3
MK
281 later). Since release 3.6, OpenBSD uses a fully randomized
282 cookie. */
645d6d10 283 {
e99b03dc 284 int pid = inferior_ptid.pid ();
645d6d10
MK
285
286 /* Sanity check. The proper type for a cookie is register_t, but
287 we can't assume that this type exists on all systems supported
288 by the code in this file. */
289 gdb_assert (sizeof (wcookie) == sizeof (register_t));
290
291 /* Fetch the cookie. */
49ec097f 292 if (ptrace (PT_WCOOKIE, pid, (PTRACE_TYPE_ARG3) &wcookie, 0) == -1)
645d6d10
MK
293 {
294 if (errno != EINVAL)
e2e0b3e5 295 perror_with_name (_("Couldn't get StackGhost cookie"));
645d6d10
MK
296
297 /* Although PT_WCOOKIE is defined on OpenBSD 3.1 and later,
298 the request wasn't implemented until after OpenBSD 3.4. If
299 the kernel doesn't support the PT_WCOOKIE request, assume
300 we're running on a kernel that uses non-randomized cookies. */
301 wcookie = 0x3;
302 }
303 }
baf92889
MK
304#endif /* PT_WCOOKIE */
305
306 if (len > sizeof (unsigned long) - offset)
307 len = sizeof (unsigned long) - offset;
308
309 memcpy (readbuf, buf + offset, len);
9b409511
YQ
310 *xfered_len = (ULONGEST) len;
311 return TARGET_XFER_OK;
baf92889 312}
1b9445c2 313\f
baf92889 314
6c265988 315void _initialize_sparc_nat ();
c906108c 316void
6c265988 317_initialize_sparc_nat ()
c906108c 318{
405feb71 319 /* Default to using SunOS 4 register sets. */
b4fd25c9
AA
320 if (sparc_gregmap == NULL)
321 sparc_gregmap = &sparc32_sunos4_gregmap;
322 if (sparc_fpregmap == NULL)
323 sparc_fpregmap = &sparc32_sunos4_fpregmap;
386c036b
MK
324 if (sparc_supply_gregset == NULL)
325 sparc_supply_gregset = sparc32_supply_gregset;
326 if (sparc_collect_gregset == NULL)
327 sparc_collect_gregset = sparc32_collect_gregset;
328 if (sparc_supply_fpregset == NULL)
329 sparc_supply_fpregset = sparc32_supply_fpregset;
330 if (sparc_collect_fpregset == NULL)
331 sparc_collect_fpregset = sparc32_collect_fpregset;
332 if (sparc_gregset_supplies_p == NULL)
333 sparc_gregset_supplies_p = sparc32_gregset_supplies_p;
334 if (sparc_fpregset_supplies_p == NULL)
335 sparc_fpregset_supplies_p = sparc32_fpregset_supplies_p;
c906108c 336}
This page took 2.242308 seconds and 4 git commands to generate.