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