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