]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdb/gdb/mipsfbsd-tdep.c
IFH@204581
[FreeBSD/FreeBSD.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
191 /*
192  * MIPSFBSD Offsets
193  * 0x7fff0000    User high mem -> USRSTACK [64K]
194  * 
195  * 0x7ffefff0    ps_strings    -> 16 bytes
196  *
197  * 0x7ffeffec    sigcode       -> 44 bytes
198  *
199  * 0x7ffeffc4    sigcode end   env strings etc start
200  */
201 #define MIPS_FBSD_SIGTRAMP_START           (0x7ffeffc4)
202 #define MIPS_FBSD_SIGTRAMP_END             (0x7ffeffec)
203 #define MIPS_FBSD_SIGTRAMP_STACK_MOD_START (0x7ffeffc8)
204 #define MIPS_FBSD_SIGTRAMP_STACK_MOD_END   (0x7ffeffd8)
205
206 static LONGEST
207 mipsfbsd_sigtramp_offset (CORE_ADDR pc)
208 {
209   return pc < MIPS_FBSD_SIGTRAMP_END && 
210          pc >= MIPS_FBSD_SIGTRAMP_START ? 1 : -1;
211 }
212
213 static int
214 fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
215
216   return (name && strcmp (name, "__sigtramp") == 0);
217 }
218
219 static int
220 mipsfbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
221 {
222   return (fbsd_pc_in_sigtramp (pc, func_name)
223           || mipsfbsd_sigtramp_offset (pc) >= 0);
224 }
225
226 static int
227 is_sigtramp_sp_modified (CORE_ADDR pc)
228 {
229   return (pc >= MIPS_FBSD_SIGTRAMP_STACK_MOD_START &&
230           pc <= MIPS_FBSD_SIGTRAMP_STACK_MOD_END);
231 }
232   
233
234 /* Figure out where the longjmp will land.  We expect that we have
235    just entered longjmp and haven't yet setup the stack frame, so
236    the args are still in the argument regs.  A0_REGNUM points at the
237    jmp_buf structure from which we extract the PC that we will land
238    at.  The PC is copied into *pc.  This routine returns true on
239    success.  */
240
241 #define FBSD_MIPS_JB_PC                 (12)
242 #define FBSD_MIPS_JB_ELEMENT_SIZE       mips_regsize (current_gdbarch)
243 #define FBSD_MIPS_JB_OFFSET             (FBSD_MIPS_JB_PC * \
244                                          FBSD_MIPS_JB_ELEMENT_SIZE)
245
246 static int
247 mipsfbsd_get_longjmp_target (CORE_ADDR *pc)
248 {
249   CORE_ADDR jb_addr;
250   char *buf;
251
252   buf = alloca (FBSD_MIPS_JB_ELEMENT_SIZE);
253
254   jb_addr = read_register (A0_REGNUM);
255
256   if (target_read_memory (jb_addr + FBSD_MIPS_JB_OFFSET, buf,
257                           FBSD_MIPS_JB_ELEMENT_SIZE))
258     return 0;
259
260   *pc = extract_unsigned_integer (buf, FBSD_MIPS_JB_ELEMENT_SIZE);
261
262   return 1;
263 }
264
265 static int
266 mipsfbsd_cannot_fetch_register (int regno)
267 {
268   return (regno == ZERO_REGNUM
269           || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
270   /* XXX TODO: Are there other registers that we cannot fetch ? */
271 }
272
273 static int
274 mipsfbsd_cannot_store_register (int regno)
275 {
276   return (regno == ZERO_REGNUM
277           || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
278   /* XXX TODO: Are there other registers that we cannot write ? */
279 }
280
281 /* 
282  * This structure is defined in mips-tdep.c. 
283  */
284 struct mips_frame_cache
285 {
286   CORE_ADDR base;
287   struct trad_frame_saved_reg *saved_regs;
288 };
289
290 /*
291  * Prologue cache for sigtramp frame 
292  * When we land in sigtramp, sigcontext is saved on the
293  * stack just below the sigtramp's stack frame. We have
294  * the Registers saved at fixed offsets on the stack.
295  */
296
297 #define MIPS_FBSD_SIGTRAMP_STACK_SIZE    (48)
298 #define MIPS_FBSD_SIGCONTEXT_REG_OFFSET  (32)
299
300 static struct mips_frame_cache *
301 mipsfbsd_sigtramp_frame_cache (struct frame_info *next_frame,
302                                void **this_cache)
303 {
304   struct mips_frame_cache *cache;
305   CORE_ADDR  gregs_addr, sp, pc;
306   int regnum;
307   int sigtramp_stack_size;
308
309   if (*this_cache)
310     return *this_cache;
311
312   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
313   *this_cache = cache;
314  
315   cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
316    
317   /* 
318    * Get sp of next frame which is the adjusted sp of
319    * tramp code.
320    */
321   sp = frame_unwind_register_unsigned(next_frame, NUM_REGS + SP_REGNUM);
322   pc = frame_unwind_register_unsigned(next_frame, NUM_REGS + PC_REGNUM);
323   sigtramp_stack_size = is_sigtramp_sp_modified(pc) ? 
324           MIPS_FBSD_SIGTRAMP_STACK_SIZE : 0;
325   gregs_addr = sp + sigtramp_stack_size + MIPS_FBSD_SIGCONTEXT_REG_OFFSET;
326
327   for (regnum = 0; regnum < PC_REGNUM; regnum++) {
328     cache->saved_regs[NUM_REGS + regnum].addr = gregs_addr + 
329        regnum * mips_regsize (current_gdbarch);
330   }
331   /* Only retrieve PC and SP */
332   cache->saved_regs[NUM_REGS + SP_REGNUM].addr = gregs_addr +
333        SP_REGNUM * ( mips_regsize (current_gdbarch));
334
335   cache->saved_regs[NUM_REGS + RA_REGNUM].addr = gregs_addr +
336         RA_REGNUM * ( mips_regsize (current_gdbarch));
337
338   cache->base = get_frame_memory_unsigned (next_frame,
339     cache->saved_regs[NUM_REGS + SP_REGNUM].addr,
340     mips_regsize (current_gdbarch)); 
341
342   /* Todo: Floating point registers */
343
344   cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
345     =  cache->saved_regs[NUM_REGS + RA_REGNUM];
346
347   return *this_cache;
348 }
349
350 static void 
351 mipsfbsd_sigtramp_frame_this_id (struct frame_info *next_frame,
352                                  void **this_cache,
353                                  struct frame_id *this_id)
354 {
355   struct mips_frame_cache *cache =
356     mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
357
358     (*this_id) = frame_id_build (cache->base, 
359         cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
360 }
361
362 static void
363 mipsfbsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
364                                        void **this_cache,
365                                        int regnum, int *optimizedp,
366                                        enum lval_type *lvalp,
367                                        CORE_ADDR *addrp,
368                                        int *realnump, void *valuep)
369 {
370   struct mips_frame_cache *cache =
371     mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
372
373     trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
374                               optimizedp, lvalp, addrp, realnump, valuep);
375 }
376
377
378 static const struct frame_unwind mipsfbsd_sigtramp_frame_unwind = 
379 {
380   SIGTRAMP_FRAME,
381   mipsfbsd_sigtramp_frame_this_id,
382   mipsfbsd_sigtramp_frame_prev_register
383 };
384
385 static const struct frame_unwind *
386 mipsfbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
387 {
388   CORE_ADDR pc = frame_pc_unwind (next_frame);
389   char *name;
390
391   find_pc_partial_function (pc, &name, NULL, NULL);
392   if (mipsfbsd_pc_in_sigtramp (pc, name) )
393     return &mipsfbsd_sigtramp_frame_unwind;
394
395   return NULL;
396 }
397
398 /*
399  * Find out if PC has landed into dynamic library stub.
400  * We can find it by seeing if the name of the object
401  * file section where the PC lies is "MIPS.stubs"
402  */
403
404 int 
405 mipsfbsd_in_stub_section (CORE_ADDR pc, char *name)
406 {
407   struct obj_section *s;
408   int retval = 0;
409
410   s = find_pc_section (pc);
411
412   retval = (s != NULL
413             && s->the_bfd_section->name != NULL
414             && strcmp (s->the_bfd_section->name, ".MIPS.stubs") == 0);
415   return (retval);
416 }
417
418
419 /*
420  * Prologue cache for dynamic library stub frame.
421  * This stub does not modify the SP, so we set the
422  * cache base to calling frame's SP
423  */
424 static struct mips_frame_cache *
425 mipsfbsd_stub_frame_cache (struct frame_info *next_frame,
426                            void **this_cache)
427 {
428   struct mips_frame_cache *cache;
429
430   if (*this_cache)
431     return *this_cache;
432
433   cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
434   *this_cache = cache;
435
436   cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
437
438
439   cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].realreg =
440     NUM_REGS + RA_REGNUM;
441   cache->base = frame_unwind_register_unsigned (next_frame,
442    NUM_REGS + SP_REGNUM); 
443
444   return (*this_cache);
445 }
446
447  
448 static void
449 mipsfbsd_stub_frame_this_id (struct frame_info *next_frame,
450                              void **this_cache,
451                              struct frame_id *this_id)
452 {
453   struct mips_frame_cache *cache =
454     mipsfbsd_stub_frame_cache (next_frame, this_cache);
455
456     (*this_id) = frame_id_build (cache->base,
457         cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
458 }
459
460 static void
461 mipsfbsd_stub_frame_prev_register (struct frame_info *next_frame,
462                                    void **this_cache,
463                                    int regnum, int *optimizedp,
464                                    enum lval_type *lvalp, CORE_ADDR *addrp,
465                                    int *realnump, void *valuep)
466 {
467   struct mips_frame_cache *cache = 
468     mipsfbsd_stub_frame_cache (next_frame, this_cache);
469
470   trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
471                               optimizedp, lvalp, addrp, realnump, valuep);
472 }
473
474  
475  
476 static const struct frame_unwind mipsfbsd_stub_frame_unwind = {
477   NORMAL_FRAME,
478   mipsfbsd_stub_frame_this_id,
479   mipsfbsd_stub_frame_prev_register
480 };
481
482 static const struct frame_unwind *
483 mipsfbsd_stub_frame_sniffer (struct frame_info *next_frame)
484 {
485    CORE_ADDR pc = frame_pc_unwind (next_frame);
486    
487    if (mipsfbsd_in_stub_section(pc, NULL)) 
488      return &mipsfbsd_stub_frame_unwind;
489    
490    return NULL;
491 }
492      
493 /*
494  *  typedef struct link_map {
495  *          caddr_t         l_addr;                 /* Base Address of library
496  *  #ifdef __mips__
497  *          caddr_t         l_offs;                 /* Load Offset of library
498  *  #endif
499  *          const char      *l_name;                /* Absolute Path to Library
500  *          const void      *l_ld;                  /* Pointer to .dynamic in memory
501  *          struct link_map *l_next, *l_prev;       /* linked list of of mapped libs
502  *  } Link_map;
503  *
504  *  struct r_debug {
505  *          int             r_version;              /* not used
506  *          struct link_map *r_map;                 /* list of loaded images
507  *          void            (*r_brk)(struct r_debug *, struct link_map *);
508  *                                                  /* pointer to break point
509  *          enum {
510  *              RT_CONSISTENT,                      /* things are stable
511  *              RT_ADD,                             /* adding a shared library
512  *              RT_DELETE                           /* removing a shared library
513  *          }               r_state;
514  *  };
515  *
516  */
517
518 static struct link_map_offsets *
519 mipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
520 {
521   static struct link_map_offsets lmo;
522   static struct link_map_offsets *lmp = NULL;
523
524   if (lmp == NULL)
525     {
526       lmp = &lmo;
527
528       lmo.r_debug_size = 16;
529
530       lmo.r_map_offset = 4;
531       lmo.r_map_size   = 4;
532
533       lmo.link_map_size = 24;
534
535       lmo.l_addr_offset = 0;
536       lmo.l_addr_size   = 4;
537
538       lmo.l_name_offset = 8;
539       lmo.l_name_size   = 4;
540
541       lmo.l_next_offset = 16;
542       lmo.l_next_size   = 4;
543
544       lmo.l_prev_offset = 20;
545       lmo.l_prev_size   = 4;
546     }
547
548   return lmp;
549 }
550
551 static void
552 mipsfbsd_init_abi (struct gdbarch_info info,
553                    struct gdbarch *gdbarch)
554 {
555   set_gdbarch_pc_in_sigtramp (gdbarch, mipsfbsd_pc_in_sigtramp);
556
557   set_gdbarch_get_longjmp_target (gdbarch, mipsfbsd_get_longjmp_target);
558
559   set_gdbarch_cannot_fetch_register (gdbarch, mipsfbsd_cannot_fetch_register);
560   set_gdbarch_cannot_store_register (gdbarch, mipsfbsd_cannot_store_register);
561
562   set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
563   set_solib_svr4_fetch_link_map_offsets (gdbarch,
564                             mipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets);
565   set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
566   set_gdbarch_in_solib_call_trampoline (gdbarch, mipsfbsd_in_stub_section);
567
568   /* frame sniffers */
569   frame_unwind_append_sniffer (gdbarch, mipsfbsd_sigtramp_frame_sniffer);
570   frame_unwind_append_sniffer (gdbarch, mipsfbsd_stub_frame_sniffer);
571
572 }
573
574 void
575 _initialize_mipsfbsd_tdep (void)
576 {
577   gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD_ELF,
578                           mipsfbsd_init_abi);
579 }