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