]> Git Repo - binutils.git/blob - gdb/arm-linux-nat.c
Fix 2 bugs with parsing the resource dependency tables.
[binutils.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.062524 seconds and 4 git commands to generate.