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