gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / hppa-linux-nat.c
CommitLineData
9cbc6ef0
AC
1/* Functions specific to running GDB native on HPPA running GNU/Linux.
2
b811d2c2 3 Copyright (C) 2004-2020 Free Software Foundation, Inc.
50306a9d
RC
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
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
50306a9d
RC
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
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
50306a9d
RC
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "regcache.h"
959464ff 23#include "inferior.h"
10d6c8cd
DJ
24#include "target.h"
25#include "linux-nat.h"
00204cf7 26#include "inf-ptrace.h"
ad75efa6 27#include "gdbarch.h"
50306a9d
RC
28
29#include <sys/procfs.h>
5826e159 30#include "nat/gdb_ptrace.h"
9a727a3c
RC
31#include <linux/version.h>
32
afa35021
DJ
33#include <asm/ptrace.h>
34#include "hppa-linux-offsets.h"
50306a9d 35
34f75cc1
RC
36#include "hppa-tdep.h"
37
f6ac5f3d
PA
38class hppa_linux_nat_target final : public linux_nat_target
39{
40public:
41 /* Add our register access methods. */
42 void fetch_registers (struct regcache *, int) override;
43 void store_registers (struct regcache *, int) override;
44};
45
46static hppa_linux_nat_target the_hppa_linux_nat_target;
47
1777feb0 48/* Prototypes for supply_gregset etc. */
50306a9d
RC
49#include "gregset.h"
50
51/* These must match the order of the register names.
52
53 Some sort of lookup table is needed because the offsets associated
54 with the registers are all over the board. */
55
56static const int u_offsets[] =
57 {
58 /* general registers */
59 -1,
60 PT_GR1,
61 PT_GR2,
62 PT_GR3,
63 PT_GR4,
64 PT_GR5,
65 PT_GR6,
66 PT_GR7,
67 PT_GR8,
68 PT_GR9,
69 PT_GR10,
70 PT_GR11,
71 PT_GR12,
72 PT_GR13,
73 PT_GR14,
74 PT_GR15,
75 PT_GR16,
76 PT_GR17,
77 PT_GR18,
78 PT_GR19,
79 PT_GR20,
80 PT_GR21,
81 PT_GR22,
82 PT_GR23,
83 PT_GR24,
84 PT_GR25,
85 PT_GR26,
86 PT_GR27,
87 PT_GR28,
88 PT_GR29,
89 PT_GR30,
90 PT_GR31,
91
92 PT_SAR,
93 PT_IAOQ0,
94 PT_IASQ0,
95 PT_IAOQ1,
96 PT_IASQ1,
97 -1, /* eiem */
98 PT_IIR,
99 PT_ISR,
100 PT_IOR,
101 PT_PSW,
102 -1, /* goto */
103
104 PT_SR4,
105 PT_SR0,
106 PT_SR1,
107 PT_SR2,
108 PT_SR3,
109 PT_SR5,
110 PT_SR6,
111 PT_SR7,
112
113 -1, /* cr0 */
114 -1, /* pid0 */
115 -1, /* pid1 */
116 -1, /* ccr */
117 -1, /* pid2 */
118 -1, /* pid3 */
119 -1, /* cr24 */
120 -1, /* cr25 */
121 -1, /* cr26 */
122 PT_CR27,
123 -1, /* cr28 */
124 -1, /* cr29 */
125 -1, /* cr30 */
126
127 /* Floating point regs. */
128 PT_FR0, PT_FR0 + 4,
129 PT_FR1, PT_FR1 + 4,
130 PT_FR2, PT_FR2 + 4,
131 PT_FR3, PT_FR3 + 4,
132 PT_FR4, PT_FR4 + 4,
133 PT_FR5, PT_FR5 + 4,
134 PT_FR6, PT_FR6 + 4,
135 PT_FR7, PT_FR7 + 4,
136 PT_FR8, PT_FR8 + 4,
137 PT_FR9, PT_FR9 + 4,
138 PT_FR10, PT_FR10 + 4,
139 PT_FR11, PT_FR11 + 4,
140 PT_FR12, PT_FR12 + 4,
141 PT_FR13, PT_FR13 + 4,
142 PT_FR14, PT_FR14 + 4,
143 PT_FR15, PT_FR15 + 4,
144 PT_FR16, PT_FR16 + 4,
145 PT_FR17, PT_FR17 + 4,
146 PT_FR18, PT_FR18 + 4,
147 PT_FR19, PT_FR19 + 4,
148 PT_FR20, PT_FR20 + 4,
149 PT_FR21, PT_FR21 + 4,
150 PT_FR22, PT_FR22 + 4,
151 PT_FR23, PT_FR23 + 4,
152 PT_FR24, PT_FR24 + 4,
153 PT_FR25, PT_FR25 + 4,
154 PT_FR26, PT_FR26 + 4,
155 PT_FR27, PT_FR27 + 4,
156 PT_FR28, PT_FR28 + 4,
157 PT_FR29, PT_FR29 + 4,
158 PT_FR30, PT_FR30 + 4,
159 PT_FR31, PT_FR31 + 4,
160 };
161
de732108
UW
162static CORE_ADDR
163hppa_linux_register_addr (int regno, CORE_ADDR blockend)
50306a9d
RC
164{
165 CORE_ADDR addr;
166
e38c262f 167 if ((unsigned) regno >= ARRAY_SIZE (u_offsets))
8a3fe4f8 168 error (_("Invalid register number %d."), regno);
50306a9d
RC
169
170 if (u_offsets[regno] == -1)
171 addr = 0;
172 else
173 {
174 addr = (CORE_ADDR) u_offsets[regno];
175 }
176
177 return addr;
178}
179
180/*
181 * Registers saved in a coredump:
182 * gr0..gr31
183 * sr0..sr7
184 * iaoq0..iaoq1
185 * iasq0..iasq1
186 * sar, iir, isr, ior, ipsw
187 * cr0, cr24..cr31
188 * cr8,9,12,13
189 * cr10, cr15
190 */
34f75cc1
RC
191#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
192#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
50306a9d
RC
193static const int greg_map[] =
194 {
195 GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
196 GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
197 GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
198 GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
199 GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
200 GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
201 GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
202 GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
203
34f75cc1
RC
204 HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
205 HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
50306a9d 206
34f75cc1
RC
207 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
208 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
50306a9d 209
34f75cc1
RC
210 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
211 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
50306a9d
RC
212
213 TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
214 TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
215
34f75cc1
RC
216 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
217 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
50306a9d
RC
218 };
219
959464ff
RC
220
221
222/* Fetch one register. */
223
224static void
56be3814 225fetch_register (struct regcache *regcache, int regno)
959464ff 226{
ac7936df 227 struct gdbarch *gdbarch = regcache->arch ();
00204cf7 228 pid_t tid;
959464ff
RC
229 int val;
230
464963c9 231 if (gdbarch_cannot_fetch_register (gdbarch, regno))
959464ff 232 {
73e1c03f 233 regcache->raw_supply (regno, NULL);
959464ff
RC
234 return;
235 }
236
222312d3 237 tid = get_ptrace_pid (regcache->ptid ());
959464ff
RC
238
239 errno = 0;
de732108 240 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
959464ff 241 if (errno != 0)
c9f4d572 242 error (_("Couldn't read register %s (#%d): %s."),
464963c9 243 gdbarch_register_name (gdbarch, regno),
959464ff
RC
244 regno, safe_strerror (errno));
245
73e1c03f 246 regcache->raw_supply (regno, &val);
959464ff
RC
247}
248
1777feb0 249/* Store one register. */
959464ff
RC
250
251static void
56be3814 252store_register (const struct regcache *regcache, int regno)
959464ff 253{
ac7936df 254 struct gdbarch *gdbarch = regcache->arch ();
00204cf7 255 pid_t tid;
959464ff
RC
256 int val;
257
464963c9 258 if (gdbarch_cannot_store_register (gdbarch, regno))
959464ff
RC
259 return;
260
222312d3 261 tid = get_ptrace_pid (regcache->ptid ());
959464ff
RC
262
263 errno = 0;
34a79281 264 regcache->raw_collect (regno, &val);
de732108 265 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
959464ff 266 if (errno != 0)
c9f4d572 267 error (_("Couldn't write register %s (#%d): %s."),
464963c9 268 gdbarch_register_name (gdbarch, regno),
959464ff
RC
269 regno, safe_strerror (errno));
270}
271
272/* Fetch registers from the child process. Fetch all registers if
273 regno == -1, otherwise fetch all general registers or all floating
274 point registers depending upon the value of regno. */
275
f6ac5f3d 276void
69c67a0b 277hppa_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
959464ff
RC
278{
279 if (-1 == regno)
280 {
464963c9 281 for (regno = 0;
ac7936df 282 regno < gdbarch_num_regs (regcache->arch ());
464963c9 283 regno++)
56be3814 284 fetch_register (regcache, regno);
959464ff
RC
285 }
286 else
287 {
56be3814 288 fetch_register (regcache, regno);
959464ff
RC
289 }
290}
291
292/* Store registers back into the inferior. Store all registers if
293 regno == -1, otherwise store all general registers or all floating
294 point registers depending upon the value of regno. */
295
f6ac5f3d
PA
296void
297hppa_linux_nat_target::store_registers (struct regcache *regcache, int regno)
959464ff
RC
298{
299 if (-1 == regno)
300 {
464963c9 301 for (regno = 0;
ac7936df 302 regno < gdbarch_num_regs (regcache->arch ());
464963c9 303 regno++)
56be3814 304 store_register (regcache, regno);
959464ff
RC
305 }
306 else
307 {
56be3814 308 store_register (regcache, regno);
959464ff
RC
309 }
310}
311
312/* Fill GDB's register array with the general-purpose register values
313 in *gregsetp. */
314
50306a9d 315void
7f7fe91e 316supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
50306a9d
RC
317{
318 int i;
7f7fe91e 319 const greg_t *regp = (const elf_greg_t *) gregsetp;
50306a9d
RC
320
321 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
322 {
323 int regno = greg_map[i];
73e1c03f 324 regcache->raw_supply (regno, regp);
50306a9d
RC
325 }
326}
327
959464ff
RC
328/* Fill register regno (if it is a general-purpose register) in
329 *gregsetp with the appropriate value from GDB's register array.
330 If regno is -1, do this for all registers. */
331
50306a9d 332void
7f7fe91e
UW
333fill_gregset (const struct regcache *regcache,
334 gdb_gregset_t *gregsetp, int regno)
50306a9d
RC
335{
336 int i;
50306a9d 337
959464ff 338 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
50306a9d 339 {
959464ff 340 int mregno = greg_map[i];
50306a9d 341
959464ff 342 if (regno == -1 || regno == mregno)
34a79281 343 regcache->raw_collect (mregno, &(*gregsetp)[i]);
50306a9d
RC
344 }
345}
346
347/* Given a pointer to a floating point register set in /proc format
348 (fpregset_t *), unpack the register contents and supply them as gdb's
1777feb0 349 idea of the current floating point register values. */
50306a9d
RC
350
351void
7f7fe91e 352supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
50306a9d 353{
1b89295f 354 int regi;
7f7fe91e 355 const char *from;
50306a9d
RC
356
357 for (regi = 0; regi <= 31; regi++)
358 {
7f7fe91e 359 from = (const char *) &((*fpregsetp)[regi]);
73e1c03f
SM
360 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM, from);
361 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM + 1, from + 4);
50306a9d
RC
362 }
363}
364
365/* Given a pointer to a floating point register set in /proc format
366 (fpregset_t *), update the register specified by REGNO from gdb's idea
367 of the current floating point register set. If REGNO is -1, update
1777feb0 368 them all. */
50306a9d
RC
369
370void
7f7fe91e
UW
371fill_fpregset (const struct regcache *regcache,
372 gdb_fpregset_t *fpregsetp, int regno)
50306a9d
RC
373{
374 int i;
375
959464ff 376 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
50306a9d 377 {
959464ff
RC
378 /* Gross. fpregset_t is double, registers[x] has single
379 precision reg. */
380 char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
381 if ((i - HPPA_FP0_REGNUM) & 1)
382 to += 4;
34a79281 383 regcache->raw_collect (i, to);
50306a9d
RC
384 }
385}
10d6c8cd 386
6c265988 387void _initialize_hppa_linux_nat ();
10d6c8cd 388void
6c265988 389_initialize_hppa_linux_nat ()
10d6c8cd 390{
10d6c8cd 391 /* Register the target. */
f6ac5f3d 392 linux_target = &the_hppa_linux_nat_target;
d9f719f1 393 add_inf_child_target (&the_hppa_linux_nat_target);
10d6c8cd 394}
This page took 1.241138 seconds and 4 git commands to generate.