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