1/***********************************************************************
2Copyright 2003-2006 Raza Microelectronics, Inc.(RMI).
3This is a derived work from software originally provided by the external
4entity identified below. The licensing terms and warranties specified in
5the header of the original work apply to this derived work.
6Contribution 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
53void
54mipsfbsd_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}
69void
70supply_gregset (gdb_gregset_t *gregs)
71{
72  mipsfbsd_supply_reg((char *)gregs, -1);
73}
74
75void
76mipsfbsd_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
85void
86fill_gregset (gdb_gregset_t  *gregs, int regno)
87{
88  mipsfbsd_fill_reg ((char *)gregs, regno);
89}
90
91void
92mipsfbsd_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
111void
112supply_fpregset (gdb_fpregset_t *fpregs)
113{
114  mipsfbsd_supply_fpreg((char *)fpregs, -1);
115}
116
117void
118mipsfbsd_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
129void
130fill_fpregset (gdb_fpregset_t *fpregs, int regno)
131{
132  mipsfbsd_fill_fpreg ((char *)fpregs, regno);
133}
134
135static void
136fetch_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
155static void
156fetch_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
181static 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
190static 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
216static LONGEST
217mipsfbsd_sigtramp_offset (CORE_ADDR pc)
218{
219  return pc < MIPS_FBSD_SIGTRAMP_END &&
220         pc >= MIPS_FBSD_SIGTRAMP_START ? 1 : -1;
221}
222
223static int
224fbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
225{
226  return (name && strcmp (name, "__sigtramp") == 0);
227}
228
229static int
230mipsfbsd_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
236static int
237is_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
256static int
257mipsfbsd_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
275static int
276mipsfbsd_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
283static int
284mipsfbsd_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 */
294struct 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
310static struct mips_frame_cache *
311mipsfbsd_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
360static void
361mipsfbsd_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
372static void
373mipsfbsd_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
388static 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
395static const struct frame_unwind *
396mipsfbsd_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
414int
415mipsfbsd_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 */
434static struct mips_frame_cache *
435mipsfbsd_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
458static void
459mipsfbsd_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
470static void
471mipsfbsd_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
486static 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
492static const struct frame_unwind *
493mipsfbsd_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
528static struct link_map_offsets *
529mipsfbsd_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
561static void
562mipsfbsd_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
584void
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}
592