OSDN Git Service

Copyright updates for 2007.
[pf3gnuchains/pf3gnuchains4x.git] / gdb / frv-linux-tdep.c
1 /* Target-dependent code for GNU/Linux running on the Fujitsu FR-V,
2    for GDB.
3
4    Copyright (C) 2004, 2006, 2007 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor,
21    Boston, MA 02110-1301, USA.  */
22
23 #include "defs.h"
24 #include "gdbcore.h"
25 #include "target.h"
26 #include "frame.h"
27 #include "osabi.h"
28 #include "regcache.h"
29 #include "elf-bfd.h"
30 #include "elf/frv.h"
31 #include "frv-tdep.h"
32 #include "trad-frame.h"
33 #include "frame-unwind.h"
34 #include "regset.h"
35 #include "gdb_string.h"
36
37 /* Define the size (in bytes) of an FR-V instruction.  */
38 static const int frv_instr_size = 4;
39
40 enum {
41   NORMAL_SIGTRAMP = 1,
42   RT_SIGTRAMP = 2
43 };
44
45 static int
46 frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
47 {
48   char buf[frv_instr_size];
49   LONGEST instr;
50   int retval = 0;
51
52   if (target_read_memory (pc, buf, sizeof buf) != 0)
53     return 0;
54
55   instr = extract_unsigned_integer (buf, sizeof buf);
56
57   if (instr == 0x8efc0077)      /* setlos #__NR_sigreturn, gr7 */
58     retval = NORMAL_SIGTRAMP;
59   else if (instr -= 0x8efc00ad) /* setlos #__NR_rt_sigreturn, gr7 */
60     retval = RT_SIGTRAMP;
61   else
62     return 0;
63
64   if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0)
65     return 0;
66   instr = extract_unsigned_integer (buf, sizeof buf);
67   if (instr != 0xc0700000)      /* tira gr0, 0 */
68     return 0;
69
70   /* If we get this far, we'll return a non-zero value, either
71      NORMAL_SIGTRAMP (1) or RT_SIGTRAMP (2).  */
72   return retval;
73 }
74
75 /* Given NEXT_FRAME, the "callee" frame of the sigtramp frame that we
76    wish to decode, and REGNO, one of the frv register numbers defined
77    in frv-tdep.h, return the address of the saved register (corresponding
78    to REGNO) in the sigtramp frame.  Return -1 if the register is not
79    found in the sigtramp frame.  The magic numbers in the code below
80    were computed by examining the following kernel structs:
81
82    From arch/frv/kernel/signal.c:
83
84       struct sigframe
85       {
86               void (*pretcode)(void);
87               int sig;
88               struct sigcontext sc;
89               unsigned long extramask[_NSIG_WORDS-1];
90               uint32_t retcode[2];
91       };
92
93       struct rt_sigframe
94       {
95               void (*pretcode)(void);
96               int sig;
97               struct siginfo *pinfo;
98               void *puc;
99               struct siginfo info;
100               struct ucontext uc;
101               uint32_t retcode[2];
102       };
103
104    From include/asm-frv/ucontext.h:
105
106       struct ucontext {
107               unsigned long             uc_flags;
108               struct ucontext           *uc_link;
109               stack_t                   uc_stack;
110               struct sigcontext uc_mcontext;
111               sigset_t          uc_sigmask;
112       };
113
114    From include/asm-frv/signal.h:
115
116       typedef struct sigaltstack {
117               void *ss_sp;
118               int ss_flags;
119               size_t ss_size;
120       } stack_t;
121
122    From include/asm-frv/sigcontext.h:
123
124       struct sigcontext {
125               struct user_context       sc_context;
126               unsigned long             sc_oldmask;
127       } __attribute__((aligned(8)));
128
129    From include/asm-frv/registers.h:
130       struct user_int_regs
131       {
132               unsigned long             psr;
133               unsigned long             isr;
134               unsigned long             ccr;
135               unsigned long             cccr;
136               unsigned long             lr;
137               unsigned long             lcr;
138               unsigned long             pc;
139               unsigned long             __status;
140               unsigned long             syscallno;
141               unsigned long             orig_gr8;
142               unsigned long             gner[2];
143               unsigned long long        iacc[1];
144
145               union {
146                       unsigned long     tbr;
147                       unsigned long     gr[64];
148               };
149       };
150
151       struct user_fpmedia_regs
152       {
153               unsigned long     fr[64];
154               unsigned long     fner[2];
155               unsigned long     msr[2];
156               unsigned long     acc[8];
157               unsigned char     accg[8];
158               unsigned long     fsr[1];
159       };
160
161       struct user_context
162       {
163               struct user_int_regs              i;
164               struct user_fpmedia_regs  f;
165
166               void *extension;
167       } __attribute__((aligned(8)));  */
168
169 static LONGEST
170 frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno,
171                                CORE_ADDR *sc_addr_cache_ptr)
172 {
173   CORE_ADDR sc_addr;
174
175   if (sc_addr_cache_ptr && *sc_addr_cache_ptr)
176     {
177       sc_addr = *sc_addr_cache_ptr;
178     }
179   else
180     {
181       CORE_ADDR pc, sp;
182       char buf[4];
183       int tramp_type;
184
185       pc = frame_pc_unwind (next_frame);
186       tramp_type = frv_linux_pc_in_sigtramp (pc, 0);
187
188       frame_unwind_register (next_frame, sp_regnum, buf);
189       sp = extract_unsigned_integer (buf, sizeof buf);
190
191       if (tramp_type == NORMAL_SIGTRAMP)
192         {
193           /* For a normal sigtramp frame, the sigcontext struct starts
194              at SP + 8.  */
195           sc_addr = sp + 8;
196         }
197       else if (tramp_type == RT_SIGTRAMP)
198         {
199           /* For a realtime sigtramp frame, SP + 12 contains a pointer
200              to a ucontext struct.  The ucontext struct contains a
201              sigcontext struct starting 24 bytes in.  (The offset of
202              uc_mcontext within struct ucontext is derived as follows: 
203              stack_t is a 12-byte struct and struct sigcontext is
204              8-byte aligned.  This gives an offset of 8 + 12 + 4 (for
205              padding) = 24.) */
206           if (target_read_memory (sp + 12, buf, sizeof buf) != 0)
207             {
208               warning (_("Can't read realtime sigtramp frame."));
209               return 0;
210             }
211           sc_addr = extract_unsigned_integer (buf, sizeof buf);
212           sc_addr += 24;
213         }
214       else
215         internal_error (__FILE__, __LINE__, _("not a signal trampoline"));
216
217       if (sc_addr_cache_ptr)
218         *sc_addr_cache_ptr = sc_addr;
219     }
220
221   switch (regno)
222     {
223     case psr_regnum :
224       return sc_addr + 0;
225     /* sc_addr + 4 has "isr", the Integer Status Register.  */
226     case ccr_regnum :
227       return sc_addr + 8;
228     case cccr_regnum :
229       return sc_addr + 12;
230     case lr_regnum :
231       return sc_addr + 16;
232     case lcr_regnum :
233       return sc_addr + 20;
234     case pc_regnum :
235       return sc_addr + 24;
236     /* sc_addr + 28 is __status, the exception status.
237        sc_addr + 32 is syscallno, the syscall number or -1.
238        sc_addr + 36 is orig_gr8, the original syscall arg #1.
239        sc_addr + 40 is gner[0].
240        sc_addr + 44 is gner[1]. */
241     case iacc0h_regnum :
242       return sc_addr + 48;
243     case iacc0l_regnum :
244       return sc_addr + 52;
245     default : 
246       if (first_gpr_regnum <= regno && regno <= last_gpr_regnum)
247         return sc_addr + 56 + 4 * (regno - first_gpr_regnum);
248       else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum)
249         return sc_addr + 312 + 4 * (regno - first_fpr_regnum);
250       else
251         return -1;  /* not saved. */
252     }
253 }
254
255 /* Signal trampolines.  */
256
257 static struct trad_frame_cache *
258 frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
259 {
260   struct trad_frame_cache *cache;
261   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
262   CORE_ADDR addr;
263   char buf[4];
264   int regnum;
265   CORE_ADDR sc_addr_cache_val = 0;
266   struct frame_id this_id;
267
268   if (*this_cache)
269     return *this_cache;
270
271   cache = trad_frame_cache_zalloc (next_frame);
272
273   /* FIXME: cagney/2004-05-01: This is is long standing broken code.
274      The frame ID's code address should be the start-address of the
275      signal trampoline and not the current PC within that
276      trampoline.  */
277   frame_unwind_register (next_frame, sp_regnum, buf);
278   this_id = frame_id_build (extract_unsigned_integer (buf, sizeof buf),
279                             frame_pc_unwind (next_frame));
280   trad_frame_set_id (cache, this_id);
281
282   for (regnum = 0; regnum < frv_num_regs; regnum++)
283     {
284       LONGEST reg_addr = frv_linux_sigcontext_reg_addr (next_frame, regnum,
285                                                         &sc_addr_cache_val);
286       if (reg_addr != -1)
287         trad_frame_set_reg_addr (cache, regnum, reg_addr);
288     }
289
290   *this_cache = cache;
291   return cache;
292 }
293
294 static void
295 frv_linux_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
296                              struct frame_id *this_id)
297 {
298   struct trad_frame_cache *cache =
299     frv_linux_sigtramp_frame_cache (next_frame, this_cache);
300   trad_frame_get_id (cache, this_id);
301 }
302
303 static void
304 frv_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
305                                    void **this_cache,
306                                    int regnum, int *optimizedp,
307                                    enum lval_type *lvalp, CORE_ADDR *addrp,
308                                    int *realnump, gdb_byte *valuep)
309 {
310   /* Make sure we've initialized the cache.  */
311   struct trad_frame_cache *cache =
312     frv_linux_sigtramp_frame_cache (next_frame, this_cache);
313   trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp,
314                            addrp, realnump, valuep);
315 }
316
317 static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
318 {
319   SIGTRAMP_FRAME,
320   frv_linux_sigtramp_frame_this_id,
321   frv_linux_sigtramp_frame_prev_register
322 };
323
324 static const struct frame_unwind *
325 frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
326 {
327   CORE_ADDR pc = frame_pc_unwind (next_frame);
328   char *name;
329
330   find_pc_partial_function (pc, &name, NULL, NULL);
331   if (frv_linux_pc_in_sigtramp (pc, name))
332     return &frv_linux_sigtramp_frame_unwind;
333
334   return NULL;
335 }
336
337 \f
338 /* The FRV kernel defines ELF_NGREG as 46.  We add 2 in order to include
339    the loadmap addresses in the register set.  (See below for more info.)  */
340 #define FRV_ELF_NGREG (46 + 2)
341 typedef unsigned char frv_elf_greg_t[4];
342 typedef struct { frv_elf_greg_t reg[FRV_ELF_NGREG]; } frv_elf_gregset_t;
343
344 typedef unsigned char frv_elf_fpreg_t[4];
345 typedef struct
346 {
347   frv_elf_fpreg_t fr[64];
348   frv_elf_fpreg_t fner[2];
349   frv_elf_fpreg_t msr[2];
350   frv_elf_fpreg_t acc[8];
351   unsigned char accg[8];
352   frv_elf_fpreg_t fsr[1];
353 } frv_elf_fpregset_t;
354
355 /* Constants for accessing elements of frv_elf_gregset_t.  */
356
357 #define FRV_PT_PSR 0
358 #define FRV_PT_ISR 1
359 #define FRV_PT_CCR 2
360 #define FRV_PT_CCCR 3
361 #define FRV_PT_LR 4
362 #define FRV_PT_LCR 5
363 #define FRV_PT_PC 6
364 #define FRV_PT_GNER0 10
365 #define FRV_PT_GNER1 11
366 #define FRV_PT_IACC0H 12
367 #define FRV_PT_IACC0L 13
368
369 /* Note: Only 32 of the GRs will be found in the corefile.  */
370 #define FRV_PT_GR(j)    ( 14 + (j))     /* GRj for 0<=j<=63. */
371
372 #define FRV_PT_TBR FRV_PT_GR(0)         /* gr0 is always 0, so TBR is stuffed
373                                            there.  */
374
375 /* Technically, the loadmap addresses are not part of `pr_reg' as
376    found in the elf_prstatus struct.  The fields which communicate the
377    loadmap address appear (by design) immediately after `pr_reg'
378    though, and the BFD function elf32_frv_grok_prstatus() has been
379    implemented to include these fields in the register section that it
380    extracts from the core file.  So, for our purposes, they may be
381    viewed as registers.  */
382
383 #define FRV_PT_EXEC_FDPIC_LOADMAP 46
384 #define FRV_PT_INTERP_FDPIC_LOADMAP 47
385
386
387 /* Unpack an frv_elf_gregset_t into GDB's register cache.  */
388
389 static void 
390 frv_linux_supply_gregset (const struct regset *regset,
391                           struct regcache *regcache,
392                           int regnum, const void *gregs, size_t len)
393 {
394   int regi;
395   char zerobuf[MAX_REGISTER_SIZE];
396   const frv_elf_gregset_t *gregsetp = gregs;
397
398   memset (zerobuf, 0, MAX_REGISTER_SIZE);
399
400   /* gr0 always contains 0.  Also, the kernel passes the TBR value in
401      this slot.  */
402   regcache_raw_supply (regcache, first_gpr_regnum, zerobuf);
403
404   for (regi = first_gpr_regnum + 1; regi <= last_gpr_regnum; regi++)
405     {
406       if (regi >= first_gpr_regnum + 32)
407         regcache_raw_supply (regcache, regi, zerobuf);
408       else
409         regcache_raw_supply (regcache, regi,
410                              gregsetp->reg[FRV_PT_GR (regi - first_gpr_regnum)]);
411     }
412
413   regcache_raw_supply (regcache, pc_regnum, gregsetp->reg[FRV_PT_PC]);
414   regcache_raw_supply (regcache, psr_regnum, gregsetp->reg[FRV_PT_PSR]);
415   regcache_raw_supply (regcache, ccr_regnum, gregsetp->reg[FRV_PT_CCR]);
416   regcache_raw_supply (regcache, cccr_regnum, gregsetp->reg[FRV_PT_CCCR]);
417   regcache_raw_supply (regcache, lr_regnum, gregsetp->reg[FRV_PT_LR]);
418   regcache_raw_supply (regcache, lcr_regnum, gregsetp->reg[FRV_PT_LCR]);
419   regcache_raw_supply (regcache, gner0_regnum, gregsetp->reg[FRV_PT_GNER0]);
420   regcache_raw_supply (regcache, gner1_regnum, gregsetp->reg[FRV_PT_GNER1]);
421   regcache_raw_supply (regcache, tbr_regnum, gregsetp->reg[FRV_PT_TBR]);
422   regcache_raw_supply (regcache, fdpic_loadmap_exec_regnum,
423                        gregsetp->reg[FRV_PT_EXEC_FDPIC_LOADMAP]);
424   regcache_raw_supply (regcache, fdpic_loadmap_interp_regnum,
425                        gregsetp->reg[FRV_PT_INTERP_FDPIC_LOADMAP]);
426 }
427
428 /* Unpack an frv_elf_fpregset_t into GDB's register cache.  */
429
430 static void
431 frv_linux_supply_fpregset (const struct regset *regset,
432                            struct regcache *regcache,
433                            int regnum, const void *gregs, size_t len)
434 {
435   int regi;
436   const frv_elf_fpregset_t *fpregsetp = gregs;
437
438   for (regi = first_fpr_regnum; regi <= last_fpr_regnum; regi++)
439     regcache_raw_supply (regcache, regi, fpregsetp->fr[regi - first_fpr_regnum]);
440
441   regcache_raw_supply (regcache, fner0_regnum, fpregsetp->fner[0]);
442   regcache_raw_supply (regcache, fner1_regnum, fpregsetp->fner[1]);
443
444   regcache_raw_supply (regcache, msr0_regnum, fpregsetp->msr[0]);
445   regcache_raw_supply (regcache, msr1_regnum, fpregsetp->msr[1]);
446
447   for (regi = acc0_regnum; regi <= acc7_regnum; regi++)
448     regcache_raw_supply (regcache, regi, fpregsetp->acc[regi - acc0_regnum]);
449
450   regcache_raw_supply (regcache, accg0123_regnum, fpregsetp->accg);
451   regcache_raw_supply (regcache, accg4567_regnum, fpregsetp->accg + 4);
452
453   regcache_raw_supply (regcache, fsr0_regnum, fpregsetp->fsr[0]);
454 }
455
456 /* FRV Linux kernel register sets.  */
457
458 static struct regset frv_linux_gregset =
459 {
460   NULL,
461   frv_linux_supply_gregset
462 };
463
464 static struct regset frv_linux_fpregset =
465 {
466   NULL,
467   frv_linux_supply_fpregset
468 };
469
470 static const struct regset *
471 frv_linux_regset_from_core_section (struct gdbarch *gdbarch,
472                                     const char *sect_name, size_t sect_size)
473 {
474   if (strcmp (sect_name, ".reg") == 0 
475       && sect_size >= sizeof (frv_elf_gregset_t))
476     return &frv_linux_gregset;
477
478   if (strcmp (sect_name, ".reg2") == 0 
479       && sect_size >= sizeof (frv_elf_fpregset_t))
480     return &frv_linux_fpregset;
481
482   return NULL;
483 }
484
485 \f
486 static void
487 frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
488 {
489   /* Set the sigtramp frame sniffer.  */
490   frame_unwind_append_sniffer (gdbarch, frv_linux_sigtramp_frame_sniffer); 
491   set_gdbarch_regset_from_core_section (gdbarch,
492                                         frv_linux_regset_from_core_section);
493 }
494
495 static enum gdb_osabi
496 frv_linux_elf_osabi_sniffer (bfd *abfd)
497 {
498   int elf_flags;
499
500   elf_flags = elf_elfheader (abfd)->e_flags;
501
502   /* Assume GNU/Linux if using the FDPIC ABI.  If/when another OS shows
503      up that uses this ABI, we'll need to start using .note sections
504      or some such.  */
505   if (elf_flags & EF_FRV_FDPIC)
506     return GDB_OSABI_LINUX;
507   else
508     return GDB_OSABI_UNKNOWN;
509 }
510
511 /* Provide a prototype to silence -Wmissing-prototypes.  */
512 void _initialize_frv_linux_tdep (void);
513
514 void
515 _initialize_frv_linux_tdep (void)
516 {
517   gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, frv_linux_init_abi);
518   gdbarch_register_osabi_sniffer (bfd_arch_frv,
519                                   bfd_target_elf_flavour,
520                                   frv_linux_elf_osabi_sniffer);
521 }