1 /* GNU/Linux on ARM native support.
2 Copyright 1999, 2000 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"
27 #include <sys/ptrace.h>
28 #include <sys/utsname.h>
29 #include <sys/procfs.h>
31 /* Prototypes for supply_gregset etc. */
34 extern int arm_apcs_32
;
37 #define typeSingle 0x01
38 #define typeDouble 0x02
39 #define typeExtended 0x03
41 #define CPSR_REGNUM 16
43 typedef union tagFPREG
46 unsigned int fDouble
[2];
47 unsigned int fExtended
[3];
51 typedef struct tagFPA11
53 FPREG fpreg
[8]; /* 8 floating point registers */
54 unsigned int fpsr
; /* floating point status register */
55 unsigned int fpcr
; /* floating point control register */
56 unsigned char fType
[8]; /* type of floating point value held in
57 floating point registers. */
58 int initflag
; /* NWFPE initialization flag. */
62 /* The following variables are used to determine the version of the
63 underlying Linux operating system. Examples:
65 Linux 2.0.35 Linux 2.2.12
66 os_version = 0x00020023 os_version = 0x0002020c
67 os_major = 2 os_major = 2
68 os_minor = 0 os_minor = 2
69 os_release = 35 os_release = 12
71 Note: os_version = (os_major << 16) | (os_minor << 8) | os_release
73 These are initialized using get_linux_version() from
74 _initialize_arm_linux_nat(). */
76 static unsigned int os_version
, os_major
, os_minor
, os_release
;
78 /* On Linux, threads are implemented as pseudo-processes, in which
79 case we may be tracing more than one process at a time. In that
80 case, inferior_pid will contain the main process ID and the
81 individual thread (process) ID mashed together. These macros are
82 used to separate them out. These definitions should be overridden
83 if thread support is included. */
85 #if !defined (PIDGET) /* Default definition for PIDGET/TIDGET. */
86 #define PIDGET(PID) PID
91 get_thread_id (int inferior_pid
)
93 int tid
= TIDGET (inferior_pid
);
94 if (0 == tid
) tid
= inferior_pid
;
97 #define GET_THREAD_ID(PID) get_thread_id ((PID));
100 fetch_nwfpe_single (unsigned int fn
, FPA11
* fpa11
)
104 mem
[0] = fpa11
->fpreg
[fn
].fSingle
;
107 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
111 fetch_nwfpe_double (unsigned int fn
, FPA11
* fpa11
)
115 mem
[0] = fpa11
->fpreg
[fn
].fDouble
[1];
116 mem
[1] = fpa11
->fpreg
[fn
].fDouble
[0];
118 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
122 fetch_nwfpe_none (unsigned int fn
)
124 unsigned int mem
[3] =
127 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
131 fetch_nwfpe_extended (unsigned int fn
, FPA11
* fpa11
)
135 mem
[0] = fpa11
->fpreg
[fn
].fExtended
[0]; /* sign & exponent */
136 mem
[1] = fpa11
->fpreg
[fn
].fExtended
[2]; /* ls bits */
137 mem
[2] = fpa11
->fpreg
[fn
].fExtended
[1]; /* ms bits */
138 supply_register (F0_REGNUM
+ fn
, (char *) &mem
[0]);
142 fetch_nwfpe_register (int regno
, FPA11
* fpa11
)
144 int fn
= regno
- F0_REGNUM
;
146 switch (fpa11
->fType
[fn
])
149 fetch_nwfpe_single (fn
, fpa11
);
153 fetch_nwfpe_double (fn
, fpa11
);
157 fetch_nwfpe_extended (fn
, fpa11
);
161 fetch_nwfpe_none (fn
);
166 store_nwfpe_single (unsigned int fn
, FPA11
* fpa11
)
170 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
171 fpa11
->fpreg
[fn
].fSingle
= mem
[0];
172 fpa11
->fType
[fn
] = typeSingle
;
176 store_nwfpe_double (unsigned int fn
, FPA11
* fpa11
)
180 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
181 fpa11
->fpreg
[fn
].fDouble
[1] = mem
[0];
182 fpa11
->fpreg
[fn
].fDouble
[0] = mem
[1];
183 fpa11
->fType
[fn
] = typeDouble
;
187 store_nwfpe_extended (unsigned int fn
, FPA11
* fpa11
)
191 read_register_gen (F0_REGNUM
+ fn
, (char *) &mem
[0]);
192 fpa11
->fpreg
[fn
].fExtended
[0] = mem
[0]; /* sign & exponent */
193 fpa11
->fpreg
[fn
].fExtended
[2] = mem
[1]; /* ls bits */
194 fpa11
->fpreg
[fn
].fExtended
[1] = mem
[2]; /* ms bits */
195 fpa11
->fType
[fn
] = typeDouble
;
199 store_nwfpe_register (int regno
, FPA11
* fpa11
)
201 if (register_valid
[regno
])
203 unsigned int fn
= regno
- F0_REGNUM
;
204 switch (fpa11
->fType
[fn
])
207 store_nwfpe_single (fn
, fpa11
);
211 store_nwfpe_double (fn
, fpa11
);
215 store_nwfpe_extended (fn
, fpa11
);
222 /* Get the value of a particular register from the floating point
223 state of the process and store it into registers[]. */
226 fetch_fpregister (int regno
)
231 /* Get the thread id for the ptrace call. */
232 tid
= GET_THREAD_ID (inferior_pid
);
234 /* Read the floating point state. */
235 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
238 warning ("Unable to fetch floating point register.");
243 if (FPS_REGNUM
== regno
)
244 supply_register (FPS_REGNUM
, (char *) &fp
.fpsr
);
246 /* Fetch the floating point register. */
247 if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
249 int fn
= regno
- F0_REGNUM
;
251 switch (fp
.fType
[fn
])
254 fetch_nwfpe_single (fn
, &fp
);
258 fetch_nwfpe_double (fn
, &fp
);
262 fetch_nwfpe_extended (fn
, &fp
);
266 fetch_nwfpe_none (fn
);
271 /* Get the whole floating point state of the process and store it
280 /* Get the thread id for the ptrace call. */
281 tid
= GET_THREAD_ID (inferior_pid
);
283 /* Read the floating point state. */
284 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
287 warning ("Unable to fetch the floating point registers.");
292 supply_register (FPS_REGNUM
, (char *) &fp
.fpsr
);
294 /* Fetch the floating point registers. */
295 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
297 int fn
= regno
- F0_REGNUM
;
299 switch (fp
.fType
[fn
])
302 fetch_nwfpe_single (fn
, &fp
);
306 fetch_nwfpe_double (fn
, &fp
);
310 fetch_nwfpe_extended (fn
, &fp
);
314 fetch_nwfpe_none (fn
);
319 /* Save a particular register into the floating point state of the
320 process using the contents from registers[]. */
323 store_fpregister (int regno
)
328 /* Get the thread id for the ptrace call. */
329 tid
= GET_THREAD_ID (inferior_pid
);
331 /* Read the floating point state. */
332 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
335 warning ("Unable to fetch the floating point registers.");
340 if (FPS_REGNUM
== regno
&& register_valid
[FPS_REGNUM
])
341 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
343 /* Store the floating point register. */
344 if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
346 store_nwfpe_register (regno
, &fp
);
349 ret
= ptrace (PTRACE_SETFPREGS
, tid
, 0, &fp
);
352 warning ("Unable to store floating point register.");
357 /* Save the whole floating point state of the process using
358 the contents from registers[]. */
366 /* Get the thread id for the ptrace call. */
367 tid
= GET_THREAD_ID (inferior_pid
);
369 /* Read the floating point state. */
370 ret
= ptrace (PT_GETFPREGS
, tid
, 0, &fp
);
373 warning ("Unable to fetch the floating point registers.");
378 if (register_valid
[FPS_REGNUM
])
379 read_register_gen (FPS_REGNUM
, (char *) &fp
.fpsr
);
381 /* Store the floating point registers. */
382 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
384 fetch_nwfpe_register (regno
, &fp
);
387 ret
= ptrace (PTRACE_SETFPREGS
, tid
, 0, &fp
);
390 warning ("Unable to store floating point registers.");
395 /* Fetch a general register of the process and store into
399 fetch_register (int regno
)
404 /* Get the thread id for the ptrace call. */
405 tid
= GET_THREAD_ID (inferior_pid
);
407 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
410 warning ("Unable to fetch general register.");
414 if (regno
>= A1_REGNUM
&& regno
< PC_REGNUM
)
415 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
417 if (PS_REGNUM
== regno
)
420 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
422 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
425 if (PC_REGNUM
== regno
)
427 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
428 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
432 /* Fetch all general registers of the process and store into
441 /* Get the thread id for the ptrace call. */
442 tid
= GET_THREAD_ID (inferior_pid
);
444 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
447 warning ("Unable to fetch general registers.");
451 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
452 supply_register (regno
, (char *) ®s
.uregs
[regno
]);
455 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[CPSR_REGNUM
]);
457 supply_register (PS_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
459 regs
.uregs
[PC_REGNUM
] = ADDR_BITS_REMOVE (regs
.uregs
[PC_REGNUM
]);
460 supply_register (PC_REGNUM
, (char *) ®s
.uregs
[PC_REGNUM
]);
463 /* Store all general registers of the process from the values in
467 store_register (int regno
)
472 if (!register_valid
[regno
])
475 /* Get the thread id for the ptrace call. */
476 tid
= GET_THREAD_ID (inferior_pid
);
478 /* Get the general registers from the process. */
479 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
482 warning ("Unable to fetch general registers.");
486 if (regno
>= A1_REGNUM
&& regno
<= PC_REGNUM
)
487 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
489 ret
= ptrace (PTRACE_SETREGS
, tid
, 0, ®s
);
492 warning ("Unable to store general register.");
503 /* Get the thread id for the ptrace call. */
504 tid
= GET_THREAD_ID (inferior_pid
);
506 /* Fetch the general registers. */
507 ret
= ptrace (PTRACE_GETREGS
, tid
, 0, ®s
);
510 warning ("Unable to fetch general registers.");
514 for (regno
= A1_REGNUM
; regno
<= PC_REGNUM
; regno
++)
516 if (register_valid
[regno
])
517 read_register_gen (regno
, (char *) ®s
.uregs
[regno
]);
520 ret
= ptrace (PTRACE_SETREGS
, tid
, 0, ®s
);
524 warning ("Unable to store general registers.");
529 /* Fetch registers from the child process. Fetch all registers if
530 regno == -1, otherwise fetch all general registers or all floating
531 point registers depending upon the value of regno. */
534 fetch_inferior_registers (int regno
)
543 if (regno
< F0_REGNUM
|| regno
> FPS_REGNUM
)
544 fetch_register (regno
);
546 if (regno
>= F0_REGNUM
&& regno
<= FPS_REGNUM
)
547 fetch_fpregister (regno
);
551 /* Store registers back into the inferior. Store all registers if
552 regno == -1, otherwise store all general registers or all floating
553 point registers depending upon the value of regno. */
556 store_inferior_registers (int regno
)
565 if ((regno
< F0_REGNUM
) || (regno
> FPS_REGNUM
))
566 store_register (regno
);
568 if ((regno
>= F0_REGNUM
) && (regno
<= FPS_REGNUM
))
569 store_fpregister (regno
);
573 /* Fill register regno (if it is a general-purpose register) in
574 *gregsetp with the appropriate value from GDB's register array.
575 If regno is -1, do this for all registers. */
578 fill_gregset (gregset_t
*gregsetp
, int regno
)
583 for (regnum
= A1_REGNUM
; regnum
<= PC_REGNUM
; regnum
++)
584 if (register_valid
[regnum
])
585 read_register_gen (regnum
, (char *) &(*gregsetp
)[regnum
]);
587 else if (regno
>= A1_REGNUM
&& regno
<= PC_REGNUM
)
589 if (register_valid
[regno
])
590 read_register_gen (regno
, (char *) &(*gregsetp
)[regno
]);
593 if (PS_REGNUM
== regno
|| -1 == regno
)
595 if (register_valid
[regno
] || -1 == regno
)
598 read_register_gen (PS_REGNUM
, (char *) &(*gregsetp
)[CPSR_REGNUM
]);
600 read_register_gen (PC_REGNUM
, (char *) &(*gregsetp
)[PC_REGNUM
]);
606 /* Fill GDB's register array with the general-purpose register values
610 supply_gregset (gregset_t
*gregsetp
)
614 for (regno
= A1_REGNUM
; regno
< PC_REGNUM
; regno
++)
615 supply_register (regno
, (char *) &(*gregsetp
)[regno
]);
618 supply_register (PS_REGNUM
, (char *) &(*gregsetp
)[CPSR_REGNUM
]);
620 supply_register (PS_REGNUM
, (char *) &(*gregsetp
)[PC_REGNUM
]);
622 reg_pc
= ADDR_BITS_REMOVE ((CORE_ADDR
)(*gregsetp
)[PC_REGNUM
]);
623 supply_register (PC_REGNUM
, (char *) ®_pc
);
626 /* Fill register regno (if it is a floating-point register) in
627 *fpregsetp with the appropriate value from GDB's register array.
628 If regno is -1, do this for all registers. */
631 fill_fpregset (fpregset_t
*fpregsetp
, int regno
)
633 FPA11
*fp
= (FPA11
*) fpregsetp
;
638 for (regnum
= F0_REGNUM
; regnum
<= F7_REGNUM
; regnum
++)
639 store_nwfpe_register (regnum
, fp
);
641 else if (regno
>= F0_REGNUM
&& regno
<= F7_REGNUM
)
643 store_nwfpe_register (regno
, fp
);
648 if (register_valid
[FPS_REGNUM
])
649 if (FPS_REGNUM
== regno
|| -1 == regno
)
650 read_register_gen (FPS_REGNUM
, (char *) &fp
->fpsr
);
653 /* Fill GDB's register array with the floating-point register values
657 supply_fpregset (fpregset_t
*fpregsetp
)
660 FPA11
*fp
= (FPA11
*) fpregsetp
;
663 supply_register (FPS_REGNUM
, (char *) &fp
->fpsr
);
665 /* Fetch the floating point registers. */
666 for (regno
= F0_REGNUM
; regno
<= F7_REGNUM
; regno
++)
668 fetch_nwfpe_register (regno
, fp
);
673 arm_linux_kernel_u_size (void)
675 return (sizeof (struct user
));
679 get_linux_version (unsigned int *vmajor
,
680 unsigned int *vminor
,
681 unsigned int *vrelease
)
684 char *pmajor
, *pminor
, *prelease
, *tail
;
686 if (-1 == uname (&info
))
688 warning ("Unable to determine Linux version.");
692 pmajor
= strtok (info
.release
, ".");
693 pminor
= strtok (NULL
, ".");
694 prelease
= strtok (NULL
, ".");
696 *vmajor
= (unsigned int) strtoul (pmajor
, &tail
, 0);
697 *vminor
= (unsigned int) strtoul (pminor
, &tail
, 0);
698 *vrelease
= (unsigned int) strtoul (prelease
, &tail
, 0);
700 return ((*vmajor
<< 16) | (*vminor
<< 8) | *vrelease
);
704 _initialize_arm_linux_nat (void)
706 os_version
= get_linux_version (&os_major
, &os_minor
, &os_release
);
This page took 0.043371 seconds and 4 git commands to generate.