* hppa-linux-nat.c: Use hppa-linux-offsets.h.
[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 #include <asm/ptrace.h>
33 #include "hppa-linux-offsets.h"
34
35 #include "hppa-tdep.h"
36
37 /* Prototypes for supply_gregset etc. */
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
45 static 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
151 static CORE_ADDR
152 hppa_linux_register_addr (int regno, CORE_ADDR blockend)
153 {
154 CORE_ADDR addr;
155
156 if ((unsigned) regno >= gdbarch_num_regs (current_gdbarch))
157 error (_("Invalid register number %d."), regno);
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 */
180 #define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
181 #define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
182 static 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
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,
195
196 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
197 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
198
199 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
200 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
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
205 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
206 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
207 };
208
209
210
211 /* Fetch one register. */
212
213 static void
214 fetch_register (struct regcache *regcache, int regno)
215 {
216 struct gdbarch *gdbarch = get_regcache_arch (regcache);
217 int tid;
218 int val;
219
220 if (gdbarch_cannot_fetch_register (gdbarch, regno))
221 {
222 regcache_raw_supply (regcache, regno, NULL);
223 return;
224 }
225
226 /* GNU/Linux LWP ID's are process ID's. */
227 tid = TIDGET (inferior_ptid);
228 if (tid == 0)
229 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
230
231 errno = 0;
232 val = ptrace (PTRACE_PEEKUSER, tid, hppa_linux_register_addr (regno, 0), 0);
233 if (errno != 0)
234 error (_("Couldn't read register %s (#%d): %s."),
235 gdbarch_register_name (gdbarch, regno),
236 regno, safe_strerror (errno));
237
238 regcache_raw_supply (regcache, regno, &val);
239 }
240
241 /* Store one register. */
242
243 static void
244 store_register (const struct regcache *regcache, int regno)
245 {
246 struct gdbarch *gdbarch = get_regcache_arch (regcache);
247 int tid;
248 int val;
249
250 if (gdbarch_cannot_store_register (gdbarch, regno))
251 return;
252
253 /* GNU/Linux LWP ID's are process ID's. */
254 tid = TIDGET (inferior_ptid);
255 if (tid == 0)
256 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
257
258 errno = 0;
259 regcache_raw_collect (regcache, regno, &val);
260 ptrace (PTRACE_POKEUSER, tid, hppa_linux_register_addr (regno, 0), val);
261 if (errno != 0)
262 error (_("Couldn't write register %s (#%d): %s."),
263 gdbarch_register_name (gdbarch, regno),
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
271 static void
272 hppa_linux_fetch_inferior_registers (struct regcache *regcache, int regno)
273 {
274 if (-1 == regno)
275 {
276 for (regno = 0;
277 regno < gdbarch_num_regs (get_regcache_arch (regcache));
278 regno++)
279 fetch_register (regcache, regno);
280 }
281 else
282 {
283 fetch_register (regcache, regno);
284 }
285 }
286
287 /* Store registers back into the inferior. Store all registers if
288 regno == -1, otherwise store all general registers or all floating
289 point registers depending upon the value of regno. */
290
291 static void
292 hppa_linux_store_inferior_registers (struct regcache *regcache, int regno)
293 {
294 if (-1 == regno)
295 {
296 for (regno = 0;
297 regno < gdbarch_num_regs (get_regcache_arch (regcache));
298 regno++)
299 store_register (regcache, regno);
300 }
301 else
302 {
303 store_register (regcache, regno);
304 }
305 }
306
307 /* Fill GDB's register array with the general-purpose register values
308 in *gregsetp. */
309
310 void
311 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
312 {
313 int i;
314 const greg_t *regp = (const elf_greg_t *) gregsetp;
315
316 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
317 {
318 int regno = greg_map[i];
319 regcache_raw_supply (regcache, regno, regp);
320 }
321 }
322
323 /* Fill register regno (if it is a general-purpose register) in
324 *gregsetp with the appropriate value from GDB's register array.
325 If regno is -1, do this for all registers. */
326
327 void
328 fill_gregset (const struct regcache *regcache,
329 gdb_gregset_t *gregsetp, int regno)
330 {
331 int i;
332
333 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
334 {
335 int mregno = greg_map[i];
336
337 if (regno == -1 || regno == mregno)
338 {
339 regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
340 }
341 }
342 }
343
344 /* Given a pointer to a floating point register set in /proc format
345 (fpregset_t *), unpack the register contents and supply them as gdb's
346 idea of the current floating point register values. */
347
348 void
349 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
350 {
351 int regi;
352 const char *from;
353
354 for (regi = 0; regi <= 31; regi++)
355 {
356 from = (const char *) &((*fpregsetp)[regi]);
357 regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM, from);
358 regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM + 1, from + 4);
359 }
360 }
361
362 /* Given a pointer to a floating point register set in /proc format
363 (fpregset_t *), update the register specified by REGNO from gdb's idea
364 of the current floating point register set. If REGNO is -1, update
365 them all. */
366
367 void
368 fill_fpregset (const struct regcache *regcache,
369 gdb_fpregset_t *fpregsetp, int regno)
370 {
371 int i;
372
373 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
374 {
375 /* Gross. fpregset_t is double, registers[x] has single
376 precision reg. */
377 char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
378 if ((i - HPPA_FP0_REGNUM) & 1)
379 to += 4;
380 regcache_raw_collect (regcache, i, to);
381 }
382 }
383
384 void _initialize_hppa_linux_nat (void);
385
386 void
387 _initialize_hppa_linux_nat (void)
388 {
389 struct target_ops *t;
390
391 /* Fill in the generic GNU/Linux methods. */
392 t = linux_target ();
393
394 /* Add our register access methods. */
395 t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
396 t->to_store_registers = hppa_linux_store_inferior_registers;
397
398 /* Register the target. */
399 linux_nat_add_target (t);
400 }
This page took 0.055546 seconds and 5 git commands to generate.