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