(Fix date for):
[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
0fb0cc75
JB
3 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
4 Free Software Foundation, Inc.
50306a9d
RC
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
50306a9d
RC
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
50306a9d
RC
20
21#include "defs.h"
22#include "gdbcore.h"
23#include "regcache.h"
24#include "gdb_string.h"
959464ff 25#include "inferior.h"
10d6c8cd
DJ
26#include "target.h"
27#include "linux-nat.h"
50306a9d
RC
28
29#include <sys/procfs.h>
959464ff 30#include <sys/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
50306a9d
RC
38/* Prototypes for supply_gregset etc. */
39#include "gregset.h"
40
41/* These must match the order of the register names.
42
43 Some sort of lookup table is needed because the offsets associated
44 with the registers are all over the board. */
45
46static const int u_offsets[] =
47 {
48 /* general registers */
49 -1,
50 PT_GR1,
51 PT_GR2,
52 PT_GR3,
53 PT_GR4,
54 PT_GR5,
55 PT_GR6,
56 PT_GR7,
57 PT_GR8,
58 PT_GR9,
59 PT_GR10,
60 PT_GR11,
61 PT_GR12,
62 PT_GR13,
63 PT_GR14,
64 PT_GR15,
65 PT_GR16,
66 PT_GR17,
67 PT_GR18,
68 PT_GR19,
69 PT_GR20,
70 PT_GR21,
71 PT_GR22,
72 PT_GR23,
73 PT_GR24,
74 PT_GR25,
75 PT_GR26,
76 PT_GR27,
77 PT_GR28,
78 PT_GR29,
79 PT_GR30,
80 PT_GR31,
81
82 PT_SAR,
83 PT_IAOQ0,
84 PT_IASQ0,
85 PT_IAOQ1,
86 PT_IASQ1,
87 -1, /* eiem */
88 PT_IIR,
89 PT_ISR,
90 PT_IOR,
91 PT_PSW,
92 -1, /* goto */
93
94 PT_SR4,
95 PT_SR0,
96 PT_SR1,
97 PT_SR2,
98 PT_SR3,
99 PT_SR5,
100 PT_SR6,
101 PT_SR7,
102
103 -1, /* cr0 */
104 -1, /* pid0 */
105 -1, /* pid1 */
106 -1, /* ccr */
107 -1, /* pid2 */
108 -1, /* pid3 */
109 -1, /* cr24 */
110 -1, /* cr25 */
111 -1, /* cr26 */
112 PT_CR27,
113 -1, /* cr28 */
114 -1, /* cr29 */
115 -1, /* cr30 */
116
117 /* Floating point regs. */
118 PT_FR0, PT_FR0 + 4,
119 PT_FR1, PT_FR1 + 4,
120 PT_FR2, PT_FR2 + 4,
121 PT_FR3, PT_FR3 + 4,
122 PT_FR4, PT_FR4 + 4,
123 PT_FR5, PT_FR5 + 4,
124 PT_FR6, PT_FR6 + 4,
125 PT_FR7, PT_FR7 + 4,
126 PT_FR8, PT_FR8 + 4,
127 PT_FR9, PT_FR9 + 4,
128 PT_FR10, PT_FR10 + 4,
129 PT_FR11, PT_FR11 + 4,
130 PT_FR12, PT_FR12 + 4,
131 PT_FR13, PT_FR13 + 4,
132 PT_FR14, PT_FR14 + 4,
133 PT_FR15, PT_FR15 + 4,
134 PT_FR16, PT_FR16 + 4,
135 PT_FR17, PT_FR17 + 4,
136 PT_FR18, PT_FR18 + 4,
137 PT_FR19, PT_FR19 + 4,
138 PT_FR20, PT_FR20 + 4,
139 PT_FR21, PT_FR21 + 4,
140 PT_FR22, PT_FR22 + 4,
141 PT_FR23, PT_FR23 + 4,
142 PT_FR24, PT_FR24 + 4,
143 PT_FR25, PT_FR25 + 4,
144 PT_FR26, PT_FR26 + 4,
145 PT_FR27, PT_FR27 + 4,
146 PT_FR28, PT_FR28 + 4,
147 PT_FR29, PT_FR29 + 4,
148 PT_FR30, PT_FR30 + 4,
149 PT_FR31, PT_FR31 + 4,
150 };
151
de732108
UW
152static CORE_ADDR
153hppa_linux_register_addr (int regno, CORE_ADDR blockend)
50306a9d
RC
154{
155 CORE_ADDR addr;
156
e38c262f 157 if ((unsigned) regno >= ARRAY_SIZE (u_offsets))
8a3fe4f8 158 error (_("Invalid register number %d."), regno);
50306a9d
RC
159
160 if (u_offsets[regno] == -1)
161 addr = 0;
162 else
163 {
164 addr = (CORE_ADDR) u_offsets[regno];
165 }
166
167 return addr;
168}
169
170/*
171 * Registers saved in a coredump:
172 * gr0..gr31
173 * sr0..sr7
174 * iaoq0..iaoq1
175 * iasq0..iasq1
176 * sar, iir, isr, ior, ipsw
177 * cr0, cr24..cr31
178 * cr8,9,12,13
179 * cr10, cr15
180 */
34f75cc1
RC
181#define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
182#define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
50306a9d
RC
183static const int greg_map[] =
184 {
185 GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
186 GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
187 GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
188 GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
189 GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
190 GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
191 GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
192 GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
193
34f75cc1
RC
194 HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
195 HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
50306a9d 196
34f75cc1
RC
197 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
198 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
50306a9d 199
34f75cc1
RC
200 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
201 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
50306a9d
RC
202
203 TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
204 TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
205
34f75cc1
RC
206 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
207 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
50306a9d
RC
208 };
209
959464ff
RC
210
211
212/* Fetch one register. */
213
214static void
56be3814 215fetch_register (struct regcache *regcache, int regno)
959464ff 216{
464963c9 217 struct gdbarch *gdbarch = get_regcache_arch (regcache);
959464ff
RC
218 int tid;
219 int val;
220
464963c9 221 if (gdbarch_cannot_fetch_register (gdbarch, regno))
959464ff 222 {
56be3814 223 regcache_raw_supply (regcache, regno, NULL);
959464ff
RC
224 return;
225 }
226
227 /* GNU/Linux LWP ID's are process ID's. */
228 tid = TIDGET (inferior_ptid);
229 if (tid == 0)
230 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
231
232 errno = 0;
de732108 233 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
959464ff 234 if (errno != 0)
c9f4d572 235 error (_("Couldn't read register %s (#%d): %s."),
464963c9 236 gdbarch_register_name (gdbarch, regno),
959464ff
RC
237 regno, safe_strerror (errno));
238
56be3814 239 regcache_raw_supply (regcache, regno, &val);
959464ff
RC
240}
241
242/* Store one register. */
243
244static void
56be3814 245store_register (const struct regcache *regcache, int regno)
959464ff 246{
464963c9 247 struct gdbarch *gdbarch = get_regcache_arch (regcache);
959464ff
RC
248 int tid;
249 int val;
250
464963c9 251 if (gdbarch_cannot_store_register (gdbarch, regno))
959464ff
RC
252 return;
253
254 /* GNU/Linux LWP ID's are process ID's. */
255 tid = TIDGET (inferior_ptid);
256 if (tid == 0)
257 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
258
259 errno = 0;
56be3814 260 regcache_raw_collect (regcache, regno, &val);
de732108 261 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
959464ff 262 if (errno != 0)
c9f4d572 263 error (_("Couldn't write register %s (#%d): %s."),
464963c9 264 gdbarch_register_name (gdbarch, regno),
959464ff
RC
265 regno, safe_strerror (errno));
266}
267
268/* Fetch registers from the child process. Fetch all registers if
269 regno == -1, otherwise fetch all general registers or all floating
270 point registers depending upon the value of regno. */
271
10d6c8cd 272static void
28439f5e
PA
273hppa_linux_fetch_inferior_registers (struct target_ops *ops,
274 struct regcache *regcache, int regno)
959464ff
RC
275{
276 if (-1 == regno)
277 {
464963c9
UW
278 for (regno = 0;
279 regno < gdbarch_num_regs (get_regcache_arch (regcache));
280 regno++)
56be3814 281 fetch_register (regcache, regno);
959464ff
RC
282 }
283 else
284 {
56be3814 285 fetch_register (regcache, regno);
959464ff
RC
286 }
287}
288
289/* Store registers back into the inferior. Store all registers if
290 regno == -1, otherwise store all general registers or all floating
291 point registers depending upon the value of regno. */
292
10d6c8cd 293static void
28439f5e
PA
294hppa_linux_store_inferior_registers (struct target_ops *ops,
295 struct regcache *regcache, int regno)
959464ff
RC
296{
297 if (-1 == regno)
298 {
464963c9
UW
299 for (regno = 0;
300 regno < gdbarch_num_regs (get_regcache_arch (regcache));
301 regno++)
56be3814 302 store_register (regcache, regno);
959464ff
RC
303 }
304 else
305 {
56be3814 306 store_register (regcache, regno);
959464ff
RC
307 }
308}
309
310/* Fill GDB's register array with the general-purpose register values
311 in *gregsetp. */
312
50306a9d 313void
7f7fe91e 314supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
50306a9d
RC
315{
316 int i;
7f7fe91e 317 const greg_t *regp = (const elf_greg_t *) gregsetp;
50306a9d
RC
318
319 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
320 {
321 int regno = greg_map[i];
7f7fe91e 322 regcache_raw_supply (regcache, regno, regp);
50306a9d
RC
323 }
324}
325
959464ff
RC
326/* Fill register regno (if it is a general-purpose register) in
327 *gregsetp with the appropriate value from GDB's register array.
328 If regno is -1, do this for all registers. */
329
50306a9d 330void
7f7fe91e
UW
331fill_gregset (const struct regcache *regcache,
332 gdb_gregset_t *gregsetp, int regno)
50306a9d
RC
333{
334 int i;
50306a9d 335
959464ff 336 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
50306a9d 337 {
959464ff 338 int mregno = greg_map[i];
50306a9d 339
959464ff 340 if (regno == -1 || regno == mregno)
50306a9d 341 {
7f7fe91e 342 regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
50306a9d
RC
343 }
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
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
UW
359 from = (const char *) &((*fpregsetp)[regi]);
360 regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM, from);
361 regcache_raw_supply (regcache, 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
368 them all. */
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;
7f7fe91e 383 regcache_raw_collect (regcache, i, to);
50306a9d
RC
384 }
385}
10d6c8cd
DJ
386
387void _initialize_hppa_linux_nat (void);
388
389void
390_initialize_hppa_linux_nat (void)
391{
392 struct target_ops *t;
393
394 /* Fill in the generic GNU/Linux methods. */
395 t = linux_target ();
396
397 /* Add our register access methods. */
11fae660
RC
398 t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
399 t->to_store_registers = hppa_linux_store_inferior_registers;
10d6c8cd
DJ
400
401 /* Register the target. */
f973ed9c 402 linux_nat_add_target (t);
10d6c8cd 403}
This page took 0.353308 seconds and 4 git commands to generate.