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