GDB (xrefs)
Loading...
Searching...
No Matches
hppa-linux-nat.c
Go to the documentation of this file.
1/* Functions specific to running GDB native on HPPA running GNU/Linux.
2
3 Copyright (C) 2004-2023 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 "regcache.h"
23#include "inferior.h"
24#include "target.h"
25#include "linux-nat.h"
26#include "inf-ptrace.h"
27#include "gdbarch.h"
28
29#include <sys/procfs.h>
30#include "nat/gdb_ptrace.h"
31#include <linux/version.h>
32
33#include <asm/ptrace.h>
34#include "hppa-linux-offsets.h"
35
36#include "hppa-tdep.h"
37
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
47
48/* Prototypes for supply_gregset etc. */
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,
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
162static CORE_ADDR
163hppa_linux_register_addr (int regno, CORE_ADDR blockend)
164{
165 CORE_ADDR addr;
166
167 if ((unsigned) regno >= ARRAY_SIZE (u_offsets))
168 error (_("Invalid register number %d."), regno);
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 */
191#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
192#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
219
220
221
222/* Fetch one register. */
223
224static void
225fetch_register (struct regcache *regcache, int regno)
226{
227 struct gdbarch *gdbarch = regcache->arch ();
228 pid_t tid;
229 int val;
230
232 {
233 regcache->raw_supply (regno, NULL);
234 return;
235 }
236
237 tid = get_ptrace_pid (regcache->ptid ());
238
239 errno = 0;
240 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
241 if (errno != 0)
242 error (_("Couldn't read register %s (#%d): %s."),
244 regno, safe_strerror (errno));
245
246 regcache->raw_supply (regno, &val);
247}
248
249/* Store one register. */
250
251static void
252store_register (const struct regcache *regcache, int regno)
253{
254 struct gdbarch *gdbarch = regcache->arch ();
255 pid_t tid;
256 int val;
257
259 return;
260
261 tid = get_ptrace_pid (regcache->ptid ());
262
263 errno = 0;
264 regcache->raw_collect (regno, &val);
265 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
266 if (errno != 0)
267 error (_("Couldn't write register %s (#%d): %s."),
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
276void
278{
279 if (-1 == regno)
280 {
281 for (regno = 0;
282 regno < gdbarch_num_regs (regcache->arch ());
283 regno++)
284 fetch_register (regcache, regno);
285 }
286 else
287 {
288 fetch_register (regcache, regno);
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
296void
298{
299 if (-1 == regno)
300 {
301 for (regno = 0;
302 regno < gdbarch_num_regs (regcache->arch ());
303 regno++)
304 store_register (regcache, regno);
305 }
306 else
307 {
308 store_register (regcache, regno);
309 }
310}
311
312/* Fill GDB's register array with the general-purpose register values
313 in *gregsetp. */
314
315void
317{
318 int i;
319 const greg_t *regp = (const elf_greg_t *) gregsetp;
320
321 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
322 {
323 int regno = greg_map[i];
324 regcache->raw_supply (regno, regp);
325 }
326}
327
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
332void
334 gdb_gregset_t *gregsetp, int regno)
335{
336 int i;
337
338 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
339 {
340 int mregno = greg_map[i];
341
342 if (regno == -1 || regno == mregno)
343 regcache->raw_collect (mregno, &(*gregsetp)[i]);
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
349 idea of the current floating point register values. */
350
351void
353{
354 int regi;
355 const char *from;
356
357 for (regi = 0; regi <= 31; regi++)
358 {
359 from = (const char *) &((*fpregsetp)[regi]);
360 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM, from);
361 regcache->raw_supply (2*regi + HPPA_FP0_REGNUM + 1, from + 4);
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
368 them all. */
369
370void
372 gdb_fpregset_t *fpregsetp, int regno)
373{
374 int i;
375
376 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
377 {
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;
383 regcache->raw_collect (i, to);
384 }
385}
386
388void
void fetch_registers(struct regcache *, int) override
void store_registers(struct regcache *, int) override
gdbarch * arch() const
Definition regcache.c:231
void raw_collect(int regnum, void *buf) const override
Definition regcache.c:1127
void raw_supply(int regnum, const void *buf) override
Definition regcache.c:1062
ptid_t ptid() const
Definition regcache.h:408
#define ptrace(request, pid, addr, data)
Definition gdb_ptrace.h:141
int gdbarch_cannot_store_register(struct gdbarch *gdbarch, int regnum)
Definition gdbarch.c:2419
int gdbarch_cannot_fetch_register(struct gdbarch *gdbarch, int regnum)
Definition gdbarch.c:2402
const char * gdbarch_register_name(struct gdbarch *gdbarch, int regnr)
Definition gdbarch.c:2173
int gdbarch_num_regs(struct gdbarch *gdbarch)
Definition gdbarch.c:1930
GDB_FPREGSET_T gdb_fpregset_t
Definition gregset.h:35
GDB_GREGSET_T gdb_gregset_t
Definition gregset.h:34
static void fetch_register(struct regcache *regcache, int regno)
void _initialize_hppa_linux_nat()
static const int u_offsets[]
void supply_gregset(struct regcache *regcache, const gdb_gregset_t *gregsetp)
#define TR_REGNUM(_n)
void fill_gregset(const struct regcache *regcache, gdb_gregset_t *gregsetp, int regno)
static hppa_linux_nat_target the_hppa_linux_nat_target
static void store_register(const struct regcache *regcache, int regno)
void supply_fpregset(struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
static CORE_ADDR hppa_linux_register_addr(int regno, CORE_ADDR blockend)
static const int greg_map[]
void fill_fpregset(const struct regcache *regcache, gdb_fpregset_t *fpregsetp, int regno)
#define GR_REGNUM(_n)
#define PT_FR15
#define PT_FR7
#define PT_FR0
#define PT_FR27
#define PT_GR23
#define PT_GR29
#define PT_FR3
#define PT_FR4
#define PT_GR22
#define PT_FR20
#define PT_SR1
#define PT_GR2
#define PT_FR11
#define PT_SR0
#define PT_GR8
#define PT_IAOQ1
#define PT_GR27
#define PT_CR27
#define PT_FR25
#define PT_FR8
#define PT_FR29
#define PT_GR20
#define PT_FR10
#define PT_FR5
#define PT_FR2
#define PT_GR21
#define PT_GR9
#define PT_SAR
#define PT_FR13
#define PT_FR23
#define PT_GR10
#define PT_GR7
#define PT_FR16
#define PT_GR30
#define PT_FR31
#define PT_FR18
#define PT_SR2
#define PT_GR4
#define PT_FR17
#define PT_SR5
#define PT_FR21
#define PT_GR1
#define PT_FR6
#define PT_GR5
#define PT_FR26
#define PT_SR3
#define PT_GR25
#define PT_GR14
#define PT_GR24
#define PT_GR13
#define PT_IOR
#define PT_FR30
#define PT_GR11
#define PT_GR26
#define PT_FR9
#define PT_FR19
#define PT_IIR
#define PT_ISR
#define PT_IASQ0
#define PT_FR14
#define PT_FR28
#define PT_PSW
#define PT_GR12
#define PT_IASQ1
#define PT_SR6
#define PT_GR19
#define PT_IAOQ0
#define PT_GR17
#define PT_GR6
#define PT_FR22
#define PT_SR4
#define PT_GR3
#define PT_GR31
#define PT_FR12
#define PT_SR7
#define PT_FR24
#define PT_GR16
#define PT_GR18
#define PT_GR15
#define PT_GR28
#define PT_FR1
@ HPPA_CCR_REGNUM
Definition hppa-tdep.h:67
@ HPPA_PCSQ_HEAD_REGNUM
Definition hppa-tdep.h:47
@ HPPA_IOR_REGNUM
Definition hppa-tdep.h:53
@ HPPA_PID3_REGNUM
Definition hppa-tdep.h:66
@ HPPA_SAR_REGNUM
Definition hppa-tdep.h:44
@ HPPA_IPSW_REGNUM
Definition hppa-tdep.h:45
@ HPPA_ISR_REGNUM
Definition hppa-tdep.h:52
@ HPPA_PID1_REGNUM
Definition hppa-tdep.h:64
@ HPPA_PID0_REGNUM
Definition hppa-tdep.h:63
@ HPPA_PCOQ_HEAD_REGNUM
Definition hppa-tdep.h:46
@ HPPA_PID2_REGNUM
Definition hppa-tdep.h:65
@ HPPA_PCSQ_TAIL_REGNUM
Definition hppa-tdep.h:49
@ HPPA_PCOQ_TAIL_REGNUM
Definition hppa-tdep.h:48
@ HPPA_FP0_REGNUM
Definition hppa-tdep.h:72
@ HPPA_RCR_REGNUM
Definition hppa-tdep.h:62
@ HPPA_EIEM_REGNUM
Definition hppa-tdep.h:50
@ HPPA_SR4_REGNUM
Definition hppa-tdep.h:54
@ HPPA_IIR_REGNUM
Definition hppa-tdep.h:51
void add_inf_child_target(inf_child_target *target)
Definition inf-child.c:418
pid_t get_ptrace_pid(ptid_t ptid)
Definition inf-ptrace.c:238
struct linux_nat_target * linux_target
Definition linux-nat.c:189