Copyright updates for 2007.
[external/binutils.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 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., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, 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 = hppa_linux_fetch_inferior_registers;
392   t->to_store_registers = hppa_linux_store_inferior_registers;
393
394   /* Register the target.  */
395   linux_nat_add_target (t);
396 }