xref: /netbsd-src/external/gpl3/gdb/dist/gdb/hppa-linux-nat.c (revision b7b7574d3bf8eeb51a1fa3977b59142ec6434a55)
1 /* Functions specific to running GDB native on HPPA running GNU/Linux.
2 
3    Copyright (C) 2004-2014 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 <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 >= ARRAY_SIZE (u_offsets))
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 = ptid_get_lwp (inferior_ptid);
228   if (tid == 0)
229     tid = ptid_get_pid (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 = ptid_get_lwp (inferior_ptid);
255   if (tid == 0)
256     tid = ptid_get_pid (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 target_ops *ops,
273 				     struct regcache *regcache, int regno)
274 {
275   if (-1 == regno)
276     {
277       for (regno = 0;
278 	   regno < gdbarch_num_regs (get_regcache_arch (regcache));
279 	   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 target_ops *ops,
294 				     struct regcache *regcache, int regno)
295 {
296   if (-1 == regno)
297     {
298       for (regno = 0;
299 	   regno < gdbarch_num_regs (get_regcache_arch (regcache));
300 	   regno++)
301 	store_register (regcache, regno);
302     }
303   else
304     {
305       store_register (regcache, regno);
306     }
307 }
308 
309 /* Fill GDB's register array with the general-purpose register values
310    in *gregsetp.  */
311 
312 void
313 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
314 {
315   int i;
316   const greg_t *regp = (const elf_greg_t *) gregsetp;
317 
318   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
319     {
320       int regno = greg_map[i];
321       regcache_raw_supply (regcache, regno, regp);
322     }
323 }
324 
325 /* Fill register regno (if it is a general-purpose register) in
326    *gregsetp with the appropriate value from GDB's register array.
327    If regno is -1, do this for all registers.  */
328 
329 void
330 fill_gregset (const struct regcache *regcache,
331 	      gdb_gregset_t *gregsetp, int regno)
332 {
333   int i;
334 
335   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
336     {
337       int mregno = greg_map[i];
338 
339       if (regno == -1 || regno == mregno)
340 	{
341           regcache_raw_collect(regcache, mregno, &(*gregsetp)[i]);
342 	}
343     }
344 }
345 
346 /*  Given a pointer to a floating point register set in /proc format
347    (fpregset_t *), unpack the register contents and supply them as gdb's
348    idea of the current floating point register values.  */
349 
350 void
351 supply_fpregset (struct regcache *regcache, const gdb_fpregset_t *fpregsetp)
352 {
353   int regi;
354   const char *from;
355 
356   for (regi = 0; regi <= 31; regi++)
357     {
358       from = (const char *) &((*fpregsetp)[regi]);
359       regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM, from);
360       regcache_raw_supply (regcache, 2*regi + HPPA_FP0_REGNUM + 1, from + 4);
361     }
362 }
363 
364 /*  Given a pointer to a floating point register set in /proc format
365    (fpregset_t *), update the register specified by REGNO from gdb's idea
366    of the current floating point register set.  If REGNO is -1, update
367    them all.  */
368 
369 void
370 fill_fpregset (const struct regcache *regcache,
371 	       gdb_fpregset_t *fpregsetp, int regno)
372 {
373   int i;
374 
375   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
376    {
377       /* Gross.  fpregset_t is double, registers[x] has single
378 	 precision reg.  */
379       char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
380       if ((i - HPPA_FP0_REGNUM) & 1)
381 	to += 4;
382       regcache_raw_collect (regcache, i, to);
383    }
384 }
385 
386 void _initialize_hppa_linux_nat (void);
387 
388 void
389 _initialize_hppa_linux_nat (void)
390 {
391   struct target_ops *t;
392 
393   /* Fill in the generic GNU/Linux methods.  */
394   t = linux_target ();
395 
396   /* Add our register access methods.  */
397   t->to_fetch_registers = hppa_linux_fetch_inferior_registers;
398   t->to_store_registers = hppa_linux_store_inferior_registers;
399 
400   /* Register the target.  */
401   linux_nat_add_target (t);
402 }
403