]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/gdb/gdb/mipsfbsd-tdep.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / gdb / gdb / mipsfbsd-tdep.c
1 /***********************************************************************
2 Copyright 2003-2006 Raza Microelectronics, Inc.(RMI).
3 This is a derived work from software originally provided by the external
4 entity identified below. The licensing terms and warranties specified in
5 the header of the original work apply to this derived work.
6 Contribution by RMI: 
7 *****************************#RMI_1#**********************************/
8 /* Target-dependent code for MIPS systems running NetBSD.
9    Copyright 2002, 2003 Free Software Foundation, Inc.
10    Contributed by Wasabi Systems, Inc.
11
12    This file is part of GDB.
13
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 2 of the License, or
17    (at your option) any later version.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23
24    You should have received a copy of the GNU General Public License
25    along with this program; if not, write to the Free Software
26    Foundation, Inc., 59 Temple Place - Suite 330,
27    Boston, MA 02111-1307, USA.  */
28
29 #include "defs.h"
30 #include "gdbcore.h"
31 #include "regcache.h"
32 #include "target.h"
33 #include "value.h"
34 #include "osabi.h"
35
36 #include "nbsd-tdep.h"     
37 #include "mipsfbsd-tdep.h" 
38 #include "mips-tdep.h"     
39
40 #include "solib-svr4.h"
41
42 #include <sys/procfs.h>
43 #include "gregset.h"
44 #include "trad-frame.h"
45 #include "frame.h"
46 #include "frame-unwind.h"
47 #include "bfd.h"
48 #include "objfiles.h"
49
50 /* Conveniently, GDB uses the same register numbering as the
51    ptrace register structure used by NetBSD/mips.  */
52
53 void
54 mipsfbsd_supply_reg (char *regs, int regno)
55 {
56   int i;
57
58   for (i = 0; i <= PC_REGNUM; i++)
59     {
60       if (regno == i || regno == -1)
61         {
62           if (CANNOT_FETCH_REGISTER (i))
63             supply_register (i, NULL);
64           else
65             supply_register (i, regs + (i * mips_regsize (current_gdbarch)));
66         }
67     }
68 }
69 void 
70 supply_gregset (gdb_gregset_t *gregs)
71 {
72   mipsfbsd_supply_reg((char *)gregs, -1);
73 }
74
75 void
76 mipsfbsd_fill_reg (char *regs, int regno)
77 {
78   int i;
79
80   for (i = 0; i <= PC_REGNUM; i++)
81     if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
82       regcache_collect (i, regs + (i * mips_regsize (current_gdbarch)));
83 }
84
85 void 
86 fill_gregset (gdb_gregset_t  *gregs, int regno)
87 {
88   mipsfbsd_fill_reg ((char *)gregs, regno);
89 }
90
91 void
92 mipsfbsd_supply_fpreg (char *fpregs, int regno)
93 {
94   int i;
95
96   for (i = FP0_REGNUM;
97        i <= mips_regnum (current_gdbarch)->fp_implementation_revision;
98        i++)
99     {
100       if (regno == i || regno == -1)
101         {
102           if (CANNOT_FETCH_REGISTER (i))
103             supply_register (i, NULL);
104           else
105             supply_register (i, 
106                 fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
107         }
108     }
109 }
110
111 void 
112 supply_fpregset (gdb_fpregset_t *fpregs)
113 {
114   mipsfbsd_supply_fpreg((char *)fpregs, -1);
115 }
116
117 void
118 mipsfbsd_fill_fpreg (char *fpregs, int regno)
119 {
120   int i;
121
122   for (i = FP0_REGNUM; i <= mips_regnum (current_gdbarch)->fp_control_status;
123        i++)
124     if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
125       regcache_collect (i, 
126           fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
127 }
128
129 void 
130 fill_fpregset (gdb_fpregset_t *fpregs, int regno)
131 {
132   mipsfbsd_fill_fpreg ((char *)fpregs, regno);
133 }
134
135 static void
136 fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
137                       CORE_ADDR ignore)
138 {
139   char *regs, *fpregs;
140
141   /* We get everything from one section.  */
142   if (which != 0)
143     return;
144
145   regs = core_reg_sect;
146   fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
147
148   /* Integer registers.  */
149   mipsfbsd_supply_reg (regs, -1);
150
151   /* Floating point registers.  */
152   mipsfbsd_supply_fpreg (fpregs, -1);
153 }
154
155 static void
156 fetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
157                          CORE_ADDR ignore)
158 {
159   switch (which)
160     {
161     case 0:  /* Integer registers.  */
162       if (core_reg_size != SIZEOF_STRUCT_REG)
163         warning ("Wrong size register set in core file.");
164       else
165         mipsfbsd_supply_reg (core_reg_sect, -1);
166       break;
167
168     case 2:  /* Floating point registers.  */
169       if (core_reg_size != SIZEOF_STRUCT_FPREG)
170         warning ("Wrong size register set in core file.");
171       else
172         mipsfbsd_supply_fpreg (core_reg_sect, -1);
173       break;
174
175     default:
176       /* Don't know what kind of register request this is; just ignore it.  */
177       break;
178     }
179 }
180
181 static struct core_fns mipsfbsd_core_fns =
182 {
183   bfd_target_unknown_flavour,           /* core_flavour */
184   default_check_format,                 /* check_format */
185   default_core_sniffer,                 /* core_sniffer */
186   fetch_core_registers,                 /* core_read_registers */
187   NULL                                  /* next */
188 };
189
190 static struct core_fns mipsfbsd_elfcore_fns =
191 {
192   bfd_target_elf_flavour,               /* core_flavour */
193   default_check_format,                 /* check_format */
194   default_core_sniffer,                 /* core_sniffer */
195   fetch_elfcore_registers,              /* core_read_registers */
196   NULL                                  /* next */
197 };
198
199 /*
200  * MIPSFBSD Offsets
201  * 0x7fff0000    User high mem -> USRSTACK [64K]
202  * 
203  * 0x7ffefff0    ps_strings    -> 16 bytes
204  *
205  * 0x7ffeffec    sigcode       -> 44 bytes
206  *
207  * 0x7ffeffc4    sigcode end   env strings etc start
208  *
209  * XXX This is out-of-date and varies by ABI.
210  */
211 #define MIPS_FBSD_SIGTRAMP_START           (0x7ffeffc4)
212 #define MIPS_FBSD_SIGTRAMP_END             (0x7ffeffec)
213 #define MIPS_FBSD_SIGTRAMP_STACK_MOD_START (0x7ffeffc8)
214 #define MIPS_FBSD_SIGTRAMP_STACK_MOD_END   (0x7ffeffd8)
215
216 static LONGEST
217 mipsfbsd_sigtramp_offset (CORE_ADDR pc)
218 {
219   return pc < MIPS_FBSD_SIGTRAMP_END && 
220          pc >= MIPS_FBSD_SIGTRAMP_START ? 1 : -1;
221 }
222
223 static int
224 fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
225
226   return (name && strcmp (name, "__sigtramp") == 0);
227 }
228
229 static int
230 mipsfbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
231 {
232   return (fbsd_pc_in_sigtramp (pc, func_name)
233           || mipsfbsd_sigtramp_offset (pc) >= 0);
234 }
235
236 static int
237 is_sigtramp_sp_modified (CORE_ADDR pc)
238 {
239   return (pc >= MIPS_FBSD_SIGTRAMP_STACK_MOD_START &&
240           pc <= MIPS_FBSD_SIGTRAMP_STACK_MOD_END);
241 }
242   
243
244 /* Figure out where the longjmp will land.  We expect that we have
245    just entered longjmp and haven't yet setup the stack frame, so
246    the args are still in the argument regs.  A0_REGNUM points at the
247    jmp_buf structure from which we extract the PC that we will land
248    at.  The PC is copied into *pc.  This routine returns true on
249    success.  */
250
251 #define FBSD_MIPS_JB_PC                 (12)
252 #define FBSD_MIPS_JB_ELEMENT_SIZE       mips_regsize (current_gdbarch)
253 #define FBSD_MIPS_JB_OFFSET             (FBSD_MIPS_JB_PC * \
254                                          FBSD_MIPS_JB_ELEMENT_SIZE)
255
256 static int
257 mipsfbsd_get_longjmp_target (CORE_ADDR *pc)
258 {
259   CORE_ADDR jb_addr;
260   char *buf;
261
262   buf = alloca (FBSD_MIPS_JB_ELEMENT_SIZE);
263
264   jb_addr = read_register (A0_REGNUM);
265
266   if (target_read_memory (jb_addr + FBSD_MIPS_JB_OFFSET, buf,
267                           FBSD_MIPS_JB_ELEMENT_SIZE))
268     return 0;
269
270   *pc = extract_unsigned_integer (buf, FBSD_MIPS_JB_ELEMENT_SIZE);
271
272   return 1;
273 }
274
275 static int
276 mipsfbsd_cannot_fetch_register (int regno)
277 {
278   return (regno == ZERO_REGNUM
279           || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
280   /* XXX TODO: Are there other registers that we cannot fetch ? */
281 }
282
283 static int
284 mipsfbsd_cannot_store_register (int regno)
285 {
286   return (regno == ZERO_REGNUM
287           || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
288   /* XXX TODO: Are there other registers that we cannot write ? */
289 }
290
291 /* 
292  * This structure is defined in mips-tdep.c. 
293  */
294 struct mips_frame_cache
295 {
296   CORE_ADDR base;
297   struct trad_frame_saved_reg *saved_regs;
298 };
299
300 /*
301  * Prologue cache for sigtramp frame 
302  * When we land in sigtramp, sigcontext is saved on the
303  * stack just below the sigtramp's stack frame. We have
304  * the Registers saved at fixed offsets on the stack.
305  */
306
307 #define MIPS_FBSD_SIGTRAMP_STACK_SIZE    (48)
308 #define MIPS_FBSD_SIGCONTEXT_REG_OFFSET  (32)
309
310 static struct mips_frame_cache *
311 mipsfbsd_sigtramp_frame_cache (struct frame_info *next_frame,
312                                void **this_cache)
313 {
314   struct mips_frame_cache *cache;
315   CORE_ADDR  gregs_addr, sp, pc;
316   int regnum;
317   int sigtramp_stack_size;
318
319   if (*this_cache)
320     return *this_cache;
321
322   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
323   *this_cache = cache;
324  
325   cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
326    
327   /* 
328    * Get sp of next frame which is the adjusted sp of
329    * tramp code.
330    */
331   sp = frame_unwind_register_unsigned(next_frame, NUM_REGS + SP_REGNUM);
332   pc = frame_unwind_register_unsigned(next_frame, NUM_REGS + PC_REGNUM);
333   sigtramp_stack_size = is_sigtramp_sp_modified(pc) ? 
334           MIPS_FBSD_SIGTRAMP_STACK_SIZE : 0;
335   gregs_addr = sp + sigtramp_stack_size + MIPS_FBSD_SIGCONTEXT_REG_OFFSET;
336
337   for (regnum = 0; regnum < PC_REGNUM; regnum++) {
338     cache->saved_regs[NUM_REGS + regnum].addr = gregs_addr + 
339        regnum * mips_regsize (current_gdbarch);
340   }
341   /* Only retrieve PC and SP */
342   cache->saved_regs[NUM_REGS + SP_REGNUM].addr = gregs_addr +
343        SP_REGNUM * ( mips_regsize (current_gdbarch));
344
345   cache->saved_regs[NUM_REGS + RA_REGNUM].addr = gregs_addr +
346         RA_REGNUM * ( mips_regsize (current_gdbarch));
347
348   cache->base = get_frame_memory_unsigned (next_frame,
349     cache->saved_regs[NUM_REGS + SP_REGNUM].addr,
350     mips_regsize (current_gdbarch)); 
351
352   /* Todo: Floating point registers */
353
354   cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
355     =  cache->saved_regs[NUM_REGS + RA_REGNUM];
356
357   return *this_cache;
358 }
359
360 static void 
361 mipsfbsd_sigtramp_frame_this_id (struct frame_info *next_frame,
362                                  void **this_cache,
363                                  struct frame_id *this_id)
364 {
365   struct mips_frame_cache *cache =
366     mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
367
368     (*this_id) = frame_id_build (cache->base, 
369         cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
370 }
371
372 static void
373 mipsfbsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
374                                        void **this_cache,
375                                        int regnum, int *optimizedp,
376                                        enum lval_type *lvalp,
377                                        CORE_ADDR *addrp,
378                                        int *realnump, void *valuep)
379 {
380   struct mips_frame_cache *cache =
381     mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
382
383     trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
384                               optimizedp, lvalp, addrp, realnump, valuep);
385 }
386
387
388 static const struct frame_unwind mipsfbsd_sigtramp_frame_unwind = 
389 {
390   SIGTRAMP_FRAME,
391   mipsfbsd_sigtramp_frame_this_id,
392   mipsfbsd_sigtramp_frame_prev_register
393 };
394
395 static const struct frame_unwind *
396 mipsfbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
397 {
398   CORE_ADDR pc = frame_pc_unwind (next_frame);
399   char *name;
400
401   find_pc_partial_function (pc, &name, NULL, NULL);
402   if (mipsfbsd_pc_in_sigtramp (pc, name) )
403     return &mipsfbsd_sigtramp_frame_unwind;
404
405   return NULL;
406 }
407
408 /*
409  * Find out if PC has landed into dynamic library stub.
410  * We can find it by seeing if the name of the object
411  * file section where the PC lies is "MIPS.stubs"
412  */
413
414 int 
415 mipsfbsd_in_stub_section (CORE_ADDR pc, char *name)
416 {
417   struct obj_section *s;
418   int retval = 0;
419
420   s = find_pc_section (pc);
421
422   retval = (s != NULL
423             && s->the_bfd_section->name != NULL
424             && strcmp (s->the_bfd_section->name, ".MIPS.stubs") == 0);
425   return (retval);
426 }
427
428
429 /*
430  * Prologue cache for dynamic library stub frame.
431  * This stub does not modify the SP, so we set the
432  * cache base to calling frame's SP
433  */
434 static struct mips_frame_cache *
435 mipsfbsd_stub_frame_cache (struct frame_info *next_frame,
436                            void **this_cache)
437 {
438   struct mips_frame_cache *cache;
439
440   if (*this_cache)
441     return *this_cache;
442
443   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
444   *this_cache = cache;
445
446   cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
447
448
449   cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].realreg =
450     NUM_REGS + RA_REGNUM;
451   cache->base = frame_unwind_register_unsigned (next_frame,
452    NUM_REGS + SP_REGNUM); 
453
454   return (*this_cache);
455 }
456
457  
458 static void
459 mipsfbsd_stub_frame_this_id (struct frame_info *next_frame,
460                              void **this_cache,
461                              struct frame_id *this_id)
462 {
463   struct mips_frame_cache *cache =
464     mipsfbsd_stub_frame_cache (next_frame, this_cache);
465
466     (*this_id) = frame_id_build (cache->base,
467         cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
468 }
469
470 static void
471 mipsfbsd_stub_frame_prev_register (struct frame_info *next_frame,
472                                    void **this_cache,
473                                    int regnum, int *optimizedp,
474                                    enum lval_type *lvalp, CORE_ADDR *addrp,
475                                    int *realnump, void *valuep)
476 {
477   struct mips_frame_cache *cache = 
478     mipsfbsd_stub_frame_cache (next_frame, this_cache);
479
480   trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
481                               optimizedp, lvalp, addrp, realnump, valuep);
482 }
483
484  
485  
486 static const struct frame_unwind mipsfbsd_stub_frame_unwind = {
487   NORMAL_FRAME,
488   mipsfbsd_stub_frame_this_id,
489   mipsfbsd_stub_frame_prev_register
490 };
491
492 static const struct frame_unwind *
493 mipsfbsd_stub_frame_sniffer (struct frame_info *next_frame)
494 {
495    CORE_ADDR pc = frame_pc_unwind (next_frame);
496    
497    if (mipsfbsd_in_stub_section(pc, NULL)) 
498      return &mipsfbsd_stub_frame_unwind;
499    
500    return NULL;
501 }
502      
503 /*
504  *  typedef struct link_map {
505  *          caddr_t         l_addr;                 /* Base Address of library
506  *  #ifdef __mips__
507  *          caddr_t         l_offs;                 /* Load Offset of library
508  *  #endif
509  *          const char      *l_name;                /* Absolute Path to Library
510  *          const void      *l_ld;                  /* Pointer to .dynamic in memory
511  *          struct link_map *l_next, *l_prev;       /* linked list of of mapped libs
512  *  } Link_map;
513  *
514  *  struct r_debug {
515  *          int             r_version;              /* not used
516  *          struct link_map *r_map;                 /* list of loaded images
517  *          void            (*r_brk)(struct r_debug *, struct link_map *);
518  *                                                  /* pointer to break point
519  *          enum {
520  *              RT_CONSISTENT,                      /* things are stable
521  *              RT_ADD,                             /* adding a shared library
522  *              RT_DELETE                           /* removing a shared library
523  *          }               r_state;
524  *  };
525  *
526  */
527
528 static struct link_map_offsets *
529 mipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
530 {
531   static struct link_map_offsets lmo;
532   static struct link_map_offsets *lmp = NULL;
533
534   if (lmp == NULL)
535     {
536       lmp = &lmo;
537
538       lmo.r_debug_size = 16;
539
540       lmo.r_map_offset = 4;
541       lmo.r_map_size   = 4;
542
543       lmo.link_map_size = 24;
544
545       lmo.l_addr_offset = 0;
546       lmo.l_addr_size   = 4;
547
548       lmo.l_name_offset = 8;
549       lmo.l_name_size   = 4;
550
551       lmo.l_next_offset = 16;
552       lmo.l_next_size   = 4;
553
554       lmo.l_prev_offset = 20;
555       lmo.l_prev_size   = 4;
556     }
557
558   return lmp;
559 }
560
561 static void
562 mipsfbsd_init_abi (struct gdbarch_info info,
563                    struct gdbarch *gdbarch)
564 {
565   set_gdbarch_pc_in_sigtramp (gdbarch, mipsfbsd_pc_in_sigtramp);
566
567   set_gdbarch_get_longjmp_target (gdbarch, mipsfbsd_get_longjmp_target);
568
569   set_gdbarch_cannot_fetch_register (gdbarch, mipsfbsd_cannot_fetch_register);
570   set_gdbarch_cannot_store_register (gdbarch, mipsfbsd_cannot_store_register);
571
572   set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
573   set_solib_svr4_fetch_link_map_offsets (gdbarch,
574                             mipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets);
575   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
576   set_gdbarch_in_solib_call_trampoline (gdbarch, mipsfbsd_in_stub_section);
577
578   /* frame sniffers */
579   frame_unwind_append_sniffer (gdbarch, mipsfbsd_sigtramp_frame_sniffer);
580   frame_unwind_append_sniffer (gdbarch, mipsfbsd_stub_frame_sniffer);
581
582 }
583
584 void
585 _initialize_mipsfbsd_tdep (void)
586 {
587   gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD_ELF,
588                           mipsfbsd_init_abi);
589   add_core_fns (&mipsfbsd_core_fns);
590   add_core_fns (&mipsfbsd_elfcore_fns);
591 }