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