示例#1
0
static void
mips_fbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
{
  enum mips_abi abi = mips_abi (gdbarch);

  /* Generic FreeBSD support.  */
  fbsd_init_abi (info, gdbarch);

  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);

  switch (abi)
    {
      case MIPS_ABI_O32:
	tramp_frame_prepend_unwinder (gdbarch, &mips_fbsd_sigframe);
	break;
      case MIPS_ABI_N32:
	tramp_frame_prepend_unwinder (gdbarch, &mipsn32_fbsd_sigframe);
	break;
      case MIPS_ABI_N64:
	tramp_frame_prepend_unwinder (gdbarch, &mips64_fbsd_sigframe);
	break;
    }

  set_gdbarch_iterate_over_regset_sections
    (gdbarch, mips_fbsd_iterate_over_regset_sections);

  /* FreeBSD/mips has SVR4-style shared libraries.  */
  set_solib_svr4_fetch_link_map_offsets
    (gdbarch, (gdbarch_ptr_bit (gdbarch) == 32 ?
	       mips_fbsd_ilp32_fetch_link_map_offsets :
	       mips_fbsd_lp64_fetch_link_map_offsets));
}
示例#2
0
static struct trad_frame_cache *
mips_sde_frame_cache (struct frame_info *this_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  const struct mips_regnum *regs = mips_regnum (gdbarch);
  const int sizeof_reg_t = mips_abi_regsize (gdbarch);
  enum mips_abi abi = mips_abi (gdbarch);
  struct trad_frame_cache *cache;
  CORE_ADDR xcpt_frame;
  CORE_ADDR start_addr;
  CORE_ADDR stack_addr;
  CORE_ADDR pc;
  int i;

  if (*this_cache != NULL)
    return (struct trad_frame_cache *) *this_cache;
  cache = trad_frame_cache_zalloc (this_frame);
  *this_cache = cache;

  /* The previous registers are held in struct xcptcontext
     which is at $sp+offs

     struct xcptcontext {
       reg_t	sr;		CP0 Status
       reg_t	cr;		CP0 Cause
       reg_t	epc;		CP0 EPC
       reg_t	vaddr;		CP0 BadVAddr
       reg_t	regs[32];	General registers
       reg_t	mdlo;		LO
       reg_t	mdhi;		HI
       reg_t	mdex;		ACX
       ...
     };
  */

  stack_addr = get_frame_register_signed (this_frame,
					  gdbarch_sp_regnum (gdbarch));
  switch (abi)
    {
    case MIPS_ABI_O32:
      /* 40: XCPTCONTEXT
	 24: xcpt_gen() argspace		(16 bytes)
	 16: _xcptcall() saved ra, rounded up	( 8 bytes)
	 00: _xcptcall() argspace 		(16 bytes)  */
      xcpt_frame = stack_addr + 40;
      break;
    case MIPS_ABI_N32:
    case MIPS_ABI_N64:
    default:			/* Wild guess.  */
      /* 16: XCPTCONTEXT
	 16: xcpt_gen() argspace 		( 0 bytes)
	 00: _xcptcall() saved ra, rounded up	(16 bytes)  */
      xcpt_frame = stack_addr + 16;
      break;
    }

  trad_frame_set_reg_addr (cache,
			   MIPS_PS_REGNUM + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 0 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->cause + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 1 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->pc + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 2 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->badvaddr + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 3 * sizeof_reg_t);
  for (i = 0; i < MIPS_NUMREGS; i++)
    trad_frame_set_reg_addr (cache,
			     i + MIPS_ZERO_REGNUM + gdbarch_num_regs (gdbarch),
			     xcpt_frame + (4 + i) * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->lo + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 36 * sizeof_reg_t);
  trad_frame_set_reg_addr (cache,
			   regs->hi + gdbarch_num_regs (gdbarch),
			   xcpt_frame + 37 * sizeof_reg_t);

  pc = get_frame_pc (this_frame);
  find_pc_partial_function (pc, NULL, &start_addr, NULL);
  trad_frame_set_id (cache, frame_id_build (start_addr, stack_addr));

  return cache;
}
static int
mips_linux_in_dynsym_stub (CORE_ADDR pc, char *name)
{
  unsigned char buf[28], *p;
  ULONGEST insn, insn1;
  int n64 = (mips_abi (target_gdbarch) == MIPS_ABI_N64);
  enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch);

  read_memory (pc - 12, buf, 28);

  if (n64)
    {
      /* ld t9,0x8010(gp) */
      insn1 = 0xdf998010;
    }
  else
    {
      /* lw t9,0x8010(gp) */
      insn1 = 0x8f998010;
    }

  p = buf + 12;
  while (p >= buf)
    {
      insn = extract_unsigned_integer (p, 4, byte_order);
      if (insn == insn1)
	break;
      p -= 4;
    }
  if (p < buf)
    return 0;

  insn = extract_unsigned_integer (p + 4, 4, byte_order);
  if (n64)
    {
      /* daddu t7,ra */
      if (insn != 0x03e0782d)
	return 0;
    }
  else
    {
      /* addu t7,ra */
      if (insn != 0x03e07821)
	return 0;
    }

  insn = extract_unsigned_integer (p + 8, 4, byte_order);
  /* jalr t9,ra */
  if (insn != 0x0320f809)
    return 0;

  insn = extract_unsigned_integer (p + 12, 4, byte_order);
  if (n64)
    {
      /* daddiu t8,zero,0 */
      if ((insn & 0xffff0000) != 0x64180000)
	return 0;
    }
  else
    {
      /* addiu t8,zero,0 */
      if ((insn & 0xffff0000) != 0x24180000)
	return 0;
    }

  return (insn & 0xffff);
}
static void
mips_linux_init_abi (struct gdbarch_info info,
		     struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum mips_abi abi = mips_abi (gdbarch);
  struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;

  linux_init_abi (info, gdbarch);

  switch (abi)
    {
      case MIPS_ABI_O32:
	set_gdbarch_get_longjmp_target (gdbarch,
	                                mips_linux_get_longjmp_target);
	set_solib_svr4_fetch_link_map_offsets
	  (gdbarch, svr4_ilp32_fetch_link_map_offsets);
	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_sigframe);
	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_o32_rt_sigframe);
	break;
      case MIPS_ABI_N32:
	set_gdbarch_get_longjmp_target (gdbarch,
	                                mips_linux_get_longjmp_target);
	set_solib_svr4_fetch_link_map_offsets
	  (gdbarch, svr4_ilp32_fetch_link_map_offsets);
	set_gdbarch_long_double_bit (gdbarch, 128);
	/* These floatformats should probably be renamed.  MIPS uses
	   the same 128-bit IEEE floating point format that IA-64 uses,
	   except that the quiet/signalling NaN bit is reversed (GDB
	   does not distinguish between quiet and signalling NaNs).  */
	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n32_rt_sigframe);
	break;
      case MIPS_ABI_N64:
	set_gdbarch_get_longjmp_target (gdbarch,
	                                mips64_linux_get_longjmp_target);
	set_solib_svr4_fetch_link_map_offsets
	  (gdbarch, svr4_lp64_fetch_link_map_offsets);
	set_gdbarch_long_double_bit (gdbarch, 128);
	/* These floatformats should probably be renamed.  MIPS uses
	   the same 128-bit IEEE floating point format that IA-64 uses,
	   except that the quiet/signalling NaN bit is reversed (GDB
	   does not distinguish between quiet and signalling NaNs).  */
	set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad);
	tramp_frame_prepend_unwinder (gdbarch, &mips_linux_n64_rt_sigframe);
	break;
      default:
	break;
    }

  set_gdbarch_skip_solib_resolver (gdbarch, mips_linux_skip_resolver);

  set_gdbarch_software_single_step (gdbarch, mips_software_single_step);

  /* Enable TLS support.  */
  set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                             svr4_fetch_objfile_link_map);

  /* Initialize this lazily, to avoid an initialization order
     dependency on solib-svr4.c's _initialize routine.  */
  if (mips_svr4_so_ops.in_dynsym_resolve_code == NULL)
    {
      mips_svr4_so_ops = svr4_so_ops;
      mips_svr4_so_ops.in_dynsym_resolve_code
	= mips_linux_in_dynsym_resolve_code;
    }
  set_solib_ops (gdbarch, &mips_svr4_so_ops);

  set_gdbarch_write_pc (gdbarch, mips_linux_write_pc);

  set_gdbarch_core_read_description (gdbarch,
				     mips_linux_core_read_description);

  set_gdbarch_regset_from_core_section (gdbarch,
					mips_linux_regset_from_core_section);

  tdep->syscall_next_pc = mips_linux_syscall_next_pc;

  if (tdesc_data)
    {
      const struct tdesc_feature *feature;

      /* If we have target-described registers, then we can safely
	 reserve a number for MIPS_RESTART_REGNUM (whether it is
	 described or not).  */
      gdb_assert (gdbarch_num_regs (gdbarch) <= MIPS_RESTART_REGNUM);
      set_gdbarch_num_regs (gdbarch, MIPS_RESTART_REGNUM + 1);
      set_gdbarch_num_pseudo_regs (gdbarch, MIPS_RESTART_REGNUM + 1);

      /* If it's present, then assign it to the reserved number.  */
      feature = tdesc_find_feature (info.target_desc,
				    "org.gnu.gdb.mips.linux");
      if (feature != NULL)
	tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
				 "restart");
    }
}