* Makefile.in (ALLDEPFILES): Update.
[deliverable/binutils-gdb.git] / gdb / hppa-linux-nat.c
1 /* Functions specific to running GDB native on HPPA running GNU/Linux.
2
3 Copyright 2004, 2005 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 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
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "gdbcore.h"
24 #include "regcache.h"
25 #include "gdb_string.h"
26 #include "inferior.h"
27 #include "target.h"
28 #include "linux-nat.h"
29
30 #include <sys/procfs.h>
31 #include <sys/ptrace.h>
32 #include <linux/version.h>
33
34 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43)
35 #include <asm/offset.h>
36 #else
37 #include <asm/offsets.h>
38 #endif
39
40 #include "hppa-tdep.h"
41
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
50 static 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
156 CORE_ADDR
157 register_addr (int regno, CORE_ADDR blockend)
158 {
159 CORE_ADDR addr;
160
161 if ((unsigned) regno >= NUM_REGS)
162 error (_("Invalid register number %d."), regno);
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 */
185 #define GR_REGNUM(_n) (HPPA_R0_REGNUM+_n)
186 #define TR_REGNUM(_n) (HPPA_TR0_REGNUM+_n)
187 static 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
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,
200
201 HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
202 HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
203
204 HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
205 HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
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
210 HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
211 HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
212 };
213
214
215
216 /* Fetch one register. */
217
218 static void
219 fetch_register (int regno)
220 {
221 int tid;
222 int val;
223
224 if (CANNOT_FETCH_REGISTER (regno))
225 {
226 regcache_raw_supply (current_regcache, regno, NULL);
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;
236 val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
237 if (errno != 0)
238 error (_("Couldn't read register %s (#%d): %s."), REGISTER_NAME (regno),
239 regno, safe_strerror (errno));
240
241 regcache_raw_supply (current_regcache, regno, &val);
242 }
243
244 /* Store one register. */
245
246 static void
247 store_register (int regno)
248 {
249 int tid;
250 int val;
251
252 if (CANNOT_STORE_REGISTER (regno))
253 return;
254
255 /* GNU/Linux LWP ID's are process ID's. */
256 tid = TIDGET (inferior_ptid);
257 if (tid == 0)
258 tid = PIDGET (inferior_ptid); /* Not a threaded program. */
259
260 errno = 0;
261 regcache_raw_collect (current_regcache, regno, &val);
262 ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
263 if (errno != 0)
264 error (_("Couldn't write register %s (#%d): %s."), REGISTER_NAME (regno),
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
272 static void
273 hppa_linux_fetch_inferior_registers (int regno)
274 {
275 if (-1 == regno)
276 {
277 for (regno = 0; regno < NUM_REGS; regno++)
278 fetch_register (regno);
279 }
280 else
281 {
282 fetch_register (regno);
283 }
284 }
285
286 /* Store registers back into the inferior. Store all registers if
287 regno == -1, otherwise store all general registers or all floating
288 point registers depending upon the value of regno. */
289
290 static void
291 hppa_linux_store_inferior_registers (int regno)
292 {
293 if (-1 == regno)
294 {
295 for (regno = 0; regno < NUM_REGS; regno++)
296 store_register (regno);
297 }
298 else
299 {
300 store_register (regno);
301 }
302 }
303
304 /* Fill GDB's register array with the general-purpose register values
305 in *gregsetp. */
306
307 void
308 supply_gregset (gdb_gregset_t *gregsetp)
309 {
310 int i;
311 greg_t *regp = (elf_greg_t *) gregsetp;
312
313 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
314 {
315 int regno = greg_map[i];
316 regcache_raw_supply (current_regcache, regno, regp);
317 }
318 }
319
320 /* Fill register regno (if it is a general-purpose register) in
321 *gregsetp with the appropriate value from GDB's register array.
322 If regno is -1, do this for all registers. */
323
324 void
325 fill_gregset (gdb_gregset_t *gregsetp, int regno)
326 {
327 int i;
328
329 for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
330 {
331 int mregno = greg_map[i];
332
333 if (regno == -1 || regno == mregno)
334 {
335 regcache_raw_collect(current_regcache, mregno, &(*gregsetp)[i]);
336 }
337 }
338 }
339
340 /* Given a pointer to a floating point register set in /proc format
341 (fpregset_t *), unpack the register contents and supply them as gdb's
342 idea of the current floating point register values. */
343
344 void
345 supply_fpregset (gdb_fpregset_t *fpregsetp)
346 {
347 int regi;
348 char *from;
349
350 for (regi = 0; regi <= 31; regi++)
351 {
352 from = (char *) &((*fpregsetp)[regi]);
353 regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM, from);
354 regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM + 1,
355 from + 4);
356 }
357 }
358
359 /* Given a pointer to a floating point register set in /proc format
360 (fpregset_t *), update the register specified by REGNO from gdb's idea
361 of the current floating point register set. If REGNO is -1, update
362 them all. */
363
364 void
365 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
366 {
367 int i;
368
369 for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
370 {
371 /* Gross. fpregset_t is double, registers[x] has single
372 precision reg. */
373 char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
374 if ((i - HPPA_FP0_REGNUM) & 1)
375 to += 4;
376 regcache_raw_collect (current_regcache, i, to);
377 }
378 }
379
380 void _initialize_hppa_linux_nat (void);
381
382 void
383 _initialize_hppa_linux_nat (void)
384 {
385 struct target_ops *t;
386
387 /* Fill in the generic GNU/Linux methods. */
388 t = linux_target ();
389
390 /* Add our register access methods. */
391 t->to_fetch_registers = arm_linux_fetch_inferior_registers;
392 t->to_store_registers = arm_linux_store_inferior_registers;
393
394 /* Register the target. */
395 add_target (t);
396 }
This page took 0.04926 seconds and 5 git commands to generate.