]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/hppa-linux-nat.c
Automatic date update in version.in
[thirdparty/binutils-gdb.git] / gdb / hppa-linux-nat.c
1 /* Functions specific to running GDB native on HPPA running GNU/Linux.
2
3 Copyright (C) 2004-2020 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
38 class hppa_linux_nat_target final : public linux_nat_target
39 {
40 public:
41 /* Add our register access methods. */
42 void fetch_registers (struct regcache *, int) override;
43 void store_registers (struct regcache *, int) override;
44 };
45
46 static hppa_linux_nat_target the_hppa_linux_nat_target;
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
56 static 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
162 static CORE_ADDR
163 hppa_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)
193 static 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
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,
206
207 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
208 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
209
210 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
211 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
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
216 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
217 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
218 };
219
220
221
222 /* Fetch one register. */
223
224 static void
225 fetch_register (struct regcache *regcache, int regno)
226 {
227 struct gdbarch *gdbarch = regcache->arch ();
228 pid_t tid;
229 int val;
230
231 if (gdbarch_cannot_fetch_register (gdbarch, regno))
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."),
243 gdbarch_register_name (gdbarch, regno),
244 regno, safe_strerror (errno));
245
246 regcache->raw_supply (regno, &val);
247 }
248
249 /* Store one register. */
250
251 static void
252 store_register (const struct regcache *regcache, int regno)
253 {
254 struct gdbarch *gdbarch = regcache->arch ();
255 pid_t tid;
256 int val;
257
258 if (gdbarch_cannot_store_register (gdbarch, regno))
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."),
268 gdbarch_register_name (gdbarch, regno),
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
276 void
277 hppa_linux_nat_target::fetch_registers (struct regcache *regcache, int regno)
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
296 void
297 hppa_linux_nat_target::store_registers (struct regcache *regcache, int regno)
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
315 void
316 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
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
332 void
333 fill_gregset (const struct regcache *regcache,
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
351 void
352 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
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
370 void
371 fill_fpregset (const struct regcache *regcache,
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
387 void _initialize_hppa_linux_nat ();
388 void
389 _initialize_hppa_linux_nat ()
390 {
391 /* Register the target. */
392 linux_target = &the_hppa_linux_nat_target;
393 add_inf_child_target (&the_hppa_linux_nat_target);
394 }