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