1 /* GNU/Linux on ARM native support.
2 Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
24 #include "gdb_string.h"
28 #include <sys/ptrace.h>
29 #include <sys/utsname.h>
30 #include <sys/procfs.h>
32 /* Prototypes for supply_gregset etc. */
35 extern int arm_apcs_32;
38 #define typeSingle 0x01
39 #define typeDouble 0x02
40 #define typeExtended 0x03
42 #define CPSR_REGNUM 16
44 typedef union tagFPREG
47 unsigned int fDouble[2];
48 unsigned int fExtended[3];
52 typedef struct tagFPA11
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. */
63 /* The following variables are used to determine the version of the
64 underlying Linux operating system. Examples:
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
72 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
74 These are initialized using get_linux_version() from
75 _initialize_arm_linux_nat(). */
77 static unsigned int os_version, os_major, os_minor, os_release;
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. */
86 #if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
87 #define PIDGET(PID) PID
92 get_thread_id (int inferior_pid)
94 int tid = TIDGET (inferior_pid);
95 if (0 == tid) tid = inferior_pid;
98 #define GET_THREAD_ID(PID) get_thread_id ((PID));
101 fetch_nwfpe_single (unsigned int fn, FPA11 * fpa11)
105 mem[0] = fpa11->fpreg[fn].fSingle;
108 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
112 fetch_nwfpe_double (unsigned int fn, FPA11 * fpa11)
116 mem[0] = fpa11->fpreg[fn].fDouble[1];
117 mem[1] = fpa11->fpreg[fn].fDouble[0];
119 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
123 fetch_nwfpe_none (unsigned int fn)
125 unsigned int mem[3] =
128 supply_register (F0_REGNUM + fn, (char *) &mem[0]);
132 fetch_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
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]);
143 fetch_nwfpe_register (int regno, FPA11 * fpa11)
145 int fn = regno - F0_REGNUM;
147 switch (fpa11->fType[fn])
150 fetch_nwfpe_single (fn, fpa11);
154 fetch_nwfpe_double (fn, fpa11);
158 fetch_nwfpe_extended (fn, fpa11);
162 fetch_nwfpe_none (fn);
167 store_nwfpe_single (unsigned int fn, FPA11 * fpa11)
171 read_register_gen (F0_REGNUM + fn, (char *) &mem[0]);
172 fpa11->fpreg[fn].fSingle = mem[0];
173 fpa11->fType[fn] = typeSingle;
177 store_nwfpe_double (unsigned int fn, FPA11 * fpa11)
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;
188 store_nwfpe_extended (unsigned int fn, FPA11 * fpa11)
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;
200 store_nwfpe_register (int regno, FPA11 * fpa11)
202 if (register_valid[regno])
204 unsigned int fn = regno - F0_REGNUM;
205 switch (fpa11->fType[fn])
208 store_nwfpe_single (fn, fpa11);
212 store_nwfpe_double (fn, fpa11);
216 store_nwfpe_extended (fn, fpa11);
223 /* Get the value of a particular register from the floating point
224 state of the process and store it into registers[]. */
227 fetch_fpregister (int regno)
232 /* Get the thread id for the ptrace call. */
233 tid = GET_THREAD_ID (inferior_pid);
235 /* Read the floating point state. */
236 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
239 warning ("Unable to fetch floating point register.");
244 if (FPS_REGNUM == regno)
245 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
247 /* Fetch the floating point register. */
248 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
250 int fn = regno - F0_REGNUM;
252 switch (fp.fType[fn])
255 fetch_nwfpe_single (fn, &fp);
259 fetch_nwfpe_double (fn, &fp);
263 fetch_nwfpe_extended (fn, &fp);
267 fetch_nwfpe_none (fn);
272 /* Get the whole floating point state of the process and store it
281 /* Get the thread id for the ptrace call. */
282 tid = GET_THREAD_ID (inferior_pid);
284 /* Read the floating point state. */
285 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
288 warning ("Unable to fetch the floating point registers.");
293 supply_register (FPS_REGNUM, (char *) &fp.fpsr);
295 /* Fetch the floating point registers. */
296 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
298 int fn = regno - F0_REGNUM;
300 switch (fp.fType[fn])
303 fetch_nwfpe_single (fn, &fp);
307 fetch_nwfpe_double (fn, &fp);
311 fetch_nwfpe_extended (fn, &fp);
315 fetch_nwfpe_none (fn);
320 /* Save a particular register into the floating point state of the
321 process using the contents from registers[]. */
324 store_fpregister (int regno)
329 /* Get the thread id for the ptrace call. */
330 tid = GET_THREAD_ID (inferior_pid);
332 /* Read the floating point state. */
333 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
336 warning ("Unable to fetch the floating point registers.");
341 if (FPS_REGNUM == regno && register_valid[FPS_REGNUM])
342 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
344 /* Store the floating point register. */
345 if (regno >= F0_REGNUM && regno <= F7_REGNUM)
347 store_nwfpe_register (regno, &fp);
350 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
353 warning ("Unable to store floating point register.");
358 /* Save the whole floating point state of the process using
359 the contents from registers[]. */
367 /* Get the thread id for the ptrace call. */
368 tid = GET_THREAD_ID (inferior_pid);
370 /* Read the floating point state. */
371 ret = ptrace (PT_GETFPREGS, tid, 0, &fp);
374 warning ("Unable to fetch the floating point registers.");
379 if (register_valid[FPS_REGNUM])
380 read_register_gen (FPS_REGNUM, (char *) &fp.fpsr);
382 /* Store the floating point registers. */
383 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
385 fetch_nwfpe_register (regno, &fp);
388 ret = ptrace (PTRACE_SETFPREGS, tid, 0, &fp);
391 warning ("Unable to store floating point registers.");
396 /* Fetch a general register of the process and store into
400 fetch_register (int regno)
405 /* Get the thread id for the ptrace call. */
406 tid = GET_THREAD_ID (inferior_pid);
408 ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
411 warning ("Unable to fetch general register.");
415 if (regno >= A1_REGNUM && regno < PC_REGNUM)
416 supply_register (regno, (char *) ®s.uregs[regno]);
418 if (PS_REGNUM == regno)
421 supply_register (PS_REGNUM, (char *) ®s.uregs[CPSR_REGNUM]);
423 supply_register (PS_REGNUM, (char *) ®s.uregs[PC_REGNUM]);
426 if (PC_REGNUM == regno)
428 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
429 supply_register (PC_REGNUM, (char *) ®s.uregs[PC_REGNUM]);
433 /* Fetch all general registers of the process and store into
442 /* Get the thread id for the ptrace call. */
443 tid = GET_THREAD_ID (inferior_pid);
445 ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
448 warning ("Unable to fetch general registers.");
452 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
453 supply_register (regno, (char *) ®s.uregs[regno]);
456 supply_register (PS_REGNUM, (char *) ®s.uregs[CPSR_REGNUM]);
458 supply_register (PS_REGNUM, (char *) ®s.uregs[PC_REGNUM]);
460 regs.uregs[PC_REGNUM] = ADDR_BITS_REMOVE (regs.uregs[PC_REGNUM]);
461 supply_register (PC_REGNUM, (char *) ®s.uregs[PC_REGNUM]);
464 /* Store all general registers of the process from the values in
468 store_register (int regno)
473 if (!register_valid[regno])
476 /* Get the thread id for the ptrace call. */
477 tid = GET_THREAD_ID (inferior_pid);
479 /* Get the general registers from the process. */
480 ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
483 warning ("Unable to fetch general registers.");
487 if (regno >= A1_REGNUM && regno <= PC_REGNUM)
488 read_register_gen (regno, (char *) ®s.uregs[regno]);
490 ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
493 warning ("Unable to store general register.");
504 /* Get the thread id for the ptrace call. */
505 tid = GET_THREAD_ID (inferior_pid);
507 /* Fetch the general registers. */
508 ret = ptrace (PTRACE_GETREGS, tid, 0, ®s);
511 warning ("Unable to fetch general registers.");
515 for (regno = A1_REGNUM; regno <= PC_REGNUM; regno++)
517 if (register_valid[regno])
518 read_register_gen (regno, (char *) ®s.uregs[regno]);
521 ret = ptrace (PTRACE_SETREGS, tid, 0, ®s);
525 warning ("Unable to store general registers.");
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. */
535 fetch_inferior_registers (int regno)
544 if (regno < F0_REGNUM || regno > FPS_REGNUM)
545 fetch_register (regno);
547 if (regno >= F0_REGNUM && regno <= FPS_REGNUM)
548 fetch_fpregister (regno);
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. */
557 store_inferior_registers (int regno)
566 if ((regno < F0_REGNUM) || (regno > FPS_REGNUM))
567 store_register (regno);
569 if ((regno >= F0_REGNUM) && (regno <= FPS_REGNUM))
570 store_fpregister (regno);
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. */
579 fill_gregset (gdb_gregset_t *gregsetp, int regno)
584 for (regnum = A1_REGNUM; regnum <= PC_REGNUM; regnum++)
585 if (register_valid[regnum])
586 read_register_gen (regnum, (char *) &(*gregsetp)[regnum]);
588 else if (regno >= A1_REGNUM && regno <= PC_REGNUM)
590 if (register_valid[regno])
591 read_register_gen (regno, (char *) &(*gregsetp)[regno]);
594 if (PS_REGNUM == regno || -1 == regno)
596 if (register_valid[regno] || -1 == regno)
599 read_register_gen (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
601 read_register_gen (PC_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
607 /* Fill GDB's register array with the general-purpose register values
611 supply_gregset (gdb_gregset_t *gregsetp)
615 for (regno = A1_REGNUM; regno < PC_REGNUM; regno++)
616 supply_register (regno, (char *) &(*gregsetp)[regno]);
619 supply_register (PS_REGNUM, (char *) &(*gregsetp)[CPSR_REGNUM]);
621 supply_register (PS_REGNUM, (char *) &(*gregsetp)[PC_REGNUM]);
623 reg_pc = ADDR_BITS_REMOVE ((CORE_ADDR)(*gregsetp)[PC_REGNUM]);
624 supply_register (PC_REGNUM, (char *) ®_pc);
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. */
632 fill_fpregset (gdb_fpregset_t *fpregsetp, int regno)
634 FPA11 *fp = (FPA11 *) fpregsetp;
639 for (regnum = F0_REGNUM; regnum <= F7_REGNUM; regnum++)
640 store_nwfpe_register (regnum, fp);
642 else if (regno >= F0_REGNUM && regno <= F7_REGNUM)
644 store_nwfpe_register (regno, fp);
649 if (register_valid[FPS_REGNUM])
650 if (FPS_REGNUM == regno || -1 == regno)
651 read_register_gen (FPS_REGNUM, (char *) &fp->fpsr);
654 /* Fill GDB's register array with the floating-point register values
658 supply_fpregset (gdb_fpregset_t *fpregsetp)
661 FPA11 *fp = (FPA11 *) fpregsetp;
664 supply_register (FPS_REGNUM, (char *) &fp->fpsr);
666 /* Fetch the floating point registers. */
667 for (regno = F0_REGNUM; regno <= F7_REGNUM; regno++)
669 fetch_nwfpe_register (regno, fp);
674 arm_linux_kernel_u_size (void)
676 return (sizeof (struct user));
680 get_linux_version (unsigned int *vmajor,
681 unsigned int *vminor,
682 unsigned int *vrelease)
685 char *pmajor, *pminor, *prelease, *tail;
687 if (-1 == uname (&info))
689 warning ("Unable to determine Linux version.");
693 pmajor = strtok (info.release, ".");
694 pminor = strtok (NULL, ".");
695 prelease = strtok (NULL, ".");
697 *vmajor = (unsigned int) strtoul (pmajor, &tail, 0);
698 *vminor = (unsigned int) strtoul (pminor, &tail, 0);
699 *vrelease = (unsigned int) strtoul (prelease, &tail, 0);
701 return ((*vmajor << 16) | (*vminor << 8) | *vrelease);
705 _initialize_arm_linux_nat (void)
707 os_version = get_linux_version (&os_major, &os_minor, &os_release);