xref: /openbsd-src/gnu/usr.bin/binutils/gdb/frv-linux-tdep.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1*11efff7fSkettenis /* Target-dependent code for GNU/Linux running on the Fujitsu FR-V,
2*11efff7fSkettenis    for GDB.
3*11efff7fSkettenis    Copyright 2004 Free Software Foundation, Inc.
4*11efff7fSkettenis 
5*11efff7fSkettenis    This file is part of GDB.
6*11efff7fSkettenis 
7*11efff7fSkettenis    This program is free software; you can redistribute it and/or modify
8*11efff7fSkettenis    it under the terms of the GNU General Public License as published by
9*11efff7fSkettenis    the Free Software Foundation; either version 2 of the License, or
10*11efff7fSkettenis    (at your option) any later version.
11*11efff7fSkettenis 
12*11efff7fSkettenis    This program is distributed in the hope that it will be useful,
13*11efff7fSkettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*11efff7fSkettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*11efff7fSkettenis    GNU General Public License for more details.
16*11efff7fSkettenis 
17*11efff7fSkettenis    You should have received a copy of the GNU General Public License
18*11efff7fSkettenis    along with this program; if not, write to the Free Software
19*11efff7fSkettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*11efff7fSkettenis    Boston, MA 02111-1307, USA.  */
21*11efff7fSkettenis 
22*11efff7fSkettenis #include "defs.h"
23*11efff7fSkettenis #include "target.h"
24*11efff7fSkettenis #include "frame.h"
25*11efff7fSkettenis #include "osabi.h"
26*11efff7fSkettenis #include "elf-bfd.h"
27*11efff7fSkettenis #include "elf/frv.h"
28*11efff7fSkettenis #include "frv-tdep.h"
29*11efff7fSkettenis #include "trad-frame.h"
30*11efff7fSkettenis #include "frame-unwind.h"
31*11efff7fSkettenis 
32*11efff7fSkettenis /* Define the size (in bytes) of an FR-V instruction.  */
33*11efff7fSkettenis static const int frv_instr_size = 4;
34*11efff7fSkettenis 
35*11efff7fSkettenis enum {
36*11efff7fSkettenis   NORMAL_SIGTRAMP = 1,
37*11efff7fSkettenis   RT_SIGTRAMP = 2
38*11efff7fSkettenis };
39*11efff7fSkettenis 
40*11efff7fSkettenis static int
frv_linux_pc_in_sigtramp(CORE_ADDR pc,char * name)41*11efff7fSkettenis frv_linux_pc_in_sigtramp (CORE_ADDR pc, char *name)
42*11efff7fSkettenis {
43*11efff7fSkettenis   char buf[frv_instr_size];
44*11efff7fSkettenis   LONGEST instr;
45*11efff7fSkettenis   int retval = 0;
46*11efff7fSkettenis 
47*11efff7fSkettenis   if (target_read_memory (pc, buf, sizeof buf) != 0)
48*11efff7fSkettenis     return 0;
49*11efff7fSkettenis 
50*11efff7fSkettenis   instr = extract_unsigned_integer (buf, sizeof buf);
51*11efff7fSkettenis 
52*11efff7fSkettenis   if (instr == 0x8efc0077)	/* setlos #__NR_sigreturn, gr7 */
53*11efff7fSkettenis     retval = NORMAL_SIGTRAMP;
54*11efff7fSkettenis   else if (instr -= 0x8efc00ad)	/* setlos #__NR_rt_sigreturn, gr7 */
55*11efff7fSkettenis     retval = RT_SIGTRAMP;
56*11efff7fSkettenis   else
57*11efff7fSkettenis     return 0;
58*11efff7fSkettenis 
59*11efff7fSkettenis   if (target_read_memory (pc + frv_instr_size, buf, sizeof buf) != 0)
60*11efff7fSkettenis     return 0;
61*11efff7fSkettenis   instr = extract_unsigned_integer (buf, sizeof buf);
62*11efff7fSkettenis   if (instr != 0xc0700000)	/* tira	gr0, 0 */
63*11efff7fSkettenis     return 0;
64*11efff7fSkettenis 
65*11efff7fSkettenis   /* If we get this far, we'll return a non-zero value, either
66*11efff7fSkettenis      NORMAL_SIGTRAMP (1) or RT_SIGTRAMP (2).  */
67*11efff7fSkettenis   return retval;
68*11efff7fSkettenis }
69*11efff7fSkettenis 
70*11efff7fSkettenis /* Given NEXT_FRAME, "callee" frame of the sigtramp frame that we
71*11efff7fSkettenis    wish to decode, and REGNO, one of the frv register numbers defined
72*11efff7fSkettenis    in frv-tdep.h, return the address of the saved register (corresponding
73*11efff7fSkettenis    to REGNO) in the sigtramp frame.  Return -1 if the register is not
74*11efff7fSkettenis    found in the sigtramp frame.  The magic numbers in the code below
75*11efff7fSkettenis    were computed by examining the following kernel structs:
76*11efff7fSkettenis 
77*11efff7fSkettenis    From arch/frvnommu/signal.c:
78*11efff7fSkettenis 
79*11efff7fSkettenis       struct sigframe
80*11efff7fSkettenis       {
81*11efff7fSkettenis 	      void (*pretcode)(void);
82*11efff7fSkettenis 	      int sig;
83*11efff7fSkettenis 	      struct sigcontext sc;
84*11efff7fSkettenis 	      unsigned long extramask[_NSIG_WORDS-1];
85*11efff7fSkettenis 	      uint32_t retcode[2];
86*11efff7fSkettenis       };
87*11efff7fSkettenis 
88*11efff7fSkettenis       struct rt_sigframe
89*11efff7fSkettenis       {
90*11efff7fSkettenis 	      void (*pretcode)(void);
91*11efff7fSkettenis 	      int sig;
92*11efff7fSkettenis 	      struct siginfo *pinfo;
93*11efff7fSkettenis 	      void *puc;
94*11efff7fSkettenis 	      struct siginfo info;
95*11efff7fSkettenis 	      struct ucontext uc;
96*11efff7fSkettenis 	      uint32_t retcode[2];
97*11efff7fSkettenis       };
98*11efff7fSkettenis 
99*11efff7fSkettenis    From include/asm-frvnommu/ucontext.h:
100*11efff7fSkettenis 
101*11efff7fSkettenis       struct ucontext {
102*11efff7fSkettenis 	      unsigned long		uc_flags;
103*11efff7fSkettenis 	      struct ucontext		*uc_link;
104*11efff7fSkettenis 	      stack_t			uc_stack;
105*11efff7fSkettenis 	      struct sigcontext	uc_mcontext;
106*11efff7fSkettenis 	      sigset_t		uc_sigmask;
107*11efff7fSkettenis       };
108*11efff7fSkettenis 
109*11efff7fSkettenis    From include/asm-frvnommu/sigcontext.h:
110*11efff7fSkettenis 
111*11efff7fSkettenis       struct sigcontext {
112*11efff7fSkettenis 	      struct user_context	sc_context;
113*11efff7fSkettenis 	      unsigned long		sc_oldmask;
114*11efff7fSkettenis       } __attribute__((aligned(8)));
115*11efff7fSkettenis 
116*11efff7fSkettenis    From include/asm-frvnommu/registers.h:
117*11efff7fSkettenis       struct user_int_regs
118*11efff7fSkettenis       {
119*11efff7fSkettenis 	      unsigned long		psr;
120*11efff7fSkettenis 	      unsigned long		isr;
121*11efff7fSkettenis 	      unsigned long		ccr;
122*11efff7fSkettenis 	      unsigned long		cccr;
123*11efff7fSkettenis 	      unsigned long		lr;
124*11efff7fSkettenis 	      unsigned long		lcr;
125*11efff7fSkettenis 	      unsigned long		pc;
126*11efff7fSkettenis 	      unsigned long		__status;
127*11efff7fSkettenis 	      unsigned long		syscallno;
128*11efff7fSkettenis 	      unsigned long		orig_gr8;
129*11efff7fSkettenis 	      unsigned long		gner[2];
130*11efff7fSkettenis 	      unsigned long long	iacc[1];
131*11efff7fSkettenis 
132*11efff7fSkettenis 	      union {
133*11efff7fSkettenis 		      unsigned long	tbr;
134*11efff7fSkettenis 		      unsigned long	gr[64];
135*11efff7fSkettenis 	      };
136*11efff7fSkettenis       };
137*11efff7fSkettenis 
138*11efff7fSkettenis       struct user_fpmedia_regs
139*11efff7fSkettenis       {
140*11efff7fSkettenis 	      unsigned long	fr[64];
141*11efff7fSkettenis 	      unsigned long	fner[2];
142*11efff7fSkettenis 	      unsigned long	msr[2];
143*11efff7fSkettenis 	      unsigned long	acc[8];
144*11efff7fSkettenis 	      unsigned char	accg[8];
145*11efff7fSkettenis 	      unsigned long	fsr[1];
146*11efff7fSkettenis       };
147*11efff7fSkettenis 
148*11efff7fSkettenis       struct user_context
149*11efff7fSkettenis       {
150*11efff7fSkettenis 	      struct user_int_regs		i;
151*11efff7fSkettenis 	      struct user_fpmedia_regs	f;
152*11efff7fSkettenis 
153*11efff7fSkettenis 	      void *extension;
154*11efff7fSkettenis       } __attribute__((aligned(8)));  */
155*11efff7fSkettenis 
156*11efff7fSkettenis static LONGEST
frv_linux_sigcontext_reg_addr(struct frame_info * next_frame,int regno,CORE_ADDR * sc_addr_cache_ptr)157*11efff7fSkettenis frv_linux_sigcontext_reg_addr (struct frame_info *next_frame, int regno,
158*11efff7fSkettenis                                CORE_ADDR *sc_addr_cache_ptr)
159*11efff7fSkettenis {
160*11efff7fSkettenis   CORE_ADDR sc_addr;
161*11efff7fSkettenis 
162*11efff7fSkettenis   if (sc_addr_cache_ptr && *sc_addr_cache_ptr)
163*11efff7fSkettenis     {
164*11efff7fSkettenis       sc_addr = *sc_addr_cache_ptr;
165*11efff7fSkettenis     }
166*11efff7fSkettenis   else
167*11efff7fSkettenis     {
168*11efff7fSkettenis       CORE_ADDR pc, sp;
169*11efff7fSkettenis       char buf[4];
170*11efff7fSkettenis       int tramp_type;
171*11efff7fSkettenis 
172*11efff7fSkettenis       pc = frame_pc_unwind (next_frame);
173*11efff7fSkettenis       tramp_type = frv_linux_pc_in_sigtramp (pc, 0);
174*11efff7fSkettenis 
175*11efff7fSkettenis       frame_unwind_register (next_frame, sp_regnum, buf);
176*11efff7fSkettenis       sp = extract_unsigned_integer (buf, sizeof buf);
177*11efff7fSkettenis 
178*11efff7fSkettenis       if (tramp_type == NORMAL_SIGTRAMP)
179*11efff7fSkettenis 	{
180*11efff7fSkettenis 	  /* For a normal sigtramp frame, the sigcontext struct starts
181*11efff7fSkettenis 	     at SP + 8.  */
182*11efff7fSkettenis 	  sc_addr = sp + 8;
183*11efff7fSkettenis 	}
184*11efff7fSkettenis       else if (tramp_type == RT_SIGTRAMP)
185*11efff7fSkettenis 	{
186*11efff7fSkettenis 	  /* For a realtime sigtramp frame, SP + 12 contains a pointer
187*11efff7fSkettenis 	     to the a ucontext struct.  The ucontext struct contains
188*11efff7fSkettenis 	     a sigcontext struct starting 12 bytes in.  */
189*11efff7fSkettenis 	  if (target_read_memory (sp + 12, buf, sizeof buf) != 0)
190*11efff7fSkettenis 	    {
191*11efff7fSkettenis 	      warning ("Can't read realtime sigtramp frame.");
192*11efff7fSkettenis 	      return 0;
193*11efff7fSkettenis 	    }
194*11efff7fSkettenis 	  sc_addr = extract_unsigned_integer (buf, sizeof buf);
195*11efff7fSkettenis 	  sc_addr += 12;
196*11efff7fSkettenis 	}
197*11efff7fSkettenis       else
198*11efff7fSkettenis 	internal_error (__FILE__, __LINE__, "not a signal trampoline");
199*11efff7fSkettenis 
200*11efff7fSkettenis       if (sc_addr_cache_ptr)
201*11efff7fSkettenis 	*sc_addr_cache_ptr = sc_addr;
202*11efff7fSkettenis     }
203*11efff7fSkettenis 
204*11efff7fSkettenis   switch (regno)
205*11efff7fSkettenis     {
206*11efff7fSkettenis     case psr_regnum :
207*11efff7fSkettenis       return sc_addr + 0;
208*11efff7fSkettenis     /* sc_addr + 4 has "isr", the Integer Status Register.  */
209*11efff7fSkettenis     case ccr_regnum :
210*11efff7fSkettenis       return sc_addr + 8;
211*11efff7fSkettenis     case cccr_regnum :
212*11efff7fSkettenis       return sc_addr + 12;
213*11efff7fSkettenis     case lr_regnum :
214*11efff7fSkettenis       return sc_addr + 16;
215*11efff7fSkettenis     case lcr_regnum :
216*11efff7fSkettenis       return sc_addr + 20;
217*11efff7fSkettenis     case pc_regnum :
218*11efff7fSkettenis       return sc_addr + 24;
219*11efff7fSkettenis     /* sc_addr + 28 is __status, the exception status.
220*11efff7fSkettenis        sc_addr + 32 is syscallno, the syscall number or -1.
221*11efff7fSkettenis        sc_addr + 36 is orig_gr8, the original syscall arg #1.
222*11efff7fSkettenis        sc_addr + 40 is gner[0].
223*11efff7fSkettenis        sc_addr + 44 is gner[1]. */
224*11efff7fSkettenis     case iacc0h_regnum :
225*11efff7fSkettenis       return sc_addr + 48;
226*11efff7fSkettenis     case iacc0l_regnum :
227*11efff7fSkettenis       return sc_addr + 52;
228*11efff7fSkettenis     default :
229*11efff7fSkettenis       if (first_gpr_regnum <= regno && regno <= last_gpr_regnum)
230*11efff7fSkettenis 	return sc_addr + 56 + 4 * (regno - first_gpr_regnum);
231*11efff7fSkettenis       else if (first_fpr_regnum <= regno && regno <= last_fpr_regnum)
232*11efff7fSkettenis 	return sc_addr + 312 + 4 * (regno - first_fpr_regnum);
233*11efff7fSkettenis       else
234*11efff7fSkettenis 	return -1;  /* not saved. */
235*11efff7fSkettenis     }
236*11efff7fSkettenis }
237*11efff7fSkettenis 
238*11efff7fSkettenis /* Signal trampolines.  */
239*11efff7fSkettenis 
240*11efff7fSkettenis static struct trad_frame_cache *
frv_linux_sigtramp_frame_cache(struct frame_info * next_frame,void ** this_cache)241*11efff7fSkettenis frv_linux_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
242*11efff7fSkettenis {
243*11efff7fSkettenis   struct trad_frame_cache *cache;
244*11efff7fSkettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
245*11efff7fSkettenis   CORE_ADDR addr;
246*11efff7fSkettenis   char buf[4];
247*11efff7fSkettenis   int regnum;
248*11efff7fSkettenis   CORE_ADDR sc_addr_cache_val = 0;
249*11efff7fSkettenis   struct frame_id this_id;
250*11efff7fSkettenis 
251*11efff7fSkettenis   if (*this_cache)
252*11efff7fSkettenis     return *this_cache;
253*11efff7fSkettenis 
254*11efff7fSkettenis   cache = trad_frame_cache_zalloc (next_frame);
255*11efff7fSkettenis 
256*11efff7fSkettenis   /* FIXME: cagney/2004-05-01: This is is long standing broken code.
257*11efff7fSkettenis      The frame ID's code address should be the start-address of the
258*11efff7fSkettenis      signal trampoline and not the current PC within that
259*11efff7fSkettenis      trampoline.  */
260*11efff7fSkettenis   frame_unwind_register (next_frame, sp_regnum, buf);
261*11efff7fSkettenis   this_id = frame_id_build (extract_unsigned_integer (buf, sizeof buf),
262*11efff7fSkettenis 			    frame_pc_unwind (next_frame));
263*11efff7fSkettenis   trad_frame_set_id (cache, this_id);
264*11efff7fSkettenis 
265*11efff7fSkettenis   for (regnum = 0; regnum < frv_num_regs; regnum++)
266*11efff7fSkettenis     {
267*11efff7fSkettenis       LONGEST reg_addr = frv_linux_sigcontext_reg_addr (next_frame, regnum,
268*11efff7fSkettenis 							&sc_addr_cache_val);
269*11efff7fSkettenis       if (reg_addr != -1)
270*11efff7fSkettenis 	trad_frame_set_reg_addr (cache, regnum, reg_addr);
271*11efff7fSkettenis     }
272*11efff7fSkettenis 
273*11efff7fSkettenis   *this_cache = cache;
274*11efff7fSkettenis   return cache;
275*11efff7fSkettenis }
276*11efff7fSkettenis 
277*11efff7fSkettenis static void
frv_linux_sigtramp_frame_this_id(struct frame_info * next_frame,void ** this_cache,struct frame_id * this_id)278*11efff7fSkettenis frv_linux_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
279*11efff7fSkettenis 			     struct frame_id *this_id)
280*11efff7fSkettenis {
281*11efff7fSkettenis   struct trad_frame_cache *cache =
282*11efff7fSkettenis     frv_linux_sigtramp_frame_cache (next_frame, this_cache);
283*11efff7fSkettenis   trad_frame_get_id (cache, this_id);
284*11efff7fSkettenis }
285*11efff7fSkettenis 
286*11efff7fSkettenis static void
frv_linux_sigtramp_frame_prev_register(struct frame_info * next_frame,void ** this_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * valuep)287*11efff7fSkettenis frv_linux_sigtramp_frame_prev_register (struct frame_info *next_frame,
288*11efff7fSkettenis 				   void **this_cache,
289*11efff7fSkettenis 				   int regnum, int *optimizedp,
290*11efff7fSkettenis 				   enum lval_type *lvalp, CORE_ADDR *addrp,
291*11efff7fSkettenis 				   int *realnump, void *valuep)
292*11efff7fSkettenis {
293*11efff7fSkettenis   /* Make sure we've initialized the cache.  */
294*11efff7fSkettenis   struct trad_frame_cache *cache =
295*11efff7fSkettenis     frv_linux_sigtramp_frame_cache (next_frame, this_cache);
296*11efff7fSkettenis   trad_frame_get_register (cache, next_frame, regnum, optimizedp, lvalp,
297*11efff7fSkettenis 			   addrp, realnump, valuep);
298*11efff7fSkettenis }
299*11efff7fSkettenis 
300*11efff7fSkettenis static const struct frame_unwind frv_linux_sigtramp_frame_unwind =
301*11efff7fSkettenis {
302*11efff7fSkettenis   SIGTRAMP_FRAME,
303*11efff7fSkettenis   frv_linux_sigtramp_frame_this_id,
304*11efff7fSkettenis   frv_linux_sigtramp_frame_prev_register
305*11efff7fSkettenis };
306*11efff7fSkettenis 
307*11efff7fSkettenis static const struct frame_unwind *
frv_linux_sigtramp_frame_sniffer(struct frame_info * next_frame)308*11efff7fSkettenis frv_linux_sigtramp_frame_sniffer (struct frame_info *next_frame)
309*11efff7fSkettenis {
310*11efff7fSkettenis   CORE_ADDR pc = frame_pc_unwind (next_frame);
311*11efff7fSkettenis   char *name;
312*11efff7fSkettenis 
313*11efff7fSkettenis   find_pc_partial_function (pc, &name, NULL, NULL);
314*11efff7fSkettenis   if (frv_linux_pc_in_sigtramp (pc, name))
315*11efff7fSkettenis     return &frv_linux_sigtramp_frame_unwind;
316*11efff7fSkettenis 
317*11efff7fSkettenis   return NULL;
318*11efff7fSkettenis }
319*11efff7fSkettenis 
320*11efff7fSkettenis static void
frv_linux_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)321*11efff7fSkettenis frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
322*11efff7fSkettenis {
323*11efff7fSkettenis   /* Set the sigtramp frame sniffer.  */
324*11efff7fSkettenis   frame_unwind_append_sniffer (gdbarch, frv_linux_sigtramp_frame_sniffer);
325*11efff7fSkettenis }
326*11efff7fSkettenis 
327*11efff7fSkettenis static enum gdb_osabi
frv_linux_elf_osabi_sniffer(bfd * abfd)328*11efff7fSkettenis frv_linux_elf_osabi_sniffer (bfd *abfd)
329*11efff7fSkettenis {
330*11efff7fSkettenis   int elf_flags;
331*11efff7fSkettenis 
332*11efff7fSkettenis   elf_flags = elf_elfheader (abfd)->e_flags;
333*11efff7fSkettenis 
334*11efff7fSkettenis   /* Assume GNU/Linux if using the FDPIC ABI.  If/when another OS shows
335*11efff7fSkettenis      up that uses this ABI, we'll need to start using .note sections
336*11efff7fSkettenis      or some such.  */
337*11efff7fSkettenis   if (elf_flags & EF_FRV_FDPIC)
338*11efff7fSkettenis     return GDB_OSABI_LINUX;
339*11efff7fSkettenis   else
340*11efff7fSkettenis     return GDB_OSABI_UNKNOWN;
341*11efff7fSkettenis }
342*11efff7fSkettenis 
343*11efff7fSkettenis /* Provide a prototype to silence -Wmissing-prototypes.  */
344*11efff7fSkettenis void _initialize_frv_linux_tdep (void);
345*11efff7fSkettenis 
346*11efff7fSkettenis void
_initialize_frv_linux_tdep(void)347*11efff7fSkettenis _initialize_frv_linux_tdep (void)
348*11efff7fSkettenis {
349*11efff7fSkettenis   gdbarch_register_osabi (bfd_arch_frv, 0, GDB_OSABI_LINUX, frv_linux_init_abi);
350*11efff7fSkettenis   gdbarch_register_osabi_sniffer (bfd_arch_frv,
351*11efff7fSkettenis 				  bfd_target_elf_flavour,
352*11efff7fSkettenis 				  frv_linux_elf_osabi_sniffer);
353*11efff7fSkettenis }
354