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_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. */
86 #if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
87 #define PIDGET(PID) PID
92 get_thread_id (ptid_t ptid
)
94 int tid
= TIDGET (ptid
);
99 #define GET_THREAD_ID(PTID) get_thread_id ((PTID));
102 fetch_nwfpe_single (unsigned int fn
, FPA11
* fpa11
)
106 mem
[0] = fpa11
->fpreg
[fn
].fSingle
;
109 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
113 fetch_nwfpe_double (unsigned int fn
, FPA11
* fpa11
)
117 mem
[0] = fpa11
->fpreg
[fn
].fDouble
[1];
118 mem
[1] = fpa11
->fpreg
[fn
].fDouble
[0];
120 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
124 fetch_nwfpe_none (unsigned int fn
)
126 unsigned int mem
[3] =
129 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
133 fetch_nwfpe_extended (unsigned int fn
, FPA11
* fpa11
)
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]);
144 fetch_nwfpe_register (int regno
, FPA11
* fpa11
)
146 int fn
= regno
- F0_REGNUM
;
148 switch (fpa11
->fType
[fn
])
151 fetch_nwfpe_single (fn
, fpa11
);
155 fetch_nwfpe_double (fn
, fpa11
);
159 fetch_nwfpe_extended (fn
, fpa11
);
163 fetch_nwfpe_none (fn
);
168 store_nwfpe_single (unsigned int fn
, FPA11
* fpa11
)
172 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
173 fpa11
->fpreg
[fn
].fSingle
= mem
[0];
174 fpa11
->fType
[fn
] = typeSingle
;
178 store_nwfpe_double (unsigned int fn
, FPA11
* fpa11
)
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
;
189 store_nwfpe_extended (unsigned int fn
, FPA11
* fpa11
)
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
;
201 store_nwfpe_register (int regno
, FPA11
* fpa11
)
203 if (register_valid
[regno
])
205 unsigned int fn
= regno
- F0_REGNUM
;
206 switch (fpa11
->fType
[fn
])
209 store_nwfpe_single (fn
, fpa11
);
213 store_nwfpe_double (fn
, fpa11
);
217 store_nwfpe_extended (fn
, fpa11
);
224 /* Get the value of a particular register from the floating point
225 state of the process and store it into registers[]. */
228 fetch_fpregister (int regno
)
233 /* Get the thread id for the ptrace call. */
234 tid
= GET_THREAD_ID (inferior_ptid
);
236 /* Read the floating point state. */
237 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
240 warning ("Unable to fetch floating point register.");
245 if (FPS_REGNUM
== regno
)
246 supply_register (FPS_REGNUM
, (char *) &fp
.fpsr
);
248 /* Fetch the floating point register. */
249 if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
251 int fn
= regno
- F0_REGNUM
;
253 switch (fp
.fType
[fn
])
256 fetch_nwfpe_single (fn
, &fp
);
260 fetch_nwfpe_double (fn
, &fp
);
264 fetch_nwfpe_extended (fn
, &fp
);
268 fetch_nwfpe_none (fn
);
273 /* Get the whole floating point state of the process and store it
282 /* Get the thread id for the ptrace call. */
283 tid
= GET_THREAD_ID (inferior_ptid
);
285 /* Read the floating point state. */
286 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
289 warning ("Unable to fetch the floating point registers.");
294 supply_register (FPS_REGNUM
, (char *) &fp
.fpsr
);
296 /* Fetch the floating point registers. */
297 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
299 int fn
= regno
- F0_REGNUM
;
301 switch (fp
.fType
[fn
])
304 fetch_nwfpe_single (fn
, &fp
);
308 fetch_nwfpe_double (fn
, &fp
);
312 fetch_nwfpe_extended (fn
, &fp
);
316 fetch_nwfpe_none (fn
);
321 /* Save a particular register into the floating point state of the
322 process using the contents from registers[]. */
325 store_fpregister (int regno
)
330 /* Get the thread id for the ptrace call. */
331 tid
= GET_THREAD_ID (inferior_ptid
);
333 /* Read the floating point state. */
334 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
337 warning ("Unable to fetch the floating point registers.");
342 if (FPS_REGNUM
== regno
&& register_valid
[FPS_REGNUM
])
343 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
345 /* Store the floating point register. */
346 if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
348 store_nwfpe_register (regno
, &fp
);
351 ret
= ptrace (PTRACE_SETFPREGS
, tid
, 0, &fp
);
354 warning ("Unable to store floating point register.");
359 /* Save the whole floating point state of the process using
360 the contents from registers[]. */
368 /* Get the thread id for the ptrace call. */
369 tid
= GET_THREAD_ID (inferior_ptid
);
371 /* Read the floating point state. */
372 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
375 warning ("Unable to fetch the floating point registers.");
380 if (register_valid
[FPS_REGNUM
])
381 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
383 /* Store the floating point registers. */
384 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
386 fetch_nwfpe_register (regno
, &fp
);
389 ret
= ptrace (PTRACE_SETFPREGS
, tid
, 0, &fp
);
392 warning ("Unable to store floating point registers.");
397 /* Fetch a general register of the process and store into
401 fetch_register (int regno
)
406 /* Get the thread id for the ptrace call. */
407 tid
= GET_THREAD_ID (inferior_ptid
);
409 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
412 warning ("Unable to fetch general register.");
416 if (regno
>= A1_REGNUM
&& regno
< PC_REGNUM
)
417 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
419 if (PS_REGNUM
== regno
)
422 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
424 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
427 if (PC_REGNUM
== regno
)
429 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
430 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
434 /* Fetch all general registers of the process and store into
443 /* Get the thread id for the ptrace call. */
444 tid
= GET_THREAD_ID (inferior_ptid
);
446 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
449 warning ("Unable to fetch general registers.");
453 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
454 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
457 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
459 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
461 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
462 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
465 /* Store all general registers of the process from the values in
469 store_register (int regno
)
474 if (!register_valid
[regno
])
477 /* Get the thread id for the ptrace call. */
478 tid
= GET_THREAD_ID (inferior_ptid
);
480 /* Get the general registers from the process. */
481 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
484 warning ("Unable to fetch general registers.");
488 if (regno
>= A1_REGNUM
&& regno
<= PC_REGNUM
)
489 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
491 ret
= ptrace (PTRACE_SETREGS
, tid
, 0, ®s
);
494 warning ("Unable to store general register.");
505 /* Get the thread id for the ptrace call. */
506 tid
= GET_THREAD_ID (inferior_ptid
);
508 /* Fetch the general registers. */
509 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
512 warning ("Unable to fetch general registers.");
516 for (regno
= A1_REGNUM
; regno
<= PC_REGNUM
; regno
++)
518 if (register_valid
[regno
])
519 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
522 ret
= ptrace (PTRACE_SETREGS
, tid
, 0, ®s
);
526 warning ("Unable to store general registers.");
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. */
536 fetch_inferior_registers (int regno
)
545 if (regno
< F0_REGNUM
|| regno
> FPS_REGNUM
)
546 fetch_register (regno
);
548 if (regno
>= F0_REGNUM
&& regno
<= FPS_REGNUM
)
549 fetch_fpregister (regno
);
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. */
558 store_inferior_registers (int regno
)
567 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
568 store_register (regno
);
570 if ((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
))
571 store_fpregister (regno
);
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. */
580 fill_gregset (gdb_gregset_t
*gregsetp
, int regno
)
585 for (regnum
= A1_REGNUM
; regnum
<= PC_REGNUM
; regnum
++)
586 if (register_valid
[regnum
])
587 read_register_gen (regnum
, (char *) &(*gregsetp
)[regnum
]);
589 else if (regno
>= A1_REGNUM
&& regno
<= PC_REGNUM
)
591 if (register_valid
[regno
])
592 read_register_gen (regno
, (char *) &(*gregsetp
)[regno
]);
595 if (PS_REGNUM
== regno
|| -1 == regno
)
597 if (register_valid
[regno
] || -1 == regno
)
600 read_register_gen (PS_REGNUM
, (char *) &(*gregsetp
)[CPSR_REGNUM
]);
602 read_register_gen (PC_REGNUM
, (char *) &(*gregsetp
)[PC_REGNUM
]);
608 /* Fill GDB's register array with the general-purpose register values
612 supply_gregset (gdb_gregset_t
*gregsetp
)
616 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
617 supply_register (regno
, (char *) &(*gregsetp
)[regno
]);
620 supply_register (PS_REGNUM
, (char *) &(*gregsetp
)[CPSR_REGNUM
]);
622 supply_register (PS_REGNUM
, (char *) &(*gregsetp
)[PC_REGNUM
]);
624 reg_pc
= ADDR_BITS_REMOVE ((CORE_ADDR
)(*gregsetp
)[PC_REGNUM
]);
625 supply_register (PC_REGNUM
, (char *) ®_pc
);
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. */
633 fill_fpregset (gdb_fpregset_t
*fpregsetp
, int regno
)
635 FPA11
*fp
= (FPA11
*) fpregsetp
;
640 for (regnum
= F0_REGNUM
; regnum
<= F7_REGNUM
; regnum
++)
641 store_nwfpe_register (regnum
, fp
);
643 else if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
645 store_nwfpe_register (regno
, fp
);
650 if (register_valid
[FPS_REGNUM
])
651 if (FPS_REGNUM
== regno
|| -1 == regno
)
652 read_register_gen (FPS_REGNUM
, (char *) &fp
->fpsr
);
655 /* Fill GDB's register array with the floating-point register values
659 supply_fpregset (gdb_fpregset_t
*fpregsetp
)
662 FPA11
*fp
= (FPA11
*) fpregsetp
;
665 supply_register (FPS_REGNUM
, (char *) &fp
->fpsr
);
667 /* Fetch the floating point registers. */
668 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
670 fetch_nwfpe_register (regno
, fp
);
675 arm_linux_kernel_u_size (void)
677 return (sizeof (struct user
));
681 get_linux_version (unsigned int *vmajor
,
682 unsigned int *vminor
,
683 unsigned int *vrelease
)
686 char *pmajor
, *pminor
, *prelease
, *tail
;
688 if (-1 == uname (&info
))
690 warning ("Unable to determine Linux version.");
694 pmajor
= strtok (info
.release
, ".");
695 pminor
= strtok (NULL
, ".");
696 prelease
= strtok (NULL
, ".");
698 *vmajor
= (unsigned int) strtoul (pmajor
, &tail
, 0);
699 *vminor
= (unsigned int) strtoul (pminor
, &tail
, 0);
700 *vrelease
= (unsigned int) strtoul (prelease
, &tail
, 0);
702 return ((*vmajor
<< 16) | (*vminor
<< 8) | *vrelease
);
706 _initialize_arm_linux_nat (void)
708 os_version
= get_linux_version (&os_major
, &os_minor
, &os_release
);
This page took 0.048806 seconds and 4 git commands to generate.