OSDN Git Service

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