xref: /openbsd-src/gnu/usr.bin/binutils/gdb/hppa-linux-nat.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1*11efff7fSkettenis /* Functions specific to running GDB native on HPPA running GNU/Linux.
2*11efff7fSkettenis 
3*11efff7fSkettenis    Copyright 2004 Free Software Foundation, Inc.
4*11efff7fSkettenis 
5*11efff7fSkettenis    This file is part of GDB.
6*11efff7fSkettenis 
7*11efff7fSkettenis    This program is free software; you can redistribute it and/or modify
8*11efff7fSkettenis    it under the terms of the GNU General Public License as published by
9*11efff7fSkettenis    the Free Software Foundation; either version 2 of the License, or
10*11efff7fSkettenis    (at your option) any later version.
11*11efff7fSkettenis 
12*11efff7fSkettenis    This program is distributed in the hope that it will be useful,
13*11efff7fSkettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*11efff7fSkettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*11efff7fSkettenis    GNU General Public License for more details.
16*11efff7fSkettenis 
17*11efff7fSkettenis    You should have received a copy of the GNU General Public License
18*11efff7fSkettenis    along with this program; if not, write to the Free Software
19*11efff7fSkettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*11efff7fSkettenis    Boston, MA 02111-1307, USA.  */
21*11efff7fSkettenis 
22*11efff7fSkettenis #include "defs.h"
23*11efff7fSkettenis #include "gdbcore.h"
24*11efff7fSkettenis #include "regcache.h"
25*11efff7fSkettenis #include "gdb_string.h"
26*11efff7fSkettenis #include "inferior.h"
27*11efff7fSkettenis 
28*11efff7fSkettenis #include <sys/procfs.h>
29*11efff7fSkettenis #include <sys/ptrace.h>
30*11efff7fSkettenis #include <linux/version.h>
31*11efff7fSkettenis 
32*11efff7fSkettenis #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,43)
33*11efff7fSkettenis #include <asm/offset.h>
34*11efff7fSkettenis #else
35*11efff7fSkettenis #include <asm/offsets.h>
36*11efff7fSkettenis #endif
37*11efff7fSkettenis 
38*11efff7fSkettenis #include "hppa-tdep.h"
39*11efff7fSkettenis 
40*11efff7fSkettenis /* Prototypes for supply_gregset etc. */
41*11efff7fSkettenis #include "gregset.h"
42*11efff7fSkettenis 
43*11efff7fSkettenis /* These must match the order of the register names.
44*11efff7fSkettenis 
45*11efff7fSkettenis    Some sort of lookup table is needed because the offsets associated
46*11efff7fSkettenis    with the registers are all over the board.  */
47*11efff7fSkettenis 
48*11efff7fSkettenis static const int u_offsets[] =
49*11efff7fSkettenis   {
50*11efff7fSkettenis     /* general registers */
51*11efff7fSkettenis     -1,
52*11efff7fSkettenis     PT_GR1,
53*11efff7fSkettenis     PT_GR2,
54*11efff7fSkettenis     PT_GR3,
55*11efff7fSkettenis     PT_GR4,
56*11efff7fSkettenis     PT_GR5,
57*11efff7fSkettenis     PT_GR6,
58*11efff7fSkettenis     PT_GR7,
59*11efff7fSkettenis     PT_GR8,
60*11efff7fSkettenis     PT_GR9,
61*11efff7fSkettenis     PT_GR10,
62*11efff7fSkettenis     PT_GR11,
63*11efff7fSkettenis     PT_GR12,
64*11efff7fSkettenis     PT_GR13,
65*11efff7fSkettenis     PT_GR14,
66*11efff7fSkettenis     PT_GR15,
67*11efff7fSkettenis     PT_GR16,
68*11efff7fSkettenis     PT_GR17,
69*11efff7fSkettenis     PT_GR18,
70*11efff7fSkettenis     PT_GR19,
71*11efff7fSkettenis     PT_GR20,
72*11efff7fSkettenis     PT_GR21,
73*11efff7fSkettenis     PT_GR22,
74*11efff7fSkettenis     PT_GR23,
75*11efff7fSkettenis     PT_GR24,
76*11efff7fSkettenis     PT_GR25,
77*11efff7fSkettenis     PT_GR26,
78*11efff7fSkettenis     PT_GR27,
79*11efff7fSkettenis     PT_GR28,
80*11efff7fSkettenis     PT_GR29,
81*11efff7fSkettenis     PT_GR30,
82*11efff7fSkettenis     PT_GR31,
83*11efff7fSkettenis 
84*11efff7fSkettenis     PT_SAR,
85*11efff7fSkettenis     PT_IAOQ0,
86*11efff7fSkettenis     PT_IASQ0,
87*11efff7fSkettenis     PT_IAOQ1,
88*11efff7fSkettenis     PT_IASQ1,
89*11efff7fSkettenis     -1, /* eiem */
90*11efff7fSkettenis     PT_IIR,
91*11efff7fSkettenis     PT_ISR,
92*11efff7fSkettenis     PT_IOR,
93*11efff7fSkettenis     PT_PSW,
94*11efff7fSkettenis     -1, /* goto */
95*11efff7fSkettenis 
96*11efff7fSkettenis     PT_SR4,
97*11efff7fSkettenis     PT_SR0,
98*11efff7fSkettenis     PT_SR1,
99*11efff7fSkettenis     PT_SR2,
100*11efff7fSkettenis     PT_SR3,
101*11efff7fSkettenis     PT_SR5,
102*11efff7fSkettenis     PT_SR6,
103*11efff7fSkettenis     PT_SR7,
104*11efff7fSkettenis 
105*11efff7fSkettenis     -1, /* cr0 */
106*11efff7fSkettenis     -1, /* pid0 */
107*11efff7fSkettenis     -1, /* pid1 */
108*11efff7fSkettenis     -1, /* ccr */
109*11efff7fSkettenis     -1, /* pid2 */
110*11efff7fSkettenis     -1, /* pid3 */
111*11efff7fSkettenis     -1, /* cr24 */
112*11efff7fSkettenis     -1, /* cr25 */
113*11efff7fSkettenis     -1, /* cr26 */
114*11efff7fSkettenis     PT_CR27,
115*11efff7fSkettenis     -1, /* cr28 */
116*11efff7fSkettenis     -1, /* cr29 */
117*11efff7fSkettenis     -1, /* cr30 */
118*11efff7fSkettenis 
119*11efff7fSkettenis     /* Floating point regs.  */
120*11efff7fSkettenis     PT_FR0,  PT_FR0 + 4,
121*11efff7fSkettenis     PT_FR1,  PT_FR1 + 4,
122*11efff7fSkettenis     PT_FR2,  PT_FR2 + 4,
123*11efff7fSkettenis     PT_FR3,  PT_FR3 + 4,
124*11efff7fSkettenis     PT_FR4,  PT_FR4 + 4,
125*11efff7fSkettenis     PT_FR5,  PT_FR5 + 4,
126*11efff7fSkettenis     PT_FR6,  PT_FR6 + 4,
127*11efff7fSkettenis     PT_FR7,  PT_FR7 + 4,
128*11efff7fSkettenis     PT_FR8,  PT_FR8 + 4,
129*11efff7fSkettenis     PT_FR9,  PT_FR9 + 4,
130*11efff7fSkettenis     PT_FR10, PT_FR10 + 4,
131*11efff7fSkettenis     PT_FR11, PT_FR11 + 4,
132*11efff7fSkettenis     PT_FR12, PT_FR12 + 4,
133*11efff7fSkettenis     PT_FR13, PT_FR13 + 4,
134*11efff7fSkettenis     PT_FR14, PT_FR14 + 4,
135*11efff7fSkettenis     PT_FR15, PT_FR15 + 4,
136*11efff7fSkettenis     PT_FR16, PT_FR16 + 4,
137*11efff7fSkettenis     PT_FR17, PT_FR17 + 4,
138*11efff7fSkettenis     PT_FR18, PT_FR18 + 4,
139*11efff7fSkettenis     PT_FR19, PT_FR19 + 4,
140*11efff7fSkettenis     PT_FR20, PT_FR20 + 4,
141*11efff7fSkettenis     PT_FR21, PT_FR21 + 4,
142*11efff7fSkettenis     PT_FR22, PT_FR22 + 4,
143*11efff7fSkettenis     PT_FR23, PT_FR23 + 4,
144*11efff7fSkettenis     PT_FR24, PT_FR24 + 4,
145*11efff7fSkettenis     PT_FR25, PT_FR25 + 4,
146*11efff7fSkettenis     PT_FR26, PT_FR26 + 4,
147*11efff7fSkettenis     PT_FR27, PT_FR27 + 4,
148*11efff7fSkettenis     PT_FR28, PT_FR28 + 4,
149*11efff7fSkettenis     PT_FR29, PT_FR29 + 4,
150*11efff7fSkettenis     PT_FR30, PT_FR30 + 4,
151*11efff7fSkettenis     PT_FR31, PT_FR31 + 4,
152*11efff7fSkettenis   };
153*11efff7fSkettenis 
154*11efff7fSkettenis CORE_ADDR
register_addr(int regno,CORE_ADDR blockend)155*11efff7fSkettenis register_addr (int regno, CORE_ADDR blockend)
156*11efff7fSkettenis {
157*11efff7fSkettenis   CORE_ADDR addr;
158*11efff7fSkettenis 
159*11efff7fSkettenis   if ((unsigned) regno >= NUM_REGS)
160*11efff7fSkettenis     error ("Invalid register number %d.", regno);
161*11efff7fSkettenis 
162*11efff7fSkettenis   if (u_offsets[regno] == -1)
163*11efff7fSkettenis     addr = 0;
164*11efff7fSkettenis   else
165*11efff7fSkettenis     {
166*11efff7fSkettenis       addr = (CORE_ADDR) u_offsets[regno];
167*11efff7fSkettenis     }
168*11efff7fSkettenis 
169*11efff7fSkettenis   return addr;
170*11efff7fSkettenis }
171*11efff7fSkettenis 
172*11efff7fSkettenis /*
173*11efff7fSkettenis  * Registers saved in a coredump:
174*11efff7fSkettenis  * gr0..gr31
175*11efff7fSkettenis  * sr0..sr7
176*11efff7fSkettenis  * iaoq0..iaoq1
177*11efff7fSkettenis  * iasq0..iasq1
178*11efff7fSkettenis  * sar, iir, isr, ior, ipsw
179*11efff7fSkettenis  * cr0, cr24..cr31
180*11efff7fSkettenis  * cr8,9,12,13
181*11efff7fSkettenis  * cr10, cr15
182*11efff7fSkettenis  */
183*11efff7fSkettenis #define GR_REGNUM(_n)	(HPPA_R0_REGNUM+_n)
184*11efff7fSkettenis #define TR_REGNUM(_n)	(HPPA_TR0_REGNUM+_n)
185*11efff7fSkettenis static const int greg_map[] =
186*11efff7fSkettenis   {
187*11efff7fSkettenis     GR_REGNUM(0), GR_REGNUM(1), GR_REGNUM(2), GR_REGNUM(3),
188*11efff7fSkettenis     GR_REGNUM(4), GR_REGNUM(5), GR_REGNUM(6), GR_REGNUM(7),
189*11efff7fSkettenis     GR_REGNUM(8), GR_REGNUM(9), GR_REGNUM(10), GR_REGNUM(11),
190*11efff7fSkettenis     GR_REGNUM(12), GR_REGNUM(13), GR_REGNUM(14), GR_REGNUM(15),
191*11efff7fSkettenis     GR_REGNUM(16), GR_REGNUM(17), GR_REGNUM(18), GR_REGNUM(19),
192*11efff7fSkettenis     GR_REGNUM(20), GR_REGNUM(21), GR_REGNUM(22), GR_REGNUM(23),
193*11efff7fSkettenis     GR_REGNUM(24), GR_REGNUM(25), GR_REGNUM(26), GR_REGNUM(27),
194*11efff7fSkettenis     GR_REGNUM(28), GR_REGNUM(29), GR_REGNUM(30), GR_REGNUM(31),
195*11efff7fSkettenis 
196*11efff7fSkettenis     HPPA_SR4_REGNUM+1, HPPA_SR4_REGNUM+2, HPPA_SR4_REGNUM+3, HPPA_SR4_REGNUM+4,
197*11efff7fSkettenis     HPPA_SR4_REGNUM, HPPA_SR4_REGNUM+5, HPPA_SR4_REGNUM+6, HPPA_SR4_REGNUM+7,
198*11efff7fSkettenis 
199*11efff7fSkettenis     HPPA_PCOQ_HEAD_REGNUM, HPPA_PCOQ_TAIL_REGNUM,
200*11efff7fSkettenis     HPPA_PCSQ_HEAD_REGNUM, HPPA_PCSQ_TAIL_REGNUM,
201*11efff7fSkettenis 
202*11efff7fSkettenis     HPPA_SAR_REGNUM, HPPA_IIR_REGNUM, HPPA_ISR_REGNUM, HPPA_IOR_REGNUM,
203*11efff7fSkettenis     HPPA_IPSW_REGNUM, HPPA_RCR_REGNUM,
204*11efff7fSkettenis 
205*11efff7fSkettenis     TR_REGNUM(0), TR_REGNUM(1), TR_REGNUM(2), TR_REGNUM(3),
206*11efff7fSkettenis     TR_REGNUM(4), TR_REGNUM(5), TR_REGNUM(6), TR_REGNUM(7),
207*11efff7fSkettenis 
208*11efff7fSkettenis     HPPA_PID0_REGNUM, HPPA_PID1_REGNUM, HPPA_PID2_REGNUM, HPPA_PID3_REGNUM,
209*11efff7fSkettenis     HPPA_CCR_REGNUM, HPPA_EIEM_REGNUM,
210*11efff7fSkettenis   };
211*11efff7fSkettenis 
212*11efff7fSkettenis 
213*11efff7fSkettenis 
214*11efff7fSkettenis /* Fetch one register.  */
215*11efff7fSkettenis 
216*11efff7fSkettenis static void
fetch_register(int regno)217*11efff7fSkettenis fetch_register (int regno)
218*11efff7fSkettenis {
219*11efff7fSkettenis   int tid;
220*11efff7fSkettenis   int val;
221*11efff7fSkettenis 
222*11efff7fSkettenis   if (CANNOT_FETCH_REGISTER (regno))
223*11efff7fSkettenis     {
224*11efff7fSkettenis       regcache_raw_supply (current_regcache, regno, NULL);
225*11efff7fSkettenis       return;
226*11efff7fSkettenis     }
227*11efff7fSkettenis 
228*11efff7fSkettenis   /* GNU/Linux LWP ID's are process ID's.  */
229*11efff7fSkettenis   tid = TIDGET (inferior_ptid);
230*11efff7fSkettenis   if (tid == 0)
231*11efff7fSkettenis     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
232*11efff7fSkettenis 
233*11efff7fSkettenis   errno = 0;
234*11efff7fSkettenis   val = ptrace (PTRACE_PEEKUSER, tid, register_addr (regno, 0), 0);
235*11efff7fSkettenis   if (errno != 0)
236*11efff7fSkettenis     error ("Couldn't read register %s (#%d): %s.", REGISTER_NAME (regno),
237*11efff7fSkettenis 	   regno, safe_strerror (errno));
238*11efff7fSkettenis 
239*11efff7fSkettenis   regcache_raw_supply (current_regcache, regno, &val);
240*11efff7fSkettenis }
241*11efff7fSkettenis 
242*11efff7fSkettenis /* Store one register. */
243*11efff7fSkettenis 
244*11efff7fSkettenis static void
store_register(int regno)245*11efff7fSkettenis store_register (int regno)
246*11efff7fSkettenis {
247*11efff7fSkettenis   int tid;
248*11efff7fSkettenis   int val;
249*11efff7fSkettenis 
250*11efff7fSkettenis   if (CANNOT_STORE_REGISTER (regno))
251*11efff7fSkettenis     return;
252*11efff7fSkettenis 
253*11efff7fSkettenis   /* GNU/Linux LWP ID's are process ID's.  */
254*11efff7fSkettenis   tid = TIDGET (inferior_ptid);
255*11efff7fSkettenis   if (tid == 0)
256*11efff7fSkettenis     tid = PIDGET (inferior_ptid); /* Not a threaded program.  */
257*11efff7fSkettenis 
258*11efff7fSkettenis   errno = 0;
259*11efff7fSkettenis   regcache_raw_collect (current_regcache, regno, &val);
260*11efff7fSkettenis   ptrace (PTRACE_POKEUSER, tid, register_addr (regno, 0), val);
261*11efff7fSkettenis   if (errno != 0)
262*11efff7fSkettenis     error ("Couldn't write register %s (#%d): %s.", REGISTER_NAME (regno),
263*11efff7fSkettenis 	   regno, safe_strerror (errno));
264*11efff7fSkettenis }
265*11efff7fSkettenis 
266*11efff7fSkettenis /* Fetch registers from the child process.  Fetch all registers if
267*11efff7fSkettenis    regno == -1, otherwise fetch all general registers or all floating
268*11efff7fSkettenis    point registers depending upon the value of regno.  */
269*11efff7fSkettenis 
270*11efff7fSkettenis void
fetch_inferior_registers(int regno)271*11efff7fSkettenis fetch_inferior_registers (int regno)
272*11efff7fSkettenis {
273*11efff7fSkettenis   if (-1 == regno)
274*11efff7fSkettenis     {
275*11efff7fSkettenis       for (regno = 0; regno < NUM_REGS; regno++)
276*11efff7fSkettenis         fetch_register (regno);
277*11efff7fSkettenis     }
278*11efff7fSkettenis   else
279*11efff7fSkettenis     {
280*11efff7fSkettenis       fetch_register (regno);
281*11efff7fSkettenis     }
282*11efff7fSkettenis }
283*11efff7fSkettenis 
284*11efff7fSkettenis /* Store registers back into the inferior.  Store all registers if
285*11efff7fSkettenis    regno == -1, otherwise store all general registers or all floating
286*11efff7fSkettenis    point registers depending upon the value of regno.  */
287*11efff7fSkettenis 
288*11efff7fSkettenis void
store_inferior_registers(int regno)289*11efff7fSkettenis store_inferior_registers (int regno)
290*11efff7fSkettenis {
291*11efff7fSkettenis   if (-1 == regno)
292*11efff7fSkettenis     {
293*11efff7fSkettenis       for (regno = 0; regno < NUM_REGS; regno++)
294*11efff7fSkettenis 	store_register (regno);
295*11efff7fSkettenis     }
296*11efff7fSkettenis   else
297*11efff7fSkettenis     {
298*11efff7fSkettenis       store_register (regno);
299*11efff7fSkettenis     }
300*11efff7fSkettenis }
301*11efff7fSkettenis 
302*11efff7fSkettenis /* Fill GDB's register array with the general-purpose register values
303*11efff7fSkettenis    in *gregsetp.  */
304*11efff7fSkettenis 
305*11efff7fSkettenis void
supply_gregset(gdb_gregset_t * gregsetp)306*11efff7fSkettenis supply_gregset (gdb_gregset_t *gregsetp)
307*11efff7fSkettenis {
308*11efff7fSkettenis   int i;
309*11efff7fSkettenis   greg_t *regp = (elf_greg_t *) gregsetp;
310*11efff7fSkettenis 
311*11efff7fSkettenis   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++, regp++)
312*11efff7fSkettenis     {
313*11efff7fSkettenis       int regno = greg_map[i];
314*11efff7fSkettenis       regcache_raw_supply (current_regcache, regno, regp);
315*11efff7fSkettenis     }
316*11efff7fSkettenis }
317*11efff7fSkettenis 
318*11efff7fSkettenis /* Fill register regno (if it is a general-purpose register) in
319*11efff7fSkettenis    *gregsetp with the appropriate value from GDB's register array.
320*11efff7fSkettenis    If regno is -1, do this for all registers.  */
321*11efff7fSkettenis 
322*11efff7fSkettenis void
fill_gregset(gdb_gregset_t * gregsetp,int regno)323*11efff7fSkettenis fill_gregset (gdb_gregset_t *gregsetp, int regno)
324*11efff7fSkettenis {
325*11efff7fSkettenis   int i;
326*11efff7fSkettenis 
327*11efff7fSkettenis   for (i = 0; i < sizeof (greg_map) / sizeof (greg_map[0]); i++)
328*11efff7fSkettenis     {
329*11efff7fSkettenis       int mregno = greg_map[i];
330*11efff7fSkettenis 
331*11efff7fSkettenis       if (regno == -1 || regno == mregno)
332*11efff7fSkettenis 	{
333*11efff7fSkettenis           regcache_raw_collect(current_regcache, mregno, &(*gregsetp)[i]);
334*11efff7fSkettenis 	}
335*11efff7fSkettenis     }
336*11efff7fSkettenis }
337*11efff7fSkettenis 
338*11efff7fSkettenis /*  Given a pointer to a floating point register set in /proc format
339*11efff7fSkettenis    (fpregset_t *), unpack the register contents and supply them as gdb's
340*11efff7fSkettenis    idea of the current floating point register values. */
341*11efff7fSkettenis 
342*11efff7fSkettenis void
supply_fpregset(gdb_fpregset_t * fpregsetp)343*11efff7fSkettenis supply_fpregset (gdb_fpregset_t *fpregsetp)
344*11efff7fSkettenis {
345*11efff7fSkettenis   int regi;
346*11efff7fSkettenis   char *from;
347*11efff7fSkettenis 
348*11efff7fSkettenis   for (regi = 0; regi <= 31; regi++)
349*11efff7fSkettenis     {
350*11efff7fSkettenis       from = (char *) &((*fpregsetp)[regi]);
351*11efff7fSkettenis       regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM, from);
352*11efff7fSkettenis       regcache_raw_supply (current_regcache, 2*regi + HPPA_FP0_REGNUM + 1,
353*11efff7fSkettenis 			   from + 4);
354*11efff7fSkettenis     }
355*11efff7fSkettenis }
356*11efff7fSkettenis 
357*11efff7fSkettenis /*  Given a pointer to a floating point register set in /proc format
358*11efff7fSkettenis    (fpregset_t *), update the register specified by REGNO from gdb's idea
359*11efff7fSkettenis    of the current floating point register set.  If REGNO is -1, update
360*11efff7fSkettenis    them all. */
361*11efff7fSkettenis 
362*11efff7fSkettenis void
fill_fpregset(gdb_fpregset_t * fpregsetp,int regno)363*11efff7fSkettenis fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
364*11efff7fSkettenis {
365*11efff7fSkettenis   int i;
366*11efff7fSkettenis 
367*11efff7fSkettenis   for (i = HPPA_FP0_REGNUM; i < HPPA_FP0_REGNUM + 32 * 2; i++)
368*11efff7fSkettenis    {
369*11efff7fSkettenis       /* Gross.  fpregset_t is double, registers[x] has single
370*11efff7fSkettenis 	 precision reg.  */
371*11efff7fSkettenis       char *to = (char *) &((*fpregsetp)[(i - HPPA_FP0_REGNUM) / 2]);
372*11efff7fSkettenis       if ((i - HPPA_FP0_REGNUM) & 1)
373*11efff7fSkettenis 	to += 4;
374*11efff7fSkettenis       regcache_raw_collect (current_regcache, i, to);
375*11efff7fSkettenis    }
376*11efff7fSkettenis }
377