Merge from gcc:
[deliverable/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, 2005, 2006, 2007 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 "gdb_string.h"
24 #include "inferior.h"
25 #include "target.h"
26 #include "linux-nat.h"
27
28 #include <sys/procfs.h>
29 #include <sys/ptrace.h>
30 #include <linux/version.h>
31
32 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43)
33 #include <asm/offset.h>
34 #else
35 #include <asm/offsets.h>
36 #endif
37
38 #include "hppa-tdep.h"
39
40 /* Prototypes for supply_gregset etc. */
41 #include "gregset.h"
42
43 /* These must match the order of the register names.
44
45 Some sort of lookup table is needed because the offsets associated
46 with the registers are all over the board. */
47
48 static const int u_offsets[] =
49 {
50 /* general registers */
51 -1,
52 PT_GR1,
53 PT_GR2,
54 PT_GR3,
55 PT_GR4,
56 PT_GR5,
57 PT_GR6,
58 PT_GR7,
59 PT_GR8,
60 PT_GR9,
61 PT_GR10,
62 PT_GR11,
63 PT_GR12,
64 PT_GR13,
65 PT_GR14,
66 PT_GR15,
67 PT_GR16,
68 PT_GR17,
69 PT_GR18,
70 PT_GR19,
71 PT_GR20,
72 PT_GR21,
73 PT_GR22,
74 PT_GR23,
75 PT_GR24,
76 PT_GR25,
77 PT_GR26,
78 PT_GR27,
79 PT_GR28,
80 PT_GR29,
81 PT_GR30,
82 PT_GR31,
83
84 PT_SAR,
85 PT_IAOQ0,
86 PT_IASQ0,
87 PT_IAOQ1,
88 PT_IASQ1,
89 -1, /* eiem */
90 PT_IIR,
91 PT_ISR,
92 PT_IOR,
93 PT_PSW,
94 -1, /* goto */
95
96 PT_SR4,
97 PT_SR0,
98 PT_SR1,
99 PT_SR2,
100 PT_SR3,
101 PT_SR5,
102 PT_SR6,
103 PT_SR7,
104
105 -1, /* cr0 */
106 -1, /* pid0 */
107 -1, /* pid1 */
108 -1, /* ccr */
109 -1, /* pid2 */
110 -1, /* pid3 */
111 -1, /* cr24 */
112 -1, /* cr25 */
113 -1, /* cr26 */
114 PT_CR27,
115 -1, /* cr28 */
116 -1, /* cr29 */
117 -1, /* cr30 */
118
119 /* Floating point regs. */
120 PT_FR0, PT_FR0 + 4,
121 PT_FR1, PT_FR1 + 4,
122 PT_FR2, PT_FR2 + 4,
123 PT_FR3, PT_FR3 + 4,
124 PT_FR4, PT_FR4 + 4,
125 PT_FR5, PT_FR5 + 4,
126 PT_FR6, PT_FR6 + 4,
127 PT_FR7, PT_FR7 + 4,
128 PT_FR8, PT_FR8 + 4,
129 PT_FR9, PT_FR9 + 4,
130 PT_FR10, PT_FR10 + 4,
131 PT_FR11, PT_FR11 + 4,
132 PT_FR12, PT_FR12 + 4,
133 PT_FR13, PT_FR13 + 4,
134 PT_FR14, PT_FR14 + 4,
135 PT_FR15, PT_FR15 + 4,
136 PT_FR16, PT_FR16 + 4,
137 PT_FR17, PT_FR17 + 4,
138 PT_FR18, PT_FR18 + 4,
139 PT_FR19, PT_FR19 + 4,
140 PT_FR20, PT_FR20 + 4,
141 PT_FR21, PT_FR21 + 4,
142 PT_FR22, PT_FR22 + 4,
143 PT_FR23, PT_FR23 + 4,
144 PT_FR24, PT_FR24 + 4,
145 PT_FR25, PT_FR25 + 4,
146 PT_FR26, PT_FR26 + 4,
147 PT_FR27, PT_FR27 + 4,
148 PT_FR28, PT_FR28 + 4,
149 PT_FR29, PT_FR29 + 4,
150 PT_FR30, PT_FR30 + 4,
151 PT_FR31, PT_FR31 + 4,
152 };
153
154 static CORE_ADDR
155 hppa_linux_register_addr (int regno, CORE_ADDR blockend)
156 {
157 CORE_ADDR addr;
158
159 if ((unsigned) regno >= gdbarch_num_regs (current_gdbarch))
160 error (_("Invalid register number %d."), regno);
161
162 if (u_offsets[regno] == -1)
163 addr = 0;
164 else
165 {
166 addr = (CORE_ADDR) u_offsets[regno];
167 }
168
169 return addr;
170 }
171
172 /*
173 * Registers saved in a coredump:
174 * gr0..gr31
175 * sr0..sr7
176 * iaoq0..iaoq1
177 * iasq0..iasq1
178 * sar, iir, isr, ior, ipsw
179 * cr0, cr24..cr31
180 * cr8,9,12,13
181 * cr10, cr15
182 */
183 #define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
184 #define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
185 static const int greg_map[] =
186 {
187 GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
188 GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
189 GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
190 GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
191 GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
192 GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
193 GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
194 GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
195
196 HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
197 HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
198
199 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
200 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
201
202 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
203 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
204
205 TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
206 TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
207
208 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
209 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
210 };
211
212
213
214 /* Fetch one register. */
215
216 static void
217 fetch_register (struct regcache *regcache, int regno)
218 {
219 struct gdbarch *gdbarch = get_regcache_arch (regcache);
220 int tid;
221 int val;
222
223 if (gdbarch_cannot_fetch_register (gdbarch, regno))
224 {
225 regcache_raw_supply (regcache, regno, NULL);
226 return;
227 }
228
229 /* GNU/Linux LWP ID's are process ID's. */
230 tid = TIDGET (inferior_ptid);
231 if (tid == 0)
232 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
233
234 errno = 0;
235 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
236 if (errno != 0)
237 error (_("Couldn't read register %s (#%d): %s."),
238 gdbarch_register_name (gdbarch, regno),
239 regno, safe_strerror (errno));
240
241 regcache_raw_supply (regcache, regno, &val);
242 }
243
244 /* Store one register. */
245
246 static void
247 store_register (const struct regcache *regcache, int regno)
248 {
249 struct gdbarch *gdbarch = get_regcache_arch (regcache);
250 int tid;
251 int val;
252
253 if (gdbarch_cannot_store_register (gdbarch, regno))
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;
262 regcache_raw_collect (regcache, regno, &val);
263 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
264 if (errno != 0)
265 error (_("Couldn't write register %s (#%d): %s."),
266 gdbarch_register_name (gdbarch, regno),
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
274 static void
275 hppa_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
276 {
277 if (-1 == regno)
278 {
279 for (regno = 0;
280 regno < gdbarch_num_regs (get_regcache_arch (regcache));
281 regno++)
282 fetch_register (regcache, regno);
283 }
284 else
285 {
286 fetch_register (regcache, regno);
287 }
288 }
289
290 /* Store registers back into the inferior. Store all registers if
291 regno == -1, otherwise store all general registers or all floating
292 point registers depending upon the value of regno. */
293
294 static void
295 hppa_linux_store_inferior_registers (struct regcache *regcache, int regno)
296 {
297 if (-1 == regno)
298 {
299 for (regno = 0;
300 regno < gdbarch_num_regs (get_regcache_arch (regcache));
301 regno++)
302 store_register (regcache, regno);
303 }
304 else
305 {
306 store_register (regcache, regno);
307 }
308 }
309
310 /* Fill GDB's register array with the general-purpose register values
311 in *gregsetp. */
312
313 void
314 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
315 {
316 int i;
317 const greg_t *regp = (const elf_greg_t *) gregsetp;
318
319 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
320 {
321 int regno = greg_map[i];
322 regcache_raw_supply (regcache, regno, regp);
323 }
324 }
325
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
330 void
331 fill_gregset (const struct regcache *regcache,
332 gdb_gregset_t *gregsetp, int regno)
333 {
334 int i;
335
336 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
337 {
338 int mregno = greg_map[i];
339
340 if (regno == -1 || regno == mregno)
341 {
342 regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
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
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 (regcache, 2*regi + HPPA_FP0_REGNUM, from);
361 regcache_raw_supply (regcache, 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 (regcache, i, to);
384 }
385 }
386
387 void _initialize_hppa_linux_nat (void);
388
389 void
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. */
398 t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
399 t->to_store_registers = hppa_linux_store_inferior_registers;
400
401 /* Register the target. */
402 linux_nat_add_target (t);
403 }
This page took 0.036768 seconds and 4 git commands to generate.