2007-06-09 Markus Deuling <deuling@de.ibm.com>
[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 static CORE_ADDR
157 hppa_linux_register_addr (int regno, CORE_ADDR blockend)
158 {
159   CORE_ADDR addr;
160
161   if ((unsigned) regno >= gdbarch_num_regs (current_gdbarch))
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 (struct regcache *regcache, int regno)
220 {
221   int tid;
222   int val;
223
224   if (gdbarch_cannot_fetch_register (current_gdbarch, regno))
225     {
226       regcache_raw_supply (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, hppa_linux_register_addr (regno, 0), 0);
237   if (errno != 0)
238     error (_("Couldn't read register %s (#%d): %s."), 
239            gdbarch_register_name (current_gdbarch, regno),
240            regno, safe_strerror (errno));
241
242   regcache_raw_supply (regcache, regno, &val);
243 }
244
245 /* Store one register. */
246
247 static void
248 store_register (const struct regcache *regcache, int regno)
249 {
250   int tid;
251   int val;
252
253   if (gdbarch_cannot_store_register (current_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 (current_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; regno < gdbarch_num_regs (current_gdbarch); regno++)
280         fetch_register (regcache, regno);
281     }
282   else 
283     {
284       fetch_register (regcache, regno);
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
292 static void
293 hppa_linux_store_inferior_registers (struct regcache *regcache, int regno)
294 {
295   if (-1 == regno)
296     {
297       for (regno = 0; regno < gdbarch_num_regs (current_gdbarch); regno++)
298         store_register (regcache, regno);
299     }
300   else
301     {
302       store_register (regcache, regno);
303     }
304 }
305
306 /* Fill GDB's register array with the general-purpose register values
307    in *gregsetp.  */
308
309 void
310 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
311 {
312   int i;
313   const greg_t *regp = (const elf_greg_t *) gregsetp;
314
315   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
316     {
317       int regno = greg_map[i];
318       regcache_raw_supply (regcache, regno, regp);
319     }
320 }
321
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
326 void
327 fill_gregset (const struct regcache *regcache,
328               gdb_gregset_t *gregsetp, int regno)
329 {
330   int i;
331
332   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
333     {
334       int mregno = greg_map[i];
335
336       if (regno == -1 || regno == mregno)
337         {
338           regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
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
347 void
348 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
349 {
350   int regi;
351   const char *from;
352
353   for (regi = 0; regi <= 31; regi++)
354     {
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);
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
366 void
367 fill_fpregset (const struct regcache *regcache,
368                gdb_fpregset_t *fpregsetp, int regno)
369 {
370   int i;
371
372   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
373    {
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;
379       regcache_raw_collect (regcache, i, to);
380    }
381 }
382
383 void _initialize_hppa_linux_nat (void);
384
385 void
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.  */
394   t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
395   t->to_store_registers = hppa_linux_store_inferior_registers;
396
397   /* Register the target.  */
398   linux_nat_add_target (t);
399 }