db80cb264231f03aa02a6bb3d976b29c4191e33b
[deliverable/binutils-gdb.git] / gdb / arm-linux-nat.c
1 /* GNU/Linux on ARM native support.
2 Copyright 1999, 2000, 2001, 2002 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 "inferior.h"
23 #include "gdbcore.h"
24 #include "gdb_string.h"
25 #include "regcache.h"
26
27 #include "arm-tdep.h"
28
29 #include <sys/user.h>
30 #include <sys/ptrace.h>
31 #include <sys/utsname.h>
32 #include <sys/procfs.h>
33
34 /* Prototypes for supply_gregset etc. */
35 #include "gregset.h"
36
37 extern int arm_apcs_32;
38
39 #define typeNone 0x00
40 #define typeSingle 0x01
41 #define typeDouble 0x02
42 #define typeExtended 0x03
43 #define FPWORDS 28
44 #define ARM_CPSR_REGNUM 16
45
46 typedef union tagFPREG
47 {
48 unsigned int fSingle;
49 unsigned int fDouble[2];
50 unsigned int fExtended[3];
51 }
52 FPREG;
53
54 typedef struct tagFPA11
55 {
56 FPREG fpreg[8]; /* 8 floating point registers */
57 unsigned int fpsr; /* floating point status register */
58 unsigned int fpcr; /* floating point control register */
59 unsigned char fType[8]; /* type of floating point value held in
60 floating point registers. */
61 int initflag; /* NWFPE initialization flag. */
62 }
63 FPA11;
64
65 /* The following variables are used to determine the version of the
66 underlying GNU/Linux operating system. Examples:
67
68 GNU/Linux 2.0.35 GNU/Linux 2.2.12
69 os_version = 0x00020023 os_version = 0x0002020c
70 os_major = 2 os_major = 2
71 os_minor = 0 os_minor = 2
72 os_release = 35 os_release = 12
73
74 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
75
76 These are initialized using get_linux_version() from
77 _initialize_arm_linux_nat(). */
78
79 static unsigned int os_version, os_major, os_minor, os_release;
80
81 /* On GNU/Linux, threads are implemented as pseudo-processes, in which
82 case we may be tracing more than one process at a time. In that
83 case, inferior_ptid will contain the main process ID and the
84 individual thread (process) ID. get_thread_id () is used to get
85 the thread id if it's available, and the process id otherwise. */
86
87 int
88 get_thread_id (ptid_t ptid)
89 {
90 int tid = TIDGET (ptid);
91 if (0 == tid)
92 tid = PIDGET (ptid);
93 return tid;
94 }
95 #define GET_THREAD_ID(PTID) get_thread_id ((PTID));
96
97 static void
98 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
99 {
100 unsigned int mem[3];
101
102 mem[0] = fpa11->fpreg[fn].fSingle;
103 mem[1] = 0;
104 mem[2] = 0;
105 regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
106 }
107
108 static void
109 fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
110 {
111 unsigned int mem[3];
112
113 mem[0] = fpa11->fpreg[fn].fDouble[1];
114 mem[1] = fpa11->fpreg[fn].fDouble[0];
115 mem[2] = 0;
116 regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
117 }
118
119 static void
120 fetch_nwfpe_none (unsigned int fn)
121 {
122 unsigned int mem[3] =
123 {0, 0, 0};
124
125 regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
126 }
127
128 static void
129 fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
130 {
131 unsigned int mem[3];
132
133 mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
134 mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
135 mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
136 regcache_raw_supply (current_regcache, ARM_F0_REGNUM + fn, (char *) &mem[0]);
137 }
138
139 static void
140 fetch_nwfpe_register (int regno, FPA11 * fpa11)
141 {
142 int fn = regno - ARM_F0_REGNUM;
143
144 switch (fpa11->fType[fn])
145 {
146 case typeSingle:
147 fetch_nwfpe_single (fn, fpa11);
148 break;
149
150 case typeDouble:
151 fetch_nwfpe_double (fn, fpa11);
152 break;
153
154 case typeExtended:
155 fetch_nwfpe_extended (fn, fpa11);
156 break;
157
158 default:
159 fetch_nwfpe_none (fn);
160 }
161 }
162
163 static void
164 store_nwfpe_single (unsigned int fn, FPA11 *fpa11)
165 {
166 unsigned int mem[3];
167
168 regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
169 fpa11->fpreg[fn].fSingle = mem[0];
170 fpa11->fType[fn] = typeSingle;
171 }
172
173 static void
174 store_nwfpe_double (unsigned int fn, FPA11 *fpa11)
175 {
176 unsigned int mem[3];
177
178 regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
179 fpa11->fpreg[fn].fDouble[1] = mem[0];
180 fpa11->fpreg[fn].fDouble[0] = mem[1];
181 fpa11->fType[fn] = typeDouble;
182 }
183
184 void
185 store_nwfpe_extended (unsigned int fn, FPA11 *fpa11)
186 {
187 unsigned int mem[3];
188
189 regcache_collect (ARM_F0_REGNUM + fn, (char *) &mem[0]);
190 fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
191 fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
192 fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
193 fpa11->fType[fn] = typeDouble;
194 }
195
196 void
197 store_nwfpe_register (int regno, FPA11 * fpa11)
198 {
199 if (register_cached (regno))
200 {
201 unsigned int fn = regno - ARM_F0_REGNUM;
202 switch (fpa11->fType[fn])
203 {
204 case typeSingle:
205 store_nwfpe_single (fn, fpa11);
206 break;
207
208 case typeDouble:
209 store_nwfpe_double (fn, fpa11);
210 break;
211
212 case typeExtended:
213 store_nwfpe_extended (fn, fpa11);
214 break;
215 }
216 }
217 }
218
219
220 /* Get the value of a particular register from the floating point
221 state of the process and store it into regcache. */
222
223 static void
224 fetch_fpregister (int regno)
225 {
226 int ret, tid;
227 FPA11 fp;
228
229 /* Get the thread id for the ptrace call. */
230 tid = GET_THREAD_ID (inferior_ptid);
231
232 /* Read the floating point state. */
233 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
234 if (ret < 0)
235 {
236 warning ("Unable to fetch floating point register.");
237 return;
238 }
239
240 /* Fetch fpsr. */
241 if (ARM_FPS_REGNUM == regno)
242 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
243
244 /* Fetch the floating point register. */
245 if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
246 {
247 int fn = regno - ARM_F0_REGNUM;
248
249 switch (fp.fType[fn])
250 {
251 case typeSingle:
252 fetch_nwfpe_single (fn, &fp);
253 break;
254
255 case typeDouble:
256 fetch_nwfpe_double (fn, &fp);
257 break;
258
259 case typeExtended:
260 fetch_nwfpe_extended (fn, &fp);
261 break;
262
263 default:
264 fetch_nwfpe_none (fn);
265 }
266 }
267 }
268
269 /* Get the whole floating point state of the process and store it
270 into regcache. */
271
272 static void
273 fetch_fpregs (void)
274 {
275 int ret, regno, tid;
276 FPA11 fp;
277
278 /* Get the thread id for the ptrace call. */
279 tid = GET_THREAD_ID (inferior_ptid);
280
281 /* Read the floating point state. */
282 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
283 if (ret < 0)
284 {
285 warning ("Unable to fetch the floating point registers.");
286 return;
287 }
288
289 /* Fetch fpsr. */
290 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp.fpsr);
291
292 /* Fetch the floating point registers. */
293 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
294 {
295 int fn = regno - ARM_F0_REGNUM;
296
297 switch (fp.fType[fn])
298 {
299 case typeSingle:
300 fetch_nwfpe_single (fn, &fp);
301 break;
302
303 case typeDouble:
304 fetch_nwfpe_double (fn, &fp);
305 break;
306
307 case typeExtended:
308 fetch_nwfpe_extended (fn, &fp);
309 break;
310
311 default:
312 fetch_nwfpe_none (fn);
313 }
314 }
315 }
316
317 /* Save a particular register into the floating point state of the
318 process using the contents from regcache. */
319
320 static void
321 store_fpregister (int regno)
322 {
323 int ret, tid;
324 FPA11 fp;
325
326 /* Get the thread id for the ptrace call. */
327 tid = GET_THREAD_ID (inferior_ptid);
328
329 /* Read the floating point state. */
330 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
331 if (ret < 0)
332 {
333 warning ("Unable to fetch the floating point registers.");
334 return;
335 }
336
337 /* Store fpsr. */
338 if (ARM_FPS_REGNUM == regno && register_cached (ARM_FPS_REGNUM))
339 regcache_collect (ARM_FPS_REGNUM, (char *) &fp.fpsr);
340
341 /* Store the floating point register. */
342 if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
343 {
344 store_nwfpe_register (regno, &fp);
345 }
346
347 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
348 if (ret < 0)
349 {
350 warning ("Unable to store floating point register.");
351 return;
352 }
353 }
354
355 /* Save the whole floating point state of the process using
356 the contents from regcache. */
357
358 static void
359 store_fpregs (void)
360 {
361 int ret, regno, tid;
362 FPA11 fp;
363
364 /* Get the thread id for the ptrace call. */
365 tid = GET_THREAD_ID (inferior_ptid);
366
367 /* Read the floating point state. */
368 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
369 if (ret < 0)
370 {
371 warning ("Unable to fetch the floating point registers.");
372 return;
373 }
374
375 /* Store fpsr. */
376 if (register_cached (ARM_FPS_REGNUM))
377 regcache_collect (ARM_FPS_REGNUM, (char *) &fp.fpsr);
378
379 /* Store the floating point registers. */
380 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
381 {
382 fetch_nwfpe_register (regno, &fp);
383 }
384
385 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
386 if (ret < 0)
387 {
388 warning ("Unable to store floating point registers.");
389 return;
390 }
391 }
392
393 /* Fetch a general register of the process and store into
394 regcache. */
395
396 static void
397 fetch_register (int regno)
398 {
399 int ret, tid;
400 elf_gregset_t regs;
401
402 /* Get the thread id for the ptrace call. */
403 tid = GET_THREAD_ID (inferior_ptid);
404
405 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
406 if (ret < 0)
407 {
408 warning ("Unable to fetch general register.");
409 return;
410 }
411
412 if (regno >= ARM_A1_REGNUM && regno < ARM_PC_REGNUM)
413 regcache_raw_supply (current_regcache, regno, (char *) &regs[regno]);
414
415 if (ARM_PS_REGNUM == regno)
416 {
417 if (arm_apcs_32)
418 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
419 (char *) &regs[ARM_CPSR_REGNUM]);
420 else
421 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
422 (char *) &regs[ARM_PC_REGNUM]);
423 }
424
425 if (ARM_PC_REGNUM == regno)
426 {
427 regs[ARM_PC_REGNUM] = ADDR_BITS_REMOVE (regs[ARM_PC_REGNUM]);
428 regcache_raw_supply (current_regcache, ARM_PC_REGNUM,
429 (char *) &regs[ARM_PC_REGNUM]);
430 }
431 }
432
433 /* Fetch all general registers of the process and store into
434 regcache. */
435
436 static void
437 fetch_regs (void)
438 {
439 int ret, regno, tid;
440 elf_gregset_t regs;
441
442 /* Get the thread id for the ptrace call. */
443 tid = GET_THREAD_ID (inferior_ptid);
444
445 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
446 if (ret < 0)
447 {
448 warning ("Unable to fetch general registers.");
449 return;
450 }
451
452 for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
453 regcache_raw_supply (current_regcache, regno, (char *) &regs[regno]);
454
455 if (arm_apcs_32)
456 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
457 (char *) &regs[ARM_CPSR_REGNUM]);
458 else
459 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
460 (char *) &regs[ARM_PC_REGNUM]);
461
462 regs[ARM_PC_REGNUM] = ADDR_BITS_REMOVE (regs[ARM_PC_REGNUM]);
463 regcache_raw_supply (current_regcache, ARM_PC_REGNUM,
464 (char *) &regs[ARM_PC_REGNUM]);
465 }
466
467 /* Store all general registers of the process from the values in
468 regcache. */
469
470 static void
471 store_register (int regno)
472 {
473 int ret, tid;
474 elf_gregset_t regs;
475
476 if (!register_cached (regno))
477 return;
478
479 /* Get the thread id for the ptrace call. */
480 tid = GET_THREAD_ID (inferior_ptid);
481
482 /* Get the general registers from the process. */
483 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
484 if (ret < 0)
485 {
486 warning ("Unable to fetch general registers.");
487 return;
488 }
489
490 if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
491 regcache_collect (regno, (char *) &regs[regno]);
492
493 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
494 if (ret < 0)
495 {
496 warning ("Unable to store general register.");
497 return;
498 }
499 }
500
501 static void
502 store_regs (void)
503 {
504 int ret, regno, tid;
505 elf_gregset_t regs;
506
507 /* Get the thread id for the ptrace call. */
508 tid = GET_THREAD_ID (inferior_ptid);
509
510 /* Fetch the general registers. */
511 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
512 if (ret < 0)
513 {
514 warning ("Unable to fetch general registers.");
515 return;
516 }
517
518 for (regno = ARM_A1_REGNUM; regno <= ARM_PC_REGNUM; regno++)
519 {
520 if (register_cached (regno))
521 regcache_collect (regno, (char *) &regs[regno]);
522 }
523
524 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
525
526 if (ret < 0)
527 {
528 warning ("Unable to store general registers.");
529 return;
530 }
531 }
532
533 /* Fetch registers from the child process. Fetch all registers if
534 regno == -1, otherwise fetch all general registers or all floating
535 point registers depending upon the value of regno. */
536
537 void
538 fetch_inferior_registers (int regno)
539 {
540 if (-1 == regno)
541 {
542 fetch_regs ();
543 fetch_fpregs ();
544 }
545 else
546 {
547 if (regno < ARM_F0_REGNUM || regno > ARM_FPS_REGNUM)
548 fetch_register (regno);
549
550 if (regno >= ARM_F0_REGNUM && regno <= ARM_FPS_REGNUM)
551 fetch_fpregister (regno);
552 }
553 }
554
555 /* Store registers back into the inferior. Store all registers if
556 regno == -1, otherwise store all general registers or all floating
557 point registers depending upon the value of regno. */
558
559 void
560 store_inferior_registers (int regno)
561 {
562 if (-1 == regno)
563 {
564 store_regs ();
565 store_fpregs ();
566 }
567 else
568 {
569 if ((regno < ARM_F0_REGNUM) || (regno > ARM_FPS_REGNUM))
570 store_register (regno);
571
572 if ((regno >= ARM_F0_REGNUM) && (regno <= ARM_FPS_REGNUM))
573 store_fpregister (regno);
574 }
575 }
576
577 /* Fill register regno (if it is a general-purpose register) in
578 *gregsetp with the appropriate value from GDB's register array.
579 If regno is -1, do this for all registers. */
580
581 void
582 fill_gregset (gdb_gregset_t *gregsetp, int regno)
583 {
584 if (-1 == regno)
585 {
586 int regnum;
587 for (regnum = ARM_A1_REGNUM; regnum <= ARM_PC_REGNUM; regnum++)
588 regcache_collect (regnum, (char *) &(*gregsetp)[regnum]);
589 }
590 else if (regno >= ARM_A1_REGNUM && regno <= ARM_PC_REGNUM)
591 regcache_collect (regno, (char *) &(*gregsetp)[regno]);
592
593 if (ARM_PS_REGNUM == regno || -1 == regno)
594 {
595 if (arm_apcs_32)
596 regcache_collect (ARM_PS_REGNUM,
597 (char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
598 else
599 regcache_collect (ARM_PC_REGNUM,
600 (char *) &(*gregsetp)[ARM_PC_REGNUM]);
601 }
602 }
603
604 /* Fill GDB's register array with the general-purpose register values
605 in *gregsetp. */
606
607 void
608 supply_gregset (gdb_gregset_t *gregsetp)
609 {
610 int regno, reg_pc;
611
612 for (regno = ARM_A1_REGNUM; regno < ARM_PC_REGNUM; regno++)
613 regcache_raw_supply (current_regcache, regno,
614 (char *) &(*gregsetp)[regno]);
615
616 if (arm_apcs_32)
617 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
618 (char *) &(*gregsetp)[ARM_CPSR_REGNUM]);
619 else
620 regcache_raw_supply (current_regcache, ARM_PS_REGNUM,
621 (char *) &(*gregsetp)[ARM_PC_REGNUM]);
622
623 reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[ARM_PC_REGNUM]);
624 regcache_raw_supply (current_regcache, ARM_PC_REGNUM, (char *) &reg_pc);
625 }
626
627 /* Fill register regno (if it is a floating-point register) in
628 *fpregsetp with the appropriate value from GDB's register array.
629 If regno is -1, do this for all registers. */
630
631 void
632 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
633 {
634 FPA11 *fp = (FPA11 *) fpregsetp;
635
636 if (-1 == regno)
637 {
638 int regnum;
639 for (regnum = ARM_F0_REGNUM; regnum <= ARM_F7_REGNUM; regnum++)
640 store_nwfpe_register (regnum, fp);
641 }
642 else if (regno >= ARM_F0_REGNUM && regno <= ARM_F7_REGNUM)
643 {
644 store_nwfpe_register (regno, fp);
645 return;
646 }
647
648 /* Store fpsr. */
649 if (ARM_FPS_REGNUM == regno || -1 == regno)
650 regcache_collect (ARM_FPS_REGNUM, (char *) &fp->fpsr);
651 }
652
653 /* Fill GDB's register array with the floating-point register values
654 in *fpregsetp. */
655
656 void
657 supply_fpregset (gdb_fpregset_t *fpregsetp)
658 {
659 int regno;
660 FPA11 *fp = (FPA11 *) fpregsetp;
661
662 /* Fetch fpsr. */
663 regcache_raw_supply (current_regcache, ARM_FPS_REGNUM, (char *) &fp->fpsr);
664
665 /* Fetch the floating point registers. */
666 for (regno = ARM_F0_REGNUM; regno <= ARM_F7_REGNUM; regno++)
667 {
668 fetch_nwfpe_register (regno, fp);
669 }
670 }
671
672 int
673 arm_linux_kernel_u_size (void)
674 {
675 return (sizeof (struct user));
676 }
677
678 static unsigned int
679 get_linux_version (unsigned int *vmajor,
680 unsigned int *vminor,
681 unsigned int *vrelease)
682 {
683 struct utsname info;
684 char *pmajor, *pminor, *prelease, *tail;
685
686 if (-1 == uname (&info))
687 {
688 warning ("Unable to determine GNU/Linux version.");
689 return -1;
690 }
691
692 pmajor = strtok (info.release, ".");
693 pminor = strtok (NULL, ".");
694 prelease = strtok (NULL, ".");
695
696 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
697 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
698 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
699
700 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
701 }
702
703 void
704 _initialize_arm_linux_nat (void)
705 {
706 os_version = get_linux_version (&os_major, &os_minor, &os_release);
707 }
This page took 0.045693 seconds and 4 git commands to generate.