5d1487e934efaaad136c4204113ac925847f58a3
[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_pid 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 (int inferior_pid)
93 {
94 int tid = TIDGET (inferior_pid);
95 if (0 == tid) tid = inferior_pid;
96 return tid;
97 }
98 #define GET_THREAD_ID(PID) get_thread_id ((PID));
99
100 static void
101 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
102 {
103 unsigned int mem[3];
104
105 mem[0] = fpa11->fpreg[fn].fSingle;
106 mem[1] = 0;
107 mem[2] = 0;
108 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
109 }
110
111 static void
112 fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
113 {
114 unsigned int mem[3];
115
116 mem[0] = fpa11->fpreg[fn].fDouble[1];
117 mem[1] = fpa11->fpreg[fn].fDouble[0];
118 mem[2] = 0;
119 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
120 }
121
122 static void
123 fetch_nwfpe_none (unsigned int fn)
124 {
125 unsigned int mem[3] =
126 {0, 0, 0};
127
128 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
129 }
130
131 static void
132 fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
133 {
134 unsigned int mem[3];
135
136 mem[0] = fpa11->fpreg[fn].fExtended[0]; /* sign & exponent */
137 mem[1] = fpa11->fpreg[fn].fExtended[2]; /* ls bits */
138 mem[2] = fpa11->fpreg[fn].fExtended[1]; /* ms bits */
139 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
140 }
141
142 static void
143 fetch_nwfpe_register (int regno, FPA11 * fpa11)
144 {
145 int fn = regno - F0_REGNUM;
146
147 switch (fpa11->fType[fn])
148 {
149 case typeSingle:
150 fetch_nwfpe_single (fn, fpa11);
151 break;
152
153 case typeDouble:
154 fetch_nwfpe_double (fn, fpa11);
155 break;
156
157 case typeExtended:
158 fetch_nwfpe_extended (fn, fpa11);
159 break;
160
161 default:
162 fetch_nwfpe_none (fn);
163 }
164 }
165
166 static void
167 store_nwfpe_single (unsigned int fn, FPA11 * fpa11)
168 {
169 unsigned int mem[3];
170
171 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
172 fpa11->fpreg[fn].fSingle = mem[0];
173 fpa11->fType[fn] = typeSingle;
174 }
175
176 static void
177 store_nwfpe_double (unsigned int fn, FPA11 * fpa11)
178 {
179 unsigned int mem[3];
180
181 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
182 fpa11->fpreg[fn].fDouble[1] = mem[0];
183 fpa11->fpreg[fn].fDouble[0] = mem[1];
184 fpa11->fType[fn] = typeDouble;
185 }
186
187 void
188 store_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
189 {
190 unsigned int mem[3];
191
192 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
193 fpa11->fpreg[fn].fExtended[0] = mem[0]; /* sign & exponent */
194 fpa11->fpreg[fn].fExtended[2] = mem[1]; /* ls bits */
195 fpa11->fpreg[fn].fExtended[1] = mem[2]; /* ms bits */
196 fpa11->fType[fn] = typeDouble;
197 }
198
199 void
200 store_nwfpe_register (int regno, FPA11 * fpa11)
201 {
202 if (register_valid[regno])
203 {
204 unsigned int fn = regno - F0_REGNUM;
205 switch (fpa11->fType[fn])
206 {
207 case typeSingle:
208 store_nwfpe_single (fn, fpa11);
209 break;
210
211 case typeDouble:
212 store_nwfpe_double (fn, fpa11);
213 break;
214
215 case typeExtended:
216 store_nwfpe_extended (fn, fpa11);
217 break;
218 }
219 }
220 }
221
222
223 /* Get the value of a particular register from the floating point
224 state of the process and store it into registers[]. */
225
226 static void
227 fetch_fpregister (int regno)
228 {
229 int ret, tid;
230 FPA11 fp;
231
232 /* Get the thread id for the ptrace call. */
233 tid = GET_THREAD_ID (inferior_pid);
234
235 /* Read the floating point state. */
236 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
237 if (ret < 0)
238 {
239 warning ("Unable to fetch floating point register.");
240 return;
241 }
242
243 /* Fetch fpsr. */
244 if (FPS_REGNUM == regno)
245 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
246
247 /* Fetch the floating point register. */
248 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
249 {
250 int fn = regno - F0_REGNUM;
251
252 switch (fp.fType[fn])
253 {
254 case typeSingle:
255 fetch_nwfpe_single (fn, &fp);
256 break;
257
258 case typeDouble:
259 fetch_nwfpe_double (fn, &fp);
260 break;
261
262 case typeExtended:
263 fetch_nwfpe_extended (fn, &fp);
264 break;
265
266 default:
267 fetch_nwfpe_none (fn);
268 }
269 }
270 }
271
272 /* Get the whole floating point state of the process and store it
273 into registers[]. */
274
275 static void
276 fetch_fpregs (void)
277 {
278 int ret, regno, tid;
279 FPA11 fp;
280
281 /* Get the thread id for the ptrace call. */
282 tid = GET_THREAD_ID (inferior_pid);
283
284 /* Read the floating point state. */
285 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
286 if (ret < 0)
287 {
288 warning ("Unable to fetch the floating point registers.");
289 return;
290 }
291
292 /* Fetch fpsr. */
293 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
294
295 /* Fetch the floating point registers. */
296 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
297 {
298 int fn = regno - F0_REGNUM;
299
300 switch (fp.fType[fn])
301 {
302 case typeSingle:
303 fetch_nwfpe_single (fn, &fp);
304 break;
305
306 case typeDouble:
307 fetch_nwfpe_double (fn, &fp);
308 break;
309
310 case typeExtended:
311 fetch_nwfpe_extended (fn, &fp);
312 break;
313
314 default:
315 fetch_nwfpe_none (fn);
316 }
317 }
318 }
319
320 /* Save a particular register into the floating point state of the
321 process using the contents from registers[]. */
322
323 static void
324 store_fpregister (int regno)
325 {
326 int ret, tid;
327 FPA11 fp;
328
329 /* Get the thread id for the ptrace call. */
330 tid = GET_THREAD_ID (inferior_pid);
331
332 /* Read the floating point state. */
333 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
334 if (ret < 0)
335 {
336 warning ("Unable to fetch the floating point registers.");
337 return;
338 }
339
340 /* Store fpsr. */
341 if (FPS_REGNUM == regno && register_valid[FPS_REGNUM])
342 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
343
344 /* Store the floating point register. */
345 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
346 {
347 store_nwfpe_register (regno, &fp);
348 }
349
350 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
351 if (ret < 0)
352 {
353 warning ("Unable to store floating point register.");
354 return;
355 }
356 }
357
358 /* Save the whole floating point state of the process using
359 the contents from registers[]. */
360
361 static void
362 store_fpregs (void)
363 {
364 int ret, regno, tid;
365 FPA11 fp;
366
367 /* Get the thread id for the ptrace call. */
368 tid = GET_THREAD_ID (inferior_pid);
369
370 /* Read the floating point state. */
371 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
372 if (ret < 0)
373 {
374 warning ("Unable to fetch the floating point registers.");
375 return;
376 }
377
378 /* Store fpsr. */
379 if (register_valid[FPS_REGNUM])
380 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
381
382 /* Store the floating point registers. */
383 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
384 {
385 fetch_nwfpe_register (regno, &fp);
386 }
387
388 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
389 if (ret < 0)
390 {
391 warning ("Unable to store floating point registers.");
392 return;
393 }
394 }
395
396 /* Fetch a general register of the process and store into
397 registers[]. */
398
399 static void
400 fetch_register (int regno)
401 {
402 int ret, tid;
403 struct pt_regs regs;
404
405 /* Get the thread id for the ptrace call. */
406 tid = GET_THREAD_ID (inferior_pid);
407
408 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
409 if (ret < 0)
410 {
411 warning ("Unable to fetch general register.");
412 return;
413 }
414
415 if (regno >= A1_REGNUM && regno < PC_REGNUM)
416 supply_register (regno, (char *) &regs.uregs[regno]);
417
418 if (PS_REGNUM == regno)
419 {
420 if (arm_apcs_32)
421 supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
422 else
423 supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
424 }
425
426 if (PC_REGNUM == regno)
427 {
428 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
429 supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
430 }
431 }
432
433 /* Fetch all general registers of the process and store into
434 registers[]. */
435
436 static void
437 fetch_regs (void)
438 {
439 int ret, regno, tid;
440 struct pt_regs regs;
441
442 /* Get the thread id for the ptrace call. */
443 tid = GET_THREAD_ID (inferior_pid);
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 = A1_REGNUM; regno < PC_REGNUM; regno++)
453 supply_register (regno, (char *) &regs.uregs[regno]);
454
455 if (arm_apcs_32)
456 supply_register (PS_REGNUM, (char *) &regs.uregs[CPSR_REGNUM]);
457 else
458 supply_register (PS_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
459
460 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
461 supply_register (PC_REGNUM, (char *) &regs.uregs[PC_REGNUM]);
462 }
463
464 /* Store all general registers of the process from the values in
465 registers[]. */
466
467 static void
468 store_register (int regno)
469 {
470 int ret, tid;
471 struct pt_regs regs;
472
473 if (!register_valid[regno])
474 return;
475
476 /* Get the thread id for the ptrace call. */
477 tid = GET_THREAD_ID (inferior_pid);
478
479 /* Get the general registers from the process. */
480 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
481 if (ret < 0)
482 {
483 warning ("Unable to fetch general registers.");
484 return;
485 }
486
487 if (regno >= A1_REGNUM && regno <= PC_REGNUM)
488 read_register_gen (regno, (char *) &regs.uregs[regno]);
489
490 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
491 if (ret < 0)
492 {
493 warning ("Unable to store general register.");
494 return;
495 }
496 }
497
498 static void
499 store_regs (void)
500 {
501 int ret, regno, tid;
502 struct pt_regs regs;
503
504 /* Get the thread id for the ptrace call. */
505 tid = GET_THREAD_ID (inferior_pid);
506
507 /* Fetch the general registers. */
508 ret = ptrace (PTRACE_GETREGS, tid, 0, &regs);
509 if (ret < 0)
510 {
511 warning ("Unable to fetch general registers.");
512 return;
513 }
514
515 for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
516 {
517 if (register_valid[regno])
518 read_register_gen (regno, (char *) &regs.uregs[regno]);
519 }
520
521 ret = ptrace (PTRACE_SETREGS, tid, 0, &regs);
522
523 if (ret < 0)
524 {
525 warning ("Unable to store general registers.");
526 return;
527 }
528 }
529
530 /* Fetch registers from the child process. Fetch all registers if
531 regno == -1, otherwise fetch all general registers or all floating
532 point registers depending upon the value of regno. */
533
534 void
535 fetch_inferior_registers (int regno)
536 {
537 if (-1 == regno)
538 {
539 fetch_regs ();
540 fetch_fpregs ();
541 }
542 else
543 {
544 if (regno < F0_REGNUM || regno > FPS_REGNUM)
545 fetch_register (regno);
546
547 if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
548 fetch_fpregister (regno);
549 }
550 }
551
552 /* Store registers back into the inferior. Store all registers if
553 regno == -1, otherwise store all general registers or all floating
554 point registers depending upon the value of regno. */
555
556 void
557 store_inferior_registers (int regno)
558 {
559 if (-1 == regno)
560 {
561 store_regs ();
562 store_fpregs ();
563 }
564 else
565 {
566 if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
567 store_register (regno);
568
569 if ((regno >= F0_REGNUM) && (regno <= FPS_REGNUM))
570 store_fpregister (regno);
571 }
572 }
573
574 /* Fill register regno (if it is a general-purpose register) in
575 *gregsetp with the appropriate value from GDB's register array.
576 If regno is -1, do this for all registers. */
577
578 void
579 fill_gregset (gdb_gregset_t *gregsetp, int regno)
580 {
581 if (-1 == regno)
582 {
583 int regnum;
584 for (regnum = A1_REGNUM; regnum <= PC_REGNUM; regnum++)
585 if (register_valid[regnum])
586 read_register_gen (regnum, (char *) &(*gregsetp)[regnum]);
587 }
588 else if (regno >= A1_REGNUM && regno <= PC_REGNUM)
589 {
590 if (register_valid[regno])
591 read_register_gen (regno, (char *) &(*gregsetp)[regno]);
592 }
593
594 if (PS_REGNUM == regno || -1 == regno)
595 {
596 if (register_valid[regno] || -1 == regno)
597 {
598 if (arm_apcs_32)
599 read_register_gen (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
600 else
601 read_register_gen (PC_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
602 }
603 }
604
605 }
606
607 /* Fill GDB's register array with the general-purpose register values
608 in *gregsetp. */
609
610 void
611 supply_gregset (gdb_gregset_t *gregsetp)
612 {
613 int regno, reg_pc;
614
615 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
616 supply_register (regno, (char *) &(*gregsetp)[regno]);
617
618 if (arm_apcs_32)
619 supply_register (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
620 else
621 supply_register (PS_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
622
623 reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[PC_REGNUM]);
624 supply_register (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 = F0_REGNUM; regnum <= F7_REGNUM; regnum++)
640 store_nwfpe_register (regnum, fp);
641 }
642 else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
643 {
644 store_nwfpe_register (regno, fp);
645 return;
646 }
647
648 /* Store fpsr. */
649 if (register_valid[FPS_REGNUM])
650 if (FPS_REGNUM == regno || -1 == regno)
651 read_register_gen (FPS_REGNUM, (char *) &fp->fpsr);
652 }
653
654 /* Fill GDB's register array with the floating-point register values
655 in *fpregsetp. */
656
657 void
658 supply_fpregset (gdb_fpregset_t *fpregsetp)
659 {
660 int regno;
661 FPA11 *fp = (FPA11 *) fpregsetp;
662
663 /* Fetch fpsr. */
664 supply_register (FPS_REGNUM, (char *) &fp->fpsr);
665
666 /* Fetch the floating point registers. */
667 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
668 {
669 fetch_nwfpe_register (regno, fp);
670 }
671 }
672
673 int
674 arm_linux_kernel_u_size (void)
675 {
676 return (sizeof (struct user));
677 }
678
679 static unsigned int
680 get_linux_version (unsigned int *vmajor,
681 unsigned int *vminor,
682 unsigned int *vrelease)
683 {
684 struct utsname info;
685 char *pmajor, *pminor, *prelease, *tail;
686
687 if (-1 == uname (&info))
688 {
689 warning ("Unable to determine Linux version.");
690 return -1;
691 }
692
693 pmajor = strtok (info.release, ".");
694 pminor = strtok (NULL, ".");
695 prelease = strtok (NULL, ".");
696
697 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
698 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
699 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
700
701 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
702 }
703
704 void
705 _initialize_arm_linux_nat (void)
706 {
707 os_version = get_linux_version (&os_major, &os_minor, &os_release);
708 }
This page took 0.044606 seconds and 4 git commands to generate.