1204174Srrs/***********************************************************************
2204174SrrsCopyright 2003-2006 Raza Microelectronics, Inc.(RMI).
3204174SrrsThis is a derived work from software originally provided by the external
4204174Srrsentity identified below. The licensing terms and warranties specified in
5204174Srrsthe header of the original work apply to this derived work.
6204174SrrsContribution by RMI:
7204174Srrs*****************************#RMI_1#**********************************/
8204174Srrs/* Target-dependent code for MIPS systems running NetBSD.
9204174Srrs   Copyright 2002, 2003 Free Software Foundation, Inc.
10204174Srrs   Contributed by Wasabi Systems, Inc.
11204174Srrs
12204174Srrs   This file is part of GDB.
13204174Srrs
14204174Srrs   This program is free software; you can redistribute it and/or modify
15204174Srrs   it under the terms of the GNU General Public License as published by
16204174Srrs   the Free Software Foundation; either version 2 of the License, or
17204174Srrs   (at your option) any later version.
18204174Srrs
19204174Srrs   This program is distributed in the hope that it will be useful,
20204174Srrs   but WITHOUT ANY WARRANTY; without even the implied warranty of
21204174Srrs   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22204174Srrs   GNU General Public License for more details.
23204174Srrs
24204174Srrs   You should have received a copy of the GNU General Public License
25204174Srrs   along with this program; if not, write to the Free Software
26204174Srrs   Foundation, Inc., 59 Temple Place - Suite 330,
27204174Srrs   Boston, MA 02111-1307, USA.  */
28204174Srrs
29204174Srrs#include "defs.h"
30204174Srrs#include "gdbcore.h"
31204174Srrs#include "regcache.h"
32204174Srrs#include "target.h"
33204174Srrs#include "value.h"
34204174Srrs#include "osabi.h"
35204174Srrs
36204174Srrs#include "nbsd-tdep.h"
37204174Srrs#include "mipsfbsd-tdep.h"
38204174Srrs#include "mips-tdep.h"
39204174Srrs
40204174Srrs#include "solib-svr4.h"
41204174Srrs
42204174Srrs#include <sys/procfs.h>
43204174Srrs#include "gregset.h"
44204174Srrs#include "trad-frame.h"
45204174Srrs#include "frame.h"
46204174Srrs#include "frame-unwind.h"
47204174Srrs#include "bfd.h"
48204174Srrs#include "objfiles.h"
49204174Srrs
50204174Srrs/* Conveniently, GDB uses the same register numbering as the
51204174Srrs   ptrace register structure used by NetBSD/mips.  */
52204174Srrs
53204174Srrsvoid
54204174Srrsmipsfbsd_supply_reg (char *regs, int regno)
55204174Srrs{
56204174Srrs  int i;
57204174Srrs
58204174Srrs  for (i = 0; i <= PC_REGNUM; i++)
59204174Srrs    {
60204174Srrs      if (regno == i || regno == -1)
61204174Srrs	{
62204174Srrs	  if (CANNOT_FETCH_REGISTER (i))
63204174Srrs	    supply_register (i, NULL);
64204174Srrs	  else
65204174Srrs            supply_register (i, regs + (i * mips_regsize (current_gdbarch)));
66204174Srrs        }
67204174Srrs    }
68204174Srrs}
69204174Srrsvoid
70204174Srrssupply_gregset (gdb_gregset_t *gregs)
71204174Srrs{
72204174Srrs  mipsfbsd_supply_reg((char *)gregs, -1);
73204174Srrs}
74204174Srrs
75204174Srrsvoid
76204174Srrsmipsfbsd_fill_reg (char *regs, int regno)
77204174Srrs{
78204174Srrs  int i;
79204174Srrs
80204174Srrs  for (i = 0; i <= PC_REGNUM; i++)
81204174Srrs    if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
82204174Srrs      regcache_collect (i, regs + (i * mips_regsize (current_gdbarch)));
83204174Srrs}
84204174Srrs
85204174Srrsvoid
86204174Srrsfill_gregset (gdb_gregset_t  *gregs, int regno)
87204174Srrs{
88204174Srrs  mipsfbsd_fill_reg ((char *)gregs, regno);
89204174Srrs}
90204174Srrs
91204174Srrsvoid
92204174Srrsmipsfbsd_supply_fpreg (char *fpregs, int regno)
93204174Srrs{
94204174Srrs  int i;
95204174Srrs
96204174Srrs  for (i = FP0_REGNUM;
97204174Srrs       i <= mips_regnum (current_gdbarch)->fp_implementation_revision;
98204174Srrs       i++)
99204174Srrs    {
100204174Srrs      if (regno == i || regno == -1)
101204174Srrs	{
102204174Srrs	  if (CANNOT_FETCH_REGISTER (i))
103204174Srrs	    supply_register (i, NULL);
104204174Srrs	  else
105204174Srrs            supply_register (i,
106204174Srrs		fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
107204174Srrs	}
108204174Srrs    }
109204174Srrs}
110204174Srrs
111204174Srrsvoid
112204174Srrssupply_fpregset (gdb_fpregset_t *fpregs)
113204174Srrs{
114204174Srrs  mipsfbsd_supply_fpreg((char *)fpregs, -1);
115204174Srrs}
116204174Srrs
117204174Srrsvoid
118204174Srrsmipsfbsd_fill_fpreg (char *fpregs, int regno)
119204174Srrs{
120204174Srrs  int i;
121204174Srrs
122204174Srrs  for (i = FP0_REGNUM; i <= mips_regnum (current_gdbarch)->fp_control_status;
123204174Srrs       i++)
124204174Srrs    if ((regno == i || regno == -1) && ! CANNOT_STORE_REGISTER (i))
125204174Srrs      regcache_collect (i,
126204174Srrs	  fpregs + ((i - FP0_REGNUM) * mips_regsize (current_gdbarch)));
127204174Srrs}
128204174Srrs
129204174Srrsvoid
130204174Srrsfill_fpregset (gdb_fpregset_t *fpregs, int regno)
131204174Srrs{
132204174Srrs  mipsfbsd_fill_fpreg ((char *)fpregs, regno);
133204174Srrs}
134204174Srrs
135204174Srrsstatic void
136204174Srrsfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which,
137204174Srrs                      CORE_ADDR ignore)
138204174Srrs{
139204174Srrs  char *regs, *fpregs;
140204174Srrs
141204174Srrs  /* We get everything from one section.  */
142204174Srrs  if (which != 0)
143204174Srrs    return;
144204174Srrs
145204174Srrs  regs = core_reg_sect;
146204174Srrs  fpregs = core_reg_sect + SIZEOF_STRUCT_REG;
147204174Srrs
148204174Srrs  /* Integer registers.  */
149204174Srrs  mipsfbsd_supply_reg (regs, -1);
150204174Srrs
151204174Srrs  /* Floating point registers.  */
152204174Srrs  mipsfbsd_supply_fpreg (fpregs, -1);
153204174Srrs}
154204174Srrs
155204174Srrsstatic void
156204174Srrsfetch_elfcore_registers (char *core_reg_sect, unsigned core_reg_size, int which,
157204174Srrs                         CORE_ADDR ignore)
158204174Srrs{
159204174Srrs  switch (which)
160204174Srrs    {
161204174Srrs    case 0:  /* Integer registers.  */
162204174Srrs      if (core_reg_size != SIZEOF_STRUCT_REG)
163204174Srrs	warning ("Wrong size register set in core file.");
164204174Srrs      else
165204174Srrs	mipsfbsd_supply_reg (core_reg_sect, -1);
166204174Srrs      break;
167204174Srrs
168204174Srrs    case 2:  /* Floating point registers.  */
169204174Srrs      if (core_reg_size != SIZEOF_STRUCT_FPREG)
170204174Srrs	warning ("Wrong size register set in core file.");
171204174Srrs      else
172204174Srrs	mipsfbsd_supply_fpreg (core_reg_sect, -1);
173204174Srrs      break;
174204174Srrs
175204174Srrs    default:
176204174Srrs      /* Don't know what kind of register request this is; just ignore it.  */
177204174Srrs      break;
178204174Srrs    }
179204174Srrs}
180204174Srrs
181204174Srrsstatic struct core_fns mipsfbsd_core_fns =
182204174Srrs{
183204174Srrs  bfd_target_unknown_flavour,		/* core_flavour */
184204174Srrs  default_check_format,			/* check_format */
185204174Srrs  default_core_sniffer,			/* core_sniffer */
186204174Srrs  fetch_core_registers,			/* core_read_registers */
187204174Srrs  NULL					/* next */
188204174Srrs};
189204174Srrs
190214652Sgonzostatic struct core_fns mipsfbsd_elfcore_fns =
191214652Sgonzo{
192214652Sgonzo  bfd_target_elf_flavour,		/* core_flavour */
193214652Sgonzo  default_check_format,			/* check_format */
194214652Sgonzo  default_core_sniffer,			/* core_sniffer */
195214652Sgonzo  fetch_elfcore_registers,		/* core_read_registers */
196214652Sgonzo  NULL					/* next */
197214652Sgonzo};
198204174Srrs
199204174Srrs/*
200204174Srrs * MIPSFBSD Offsets
201204174Srrs * 0x7fff0000    User high mem -> USRSTACK [64K]
202204174Srrs *
203204174Srrs * 0x7ffefff0    ps_strings    -> 16 bytes
204204174Srrs *
205204174Srrs * 0x7ffeffec    sigcode       -> 44 bytes
206204174Srrs *
207204174Srrs * 0x7ffeffc4    sigcode end   env strings etc start
208232910Sjmallett *
209232910Sjmallett * XXX This is out-of-date and varies by ABI.
210204174Srrs */
211204174Srrs#define MIPS_FBSD_SIGTRAMP_START           (0x7ffeffc4)
212204174Srrs#define MIPS_FBSD_SIGTRAMP_END             (0x7ffeffec)
213204174Srrs#define MIPS_FBSD_SIGTRAMP_STACK_MOD_START (0x7ffeffc8)
214204174Srrs#define MIPS_FBSD_SIGTRAMP_STACK_MOD_END   (0x7ffeffd8)
215204174Srrs
216204174Srrsstatic LONGEST
217204174Srrsmipsfbsd_sigtramp_offset (CORE_ADDR pc)
218204174Srrs{
219204174Srrs  return pc < MIPS_FBSD_SIGTRAMP_END &&
220204174Srrs         pc >= MIPS_FBSD_SIGTRAMP_START ? 1 : -1;
221204174Srrs}
222204174Srrs
223204174Srrsstatic int
224204174Srrsfbsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
225204174Srrs{
226204174Srrs  return (name && strcmp (name, "__sigtramp") == 0);
227204174Srrs}
228204174Srrs
229204174Srrsstatic int
230204174Srrsmipsfbsd_pc_in_sigtramp (CORE_ADDR pc, char *func_name)
231204174Srrs{
232204174Srrs  return (fbsd_pc_in_sigtramp (pc, func_name)
233204174Srrs	  || mipsfbsd_sigtramp_offset (pc) >= 0);
234204174Srrs}
235204174Srrs
236204174Srrsstatic int
237204174Srrsis_sigtramp_sp_modified (CORE_ADDR pc)
238204174Srrs{
239204174Srrs  return (pc >= MIPS_FBSD_SIGTRAMP_STACK_MOD_START &&
240204174Srrs          pc <= MIPS_FBSD_SIGTRAMP_STACK_MOD_END);
241204174Srrs}
242204174Srrs
243204174Srrs
244204174Srrs/* Figure out where the longjmp will land.  We expect that we have
245204174Srrs   just entered longjmp and haven't yet setup the stack frame, so
246204174Srrs   the args are still in the argument regs.  A0_REGNUM points at the
247204174Srrs   jmp_buf structure from which we extract the PC that we will land
248204174Srrs   at.  The PC is copied into *pc.  This routine returns true on
249204174Srrs   success.  */
250204174Srrs
251204174Srrs#define FBSD_MIPS_JB_PC			(12)
252204174Srrs#define FBSD_MIPS_JB_ELEMENT_SIZE	mips_regsize (current_gdbarch)
253204174Srrs#define FBSD_MIPS_JB_OFFSET		(FBSD_MIPS_JB_PC * \
254204174Srrs					 FBSD_MIPS_JB_ELEMENT_SIZE)
255204174Srrs
256204174Srrsstatic int
257204174Srrsmipsfbsd_get_longjmp_target (CORE_ADDR *pc)
258204174Srrs{
259204174Srrs  CORE_ADDR jb_addr;
260204174Srrs  char *buf;
261204174Srrs
262204174Srrs  buf = alloca (FBSD_MIPS_JB_ELEMENT_SIZE);
263204174Srrs
264204174Srrs  jb_addr = read_register (A0_REGNUM);
265204174Srrs
266204174Srrs  if (target_read_memory (jb_addr + FBSD_MIPS_JB_OFFSET, buf,
267204174Srrs  			  FBSD_MIPS_JB_ELEMENT_SIZE))
268204174Srrs    return 0;
269204174Srrs
270204174Srrs  *pc = extract_unsigned_integer (buf, FBSD_MIPS_JB_ELEMENT_SIZE);
271204174Srrs
272204174Srrs  return 1;
273204174Srrs}
274204174Srrs
275204174Srrsstatic int
276204174Srrsmipsfbsd_cannot_fetch_register (int regno)
277204174Srrs{
278204174Srrs  return (regno == ZERO_REGNUM
279204174Srrs	  || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
280204174Srrs  /* XXX TODO: Are there other registers that we cannot fetch ? */
281204174Srrs}
282204174Srrs
283204174Srrsstatic int
284204174Srrsmipsfbsd_cannot_store_register (int regno)
285204174Srrs{
286204174Srrs  return (regno == ZERO_REGNUM
287204174Srrs	  || regno == mips_regnum (current_gdbarch)->fp_implementation_revision);
288204174Srrs  /* XXX TODO: Are there other registers that we cannot write ? */
289204174Srrs}
290204174Srrs
291204174Srrs/*
292204174Srrs * This structure is defined in mips-tdep.c.
293204174Srrs */
294204174Srrsstruct mips_frame_cache
295204174Srrs{
296204174Srrs  CORE_ADDR base;
297204174Srrs  struct trad_frame_saved_reg *saved_regs;
298204174Srrs};
299204174Srrs
300204174Srrs/*
301204174Srrs * Prologue cache for sigtramp frame
302204174Srrs * When we land in sigtramp, sigcontext is saved on the
303204174Srrs * stack just below the sigtramp's stack frame. We have
304204174Srrs * the Registers saved at fixed offsets on the stack.
305204174Srrs */
306204174Srrs
307204174Srrs#define MIPS_FBSD_SIGTRAMP_STACK_SIZE    (48)
308204174Srrs#define MIPS_FBSD_SIGCONTEXT_REG_OFFSET  (32)
309204174Srrs
310204174Srrsstatic struct mips_frame_cache *
311204174Srrsmipsfbsd_sigtramp_frame_cache (struct frame_info *next_frame,
312204174Srrs                               void **this_cache)
313204174Srrs{
314204174Srrs  struct mips_frame_cache *cache;
315204174Srrs  CORE_ADDR  gregs_addr, sp, pc;
316204174Srrs  int regnum;
317204174Srrs  int sigtramp_stack_size;
318204174Srrs
319204174Srrs  if (*this_cache)
320204174Srrs    return *this_cache;
321204174Srrs
322204174Srrs  cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
323204174Srrs  *this_cache = cache;
324204174Srrs
325204174Srrs  cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
326204174Srrs
327204174Srrs  /*
328204174Srrs   * Get sp of next frame which is the adjusted sp of
329204174Srrs   * tramp code.
330204174Srrs   */
331204174Srrs  sp = frame_unwind_register_unsigned(next_frame, NUM_REGS + SP_REGNUM);
332204174Srrs  pc = frame_unwind_register_unsigned(next_frame, NUM_REGS + PC_REGNUM);
333204174Srrs  sigtramp_stack_size = is_sigtramp_sp_modified(pc) ?
334204174Srrs	  MIPS_FBSD_SIGTRAMP_STACK_SIZE : 0;
335204174Srrs  gregs_addr = sp + sigtramp_stack_size + MIPS_FBSD_SIGCONTEXT_REG_OFFSET;
336204174Srrs
337204174Srrs  for (regnum = 0; regnum < PC_REGNUM; regnum++) {
338204174Srrs    cache->saved_regs[NUM_REGS + regnum].addr = gregs_addr +
339204174Srrs       regnum * mips_regsize (current_gdbarch);
340204174Srrs  }
341204174Srrs  /* Only retrieve PC and SP */
342204174Srrs  cache->saved_regs[NUM_REGS + SP_REGNUM].addr = gregs_addr +
343204174Srrs       SP_REGNUM * ( mips_regsize (current_gdbarch));
344204174Srrs
345204174Srrs  cache->saved_regs[NUM_REGS + RA_REGNUM].addr = gregs_addr +
346204174Srrs        RA_REGNUM * ( mips_regsize (current_gdbarch));
347204174Srrs
348204174Srrs  cache->base = get_frame_memory_unsigned (next_frame,
349204174Srrs    cache->saved_regs[NUM_REGS + SP_REGNUM].addr,
350204174Srrs    mips_regsize (current_gdbarch));
351204174Srrs
352204174Srrs  /* Todo: Floating point registers */
353204174Srrs
354204174Srrs  cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc]
355204174Srrs    =  cache->saved_regs[NUM_REGS + RA_REGNUM];
356204174Srrs
357204174Srrs  return *this_cache;
358204174Srrs}
359204174Srrs
360204174Srrsstatic void
361204174Srrsmipsfbsd_sigtramp_frame_this_id (struct frame_info *next_frame,
362204174Srrs                                 void **this_cache,
363204174Srrs				 struct frame_id *this_id)
364204174Srrs{
365204174Srrs  struct mips_frame_cache *cache =
366204174Srrs    mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
367204174Srrs
368204174Srrs    (*this_id) = frame_id_build (cache->base,
369204174Srrs	cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
370204174Srrs}
371204174Srrs
372204174Srrsstatic void
373204174Srrsmipsfbsd_sigtramp_frame_prev_register (struct frame_info *next_frame,
374204174Srrs                                       void **this_cache,
375204174Srrs				       int regnum, int *optimizedp,
376204174Srrs				       enum lval_type *lvalp,
377204174Srrs				       CORE_ADDR *addrp,
378204174Srrs				       int *realnump, void *valuep)
379204174Srrs{
380204174Srrs  struct mips_frame_cache *cache =
381204174Srrs    mipsfbsd_sigtramp_frame_cache (next_frame, this_cache);
382204174Srrs
383204174Srrs    trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
384204174Srrs			      optimizedp, lvalp, addrp, realnump, valuep);
385204174Srrs}
386204174Srrs
387204174Srrs
388204174Srrsstatic const struct frame_unwind mipsfbsd_sigtramp_frame_unwind =
389204174Srrs{
390204174Srrs  SIGTRAMP_FRAME,
391204174Srrs  mipsfbsd_sigtramp_frame_this_id,
392204174Srrs  mipsfbsd_sigtramp_frame_prev_register
393204174Srrs};
394204174Srrs
395204174Srrsstatic const struct frame_unwind *
396204174Srrsmipsfbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
397204174Srrs{
398204174Srrs  CORE_ADDR pc = frame_pc_unwind (next_frame);
399204174Srrs  char *name;
400204174Srrs
401204174Srrs  find_pc_partial_function (pc, &name, NULL, NULL);
402204174Srrs  if (mipsfbsd_pc_in_sigtramp (pc, name) )
403204174Srrs    return &mipsfbsd_sigtramp_frame_unwind;
404204174Srrs
405204174Srrs  return NULL;
406204174Srrs}
407204174Srrs
408204174Srrs/*
409204174Srrs * Find out if PC has landed into dynamic library stub.
410204174Srrs * We can find it by seeing if the name of the object
411204174Srrs * file section where the PC lies is "MIPS.stubs"
412204174Srrs */
413204174Srrs
414204174Srrsint
415204174Srrsmipsfbsd_in_stub_section (CORE_ADDR pc, char *name)
416204174Srrs{
417204174Srrs  struct obj_section *s;
418204174Srrs  int retval = 0;
419204174Srrs
420204174Srrs  s = find_pc_section (pc);
421204174Srrs
422204174Srrs  retval = (s != NULL
423204174Srrs            && s->the_bfd_section->name != NULL
424204174Srrs            && strcmp (s->the_bfd_section->name, ".MIPS.stubs") == 0);
425204174Srrs  return (retval);
426204174Srrs}
427204174Srrs
428204174Srrs
429204174Srrs/*
430204174Srrs * Prologue cache for dynamic library stub frame.
431204174Srrs * This stub does not modify the SP, so we set the
432204174Srrs * cache base to calling frame's SP
433204174Srrs */
434204174Srrsstatic struct mips_frame_cache *
435204174Srrsmipsfbsd_stub_frame_cache (struct frame_info *next_frame,
436204174Srrs                           void **this_cache)
437204174Srrs{
438204174Srrs  struct mips_frame_cache *cache;
439204174Srrs
440204174Srrs  if (*this_cache)
441204174Srrs    return *this_cache;
442204174Srrs
443204174Srrs  cache = FRAME_OBSTACK_ZALLOC (struct mips_frame_cache);
444204174Srrs  *this_cache = cache;
445204174Srrs
446204174Srrs  cache->saved_regs =  trad_frame_alloc_saved_regs (next_frame);
447204174Srrs
448204174Srrs
449204174Srrs  cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].realreg =
450204174Srrs    NUM_REGS + RA_REGNUM;
451204174Srrs  cache->base = frame_unwind_register_unsigned (next_frame,
452204174Srrs   NUM_REGS + SP_REGNUM);
453204174Srrs
454204174Srrs  return (*this_cache);
455204174Srrs}
456204174Srrs
457204174Srrs
458204174Srrsstatic void
459204174Srrsmipsfbsd_stub_frame_this_id (struct frame_info *next_frame,
460204174Srrs                             void **this_cache,
461204174Srrs                             struct frame_id *this_id)
462204174Srrs{
463204174Srrs  struct mips_frame_cache *cache =
464204174Srrs    mipsfbsd_stub_frame_cache (next_frame, this_cache);
465204174Srrs
466204174Srrs    (*this_id) = frame_id_build (cache->base,
467204174Srrs        cache->saved_regs[NUM_REGS + mips_regnum (current_gdbarch)->pc].addr);
468204174Srrs}
469204174Srrs
470204174Srrsstatic void
471204174Srrsmipsfbsd_stub_frame_prev_register (struct frame_info *next_frame,
472204174Srrs                                   void **this_cache,
473204174Srrs                                   int regnum, int *optimizedp,
474204174Srrs				   enum lval_type *lvalp, CORE_ADDR *addrp,
475204174Srrs				   int *realnump, void *valuep)
476204174Srrs{
477204174Srrs  struct mips_frame_cache *cache =
478204174Srrs    mipsfbsd_stub_frame_cache (next_frame, this_cache);
479204174Srrs
480204174Srrs  trad_frame_prev_register (next_frame, cache->saved_regs, regnum,
481204174Srrs                              optimizedp, lvalp, addrp, realnump, valuep);
482204174Srrs}
483204174Srrs
484204174Srrs
485204174Srrs
486204174Srrsstatic const struct frame_unwind mipsfbsd_stub_frame_unwind = {
487204174Srrs  NORMAL_FRAME,
488204174Srrs  mipsfbsd_stub_frame_this_id,
489204174Srrs  mipsfbsd_stub_frame_prev_register
490204174Srrs};
491204174Srrs
492204174Srrsstatic const struct frame_unwind *
493204174Srrsmipsfbsd_stub_frame_sniffer (struct frame_info *next_frame)
494204174Srrs{
495204174Srrs   CORE_ADDR pc = frame_pc_unwind (next_frame);
496204174Srrs
497204174Srrs   if (mipsfbsd_in_stub_section(pc, NULL))
498204174Srrs     return &mipsfbsd_stub_frame_unwind;
499204174Srrs
500204174Srrs   return NULL;
501204174Srrs}
502204174Srrs
503204174Srrs/*
504204174Srrs *  typedef struct link_map {
505204174Srrs *          caddr_t         l_addr;                 /* Base Address of library
506204174Srrs *  #ifdef __mips__
507204174Srrs *          caddr_t         l_offs;                 /* Load Offset of library
508204174Srrs *  #endif
509204174Srrs *          const char      *l_name;                /* Absolute Path to Library
510204174Srrs *          const void      *l_ld;                  /* Pointer to .dynamic in memory
511204174Srrs *          struct link_map *l_next, *l_prev;       /* linked list of of mapped libs
512204174Srrs *  } Link_map;
513204174Srrs *
514204174Srrs *  struct r_debug {
515204174Srrs *          int             r_version;              /* not used
516204174Srrs *          struct link_map *r_map;                 /* list of loaded images
517204174Srrs *          void            (*r_brk)(struct r_debug *, struct link_map *);
518204174Srrs *                                                  /* pointer to break point
519204174Srrs *          enum {
520204174Srrs *              RT_CONSISTENT,                      /* things are stable
521204174Srrs *              RT_ADD,                             /* adding a shared library
522204174Srrs *              RT_DELETE                           /* removing a shared library
523204174Srrs *          }               r_state;
524204174Srrs *  };
525204174Srrs *
526204174Srrs */
527204174Srrs
528204174Srrsstatic struct link_map_offsets *
529204174Srrsmipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets (void)
530204174Srrs{
531204174Srrs  static struct link_map_offsets lmo;
532204174Srrs  static struct link_map_offsets *lmp = NULL;
533204174Srrs
534204174Srrs  if (lmp == NULL)
535204174Srrs    {
536204174Srrs      lmp = &lmo;
537204174Srrs
538204174Srrs      lmo.r_debug_size = 16;
539204174Srrs
540204174Srrs      lmo.r_map_offset = 4;
541204174Srrs      lmo.r_map_size   = 4;
542204174Srrs
543204174Srrs      lmo.link_map_size = 24;
544204174Srrs
545204174Srrs      lmo.l_addr_offset = 0;
546204174Srrs      lmo.l_addr_size   = 4;
547204174Srrs
548204174Srrs      lmo.l_name_offset = 8;
549204174Srrs      lmo.l_name_size   = 4;
550204174Srrs
551204174Srrs      lmo.l_next_offset = 16;
552204174Srrs      lmo.l_next_size   = 4;
553204174Srrs
554204174Srrs      lmo.l_prev_offset = 20;
555204174Srrs      lmo.l_prev_size   = 4;
556204174Srrs    }
557204174Srrs
558204174Srrs  return lmp;
559204174Srrs}
560204174Srrs
561204174Srrsstatic void
562204174Srrsmipsfbsd_init_abi (struct gdbarch_info info,
563204174Srrs                   struct gdbarch *gdbarch)
564204174Srrs{
565204174Srrs  set_gdbarch_pc_in_sigtramp (gdbarch, mipsfbsd_pc_in_sigtramp);
566204174Srrs
567204174Srrs  set_gdbarch_get_longjmp_target (gdbarch, mipsfbsd_get_longjmp_target);
568204174Srrs
569204174Srrs  set_gdbarch_cannot_fetch_register (gdbarch, mipsfbsd_cannot_fetch_register);
570204174Srrs  set_gdbarch_cannot_store_register (gdbarch, mipsfbsd_cannot_store_register);
571204174Srrs
572204174Srrs  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);
573204174Srrs  set_solib_svr4_fetch_link_map_offsets (gdbarch,
574204174Srrs      			    mipsfbsd_ilp32_solib_svr4_fetch_link_map_offsets);
575204174Srrs  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
576204174Srrs  set_gdbarch_in_solib_call_trampoline (gdbarch, mipsfbsd_in_stub_section);
577204174Srrs
578204174Srrs  /* frame sniffers */
579204174Srrs  frame_unwind_append_sniffer (gdbarch, mipsfbsd_sigtramp_frame_sniffer);
580204174Srrs  frame_unwind_append_sniffer (gdbarch, mipsfbsd_stub_frame_sniffer);
581204174Srrs
582204174Srrs}
583204174Srrs
584204174Srrsvoid
585204174Srrs_initialize_mipsfbsd_tdep (void)
586204174Srrs{
587204174Srrs  gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD_ELF,
588204174Srrs			  mipsfbsd_init_abi);
589214652Sgonzo  add_core_fns (&mipsfbsd_core_fns);
590214652Sgonzo  add_core_fns (&mipsfbsd_elfcore_fns);
591204174Srrs}
592