static LONGEST
mipsnbsd_sigtramp_offset (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  const char *retcode = gdbarch_byte_order (get_frame_arch (next_frame))
			== BFD_ENDIAN_BIG ? sigtramp_retcode_mipseb :
			sigtramp_retcode_mipsel;
  unsigned char ret[RETCODE_SIZE], w[4];
  LONGEST off;
  int i;

  if (!safe_frame_unwind_memory (next_frame, pc, w, sizeof (w)))
    return -1;

  for (i = 0; i < RETCODE_NWORDS; i++)
    {
      if (memcmp (w, retcode + (i * 4), 4) == 0)
	break;
    }
  if (i == RETCODE_NWORDS)
    return -1;

  off = i * 4;
  pc -= off;

  if (!safe_frame_unwind_memory (next_frame, pc, ret, sizeof (ret)))
    return -1;

  if (memcmp (ret, retcode, RETCODE_SIZE) == 0)
    return off;

  return -1;
}
Ejemplo n.º 2
0
static CORE_ADDR
i386_linux_rt_sigtramp_start (struct frame_info *this_frame)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  gdb_byte buf[LINUX_RT_SIGTRAMP_LEN];

  /* We only recognize a signal trampoline if PC is at the start of
     one of the two instructions.  We optimize for finding the PC at
     the start, as will be the case when the trampoline is not the
     first frame on the stack.  We assume that in the case where the
     PC is not at the start of the instruction sequence, there will be
     a few trailing readable bytes on the stack.  */

  if (!safe_frame_unwind_memory (this_frame, pc, buf, LINUX_RT_SIGTRAMP_LEN))
    return 0;

  if (buf[0] != LINUX_RT_SIGTRAMP_INSN0)
    {
      if (buf[0] != LINUX_RT_SIGTRAMP_INSN1)
	return 0;

      pc -= LINUX_RT_SIGTRAMP_OFFSET1;

      if (!safe_frame_unwind_memory (this_frame, pc, buf,
				     LINUX_RT_SIGTRAMP_LEN))
	return 0;
    }

  if (memcmp (buf, linux_rt_sigtramp_code, LINUX_RT_SIGTRAMP_LEN) != 0)
    return 0;

  return pc;
}
Ejemplo n.º 3
0
static CORE_ADDR
m32r_linux_sigtramp_start (CORE_ADDR pc, struct frame_info *next_frame)
{
  gdb_byte buf[4];

  /* We only recognize a signal trampoline if PC is at the start of
     one of the instructions.  We optimize for finding the PC at the
     start of the instruction sequence, as will be the case when the
     trampoline is not the first frame on the stack.  We assume that
     in the case where the PC is not at the start of the instruction
     sequence, there will be a few trailing readable bytes on the
     stack.  */

  if (pc % 2 != 0)
    {
      if (!safe_frame_unwind_memory (next_frame, pc, buf, 2))
	return 0;

      if (memcmp (buf, linux_sigtramp_code, 2) == 0)
	pc -= 2;
      else
	return 0;
    }

  if (!safe_frame_unwind_memory (next_frame, pc, buf, 4))
    return 0;

  if (memcmp (buf, linux_sigtramp_code, 4) != 0)
    return 0;

  return pc;
}
Ejemplo n.º 4
0
static int
i386fbsd_sigtramp_p (struct frame_info *this_frame)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  gdb_byte buf[sizeof i386fbsd_sigtramp_middle];
  const gdb_byte *middle, *end;

  /* Look for a matching start.  */
  if (!safe_frame_unwind_memory (this_frame, pc, buf,
				 sizeof i386fbsd_sigtramp_start))
    return 0;
  if (memcmp (buf, i386fbsd_sigtramp_start, sizeof i386fbsd_sigtramp_start)
      == 0)
    {
      middle = i386fbsd_sigtramp_middle;
      end = i386fbsd_sigtramp_end;
    }
  else if (memcmp (buf, i386fbsd_freebsd4_sigtramp_start,
		   sizeof i386fbsd_freebsd4_sigtramp_start) == 0)
    {
      middle = i386fbsd_freebsd4_sigtramp_middle;
      end = i386fbsd_freebsd4_sigtramp_end;
    }
  else if (memcmp (buf, i386fbsd_osigtramp_start,
		   sizeof i386fbsd_osigtramp_start) == 0)
    {
      middle = i386fbsd_osigtramp_middle;
      end = i386fbsd_osigtramp_end;
    }
  else
    return 0;

  /* Since the end is shorter than the middle, check for a matching end
     next.  */
  pc += sizeof i386fbsd_sigtramp_start;
  if (!safe_frame_unwind_memory (this_frame, pc, buf,
				 sizeof i386fbsd_sigtramp_end))
    return 0;
  if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) == 0)
    return 1;

  /* If the end didn't match, check for a matching middle.  */
  if (!safe_frame_unwind_memory (this_frame, pc, buf,
				 sizeof i386fbsd_sigtramp_middle))
    return 0;
  if (memcmp (buf, middle, sizeof i386fbsd_sigtramp_middle) != 0)
    return 0;

  /* The middle matched, check for a matching end.  */
  pc += sizeof i386fbsd_sigtramp_middle;
  if (!safe_frame_unwind_memory (this_frame, pc, buf,
				 sizeof i386fbsd_sigtramp_end))
    return 0;
  if (memcmp (buf, end, sizeof i386fbsd_sigtramp_end) != 0)
    return 0;

  return 1;
}
Ejemplo n.º 5
0
static LONGEST
i386nbsd_sigtramp_offset (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  unsigned char ret[sizeof(sigtramp_retcode)], insn;
  LONGEST off;
  int i;

  if (!safe_frame_unwind_memory (next_frame, pc, &insn, 1))
    return -1;

  switch (insn)
    {
    case RETCODE_INSN1:
      off = 0;
      break;

    case RETCODE_INSN2:
      /* INSN2 and INSN3 are the same.  Read at the location of PC+1
	 to determine if we're actually looking at INSN2 or INSN3.  */
      if (!safe_frame_unwind_memory (next_frame, pc + 1, &insn, 1))
	return -1;

      if (insn == RETCODE_INSN3)
	off = RETCODE_INSN2_OFF;
      else
	off = RETCODE_INSN3_OFF;
      break;

    case RETCODE_INSN4:
      off = RETCODE_INSN4_OFF;
      break;

    case RETCODE_INSN5:
      off = RETCODE_INSN5_OFF;
      break;

    default:
      return -1;
    }

  pc -= off;

  if (!safe_frame_unwind_memory (next_frame, pc, ret, sizeof (ret)))
    return -1;

  if (memcmp (ret, sigtramp_retcode, sizeof (ret)) == 0)
    return off;

  return -1;
}
Ejemplo n.º 6
0
static CORE_ADDR
tramp_frame_start (const struct tramp_frame *tramp,
		   struct frame_info *this_frame, CORE_ADDR pc)
{
  int ti;
  /* Search through the trampoline for one that matches the
     instruction sequence around PC.  */
  for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
    {
      CORE_ADDR func = pc - tramp->insn_size * ti;
      int i;
      for (i = 0; 1; i++)
	{
	  gdb_byte buf[sizeof (tramp->insn[0])];
	  ULONGEST insn;
	  if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
	    return func;
	  if (!safe_frame_unwind_memory (this_frame,
					 func + i * tramp->insn_size,
					 buf, tramp->insn_size))
	    break;
	  insn = extract_unsigned_integer (buf, tramp->insn_size);
	  if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
	    break;
	}
    }
  /* Trampoline doesn't match.  */
  return 0;
}
Ejemplo n.º 7
0
static int
vaxobsd_sigtramp_sniffer (const struct frame_unwind *self,
			  struct frame_info *this_frame,
			  void **this_cache)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1));
  CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset;
  gdb_byte *buf;
  const char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name)
    return 0;

  buf = alloca(sizeof vaxobsd_sigreturn);
  if (!safe_frame_unwind_memory (this_frame, sigreturn_addr,
				 buf, sizeof vaxobsd_sigreturn))
    return 0;

  if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0)
    return 1;

  return 0;
}
Ejemplo n.º 8
0
static int
i386obsd_sigtramp_p (struct frame_info *next_frame)
{
    CORE_ADDR pc = frame_pc_unwind (next_frame);
    CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
    const char sigreturn[] =
    {
        0xb8,
        0x67, 0x00, 0x00, 0x00,	/* movl $SYS_sigreturn, %eax */
        0xcd, 0x80			/* int $0x80 */
    };
    size_t buflen = sizeof sigreturn;
    char *name, *buf;

    /* If the function has a valid symbol name, it isn't a
       trampoline.  */
    find_pc_partial_function (pc, &name, NULL, NULL);
    if (name != NULL)
        return 0;

    /* If the function lives in a valid section (even without a starting
       point) it isn't a trampoline.  */
    if (find_pc_section (pc) != NULL)
        return 0;

    /* Allocate buffer.  */
    buf = alloca (buflen);

    /* If we can't read the instructions at START_PC, return zero.  */
    if (!safe_frame_unwind_memory (next_frame, start_pc + 0x0a, buf, buflen))
        return 0;

    /* Check for sigreturn(2).  */
    if (memcmp (buf, sigreturn, buflen) == 0)
        return 1;

    /* If we can't read the instructions at START_PC, return zero.  */
    if (!safe_frame_unwind_memory (next_frame, start_pc + 0x14, buf, buflen))
        return 0;

    /* Check for sigreturn(2) (again).  */
    if (memcmp (buf, sigreturn, buflen) == 0)
        return 1;

    return 0;
}
Ejemplo n.º 9
0
static CORE_ADDR
i386syl_sigtramp_start (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  unsigned char buf[SYL_SIGTRAMP_LEN];

  /* We only recognize a signal trampoline if PC is at the start of
     one of the three instructions.  We optimize for finding the PC at
     the start, as will be the case when the trampoline is not the
     first frame on the stack.  We assume that in the case where the
     PC is not at the start of the instruction sequence, there will be
     a few trailing readable bytes on the stack.  */

  if (!safe_frame_unwind_memory (next_frame, pc, buf, SYL_SIGTRAMP_LEN))
    return 0;

  if (buf[0] != SYL_SIGTRAMP_INSN0)
  {
    int adjust;

    switch (buf[0])
    {
      case SYL_SIGTRAMP_INSN1:
        adjust = SYL_SIGTRAMP_OFFSET1;
        break;
      case SYL_SIGTRAMP_INSN2:
        adjust = SYL_SIGTRAMP_OFFSET2;
        break;
      default:
        return 0;
    }

    pc -= adjust;

    if (!safe_frame_unwind_memory (next_frame, pc, buf, SYL_SIGTRAMP_LEN))
      return 0;
  }

  if (memcmp (buf, syllable_sigtramp_code, SYL_SIGTRAMP_LEN) != 0)
    return 0;

  return pc;
}
Ejemplo n.º 10
0
static struct trad_frame_cache *
ppcobsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  struct trad_frame_cache *cache;
  CORE_ADDR addr, base, func;
  gdb_byte buf[PPC_INSN_SIZE];
  unsigned long insn, sigcontext_offset;
  int i;

  if (*this_cache)
    return (struct trad_frame_cache *) *this_cache;

  cache = trad_frame_cache_zalloc (this_frame);
  *this_cache = cache;

  func = get_frame_pc (this_frame);
  func &= ~(ppcobsd_page_size - 1);
  if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
    return cache;

  /* Calculate the offset where we can find `struct sigcontext'.  We
     base our calculation on the amount of stack space reserved by the
     first instruction of the signal trampoline.  */
  insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
  sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;

  base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
  addr = base + sigcontext_offset + 2 * tdep->wordsize;
  for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
    {
      int regnum = i + tdep->ppc_gp0_regnum;
      trad_frame_set_reg_addr (cache, regnum, addr);
    }
  trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
  /* SRR0?  */
  addr += tdep->wordsize;

  /* Construct the frame ID using the function start.  */
  trad_frame_set_id (cache, frame_id_build (base, func));

  return cache;
}
Ejemplo n.º 11
0
static int
ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
				struct frame_info *this_frame,
				void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch(this_frame);
  enum bfd_endian byte_order = (enum bfd_endian)gdbarch_byte_order(gdbarch);
  CORE_ADDR pc = get_frame_pc(this_frame);
  CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1));
  const int *offset;
  const char *name;

  /* A stack trampoline is detected if no name is associated
   to the current pc and if it points inside a trampoline
   sequence.  */

  find_pc_partial_function (pc, &name, NULL, NULL);

  /* If we have a name, we have no trampoline, return.  */
  if (name)
    return 0;

  for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++)
    {
#ifdef PPC_INSN_SIZE
      gdb_byte buf[2 * PPC_INSN_SIZE];
#else
      gdb_byte buf[2 * sizeof(unsigned long)];
#endif /* PPC_INSN_SIZE */
      unsigned long insn;

      if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
				     buf, sizeof buf))
	continue;

      /* Check for "li r0,SYS_sigreturn".  */
      insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
      if (insn != 0x380001a1)
	continue;

      /* Check for "sc".  */
      insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
				       PPC_INSN_SIZE, byte_order);
      if (insn != 0x44000002)
	continue;

      return 1;
    }

  return 0;
}
Ejemplo n.º 12
0
static int
amd64obsd_sigtramp_p (struct frame_info *this_frame)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  CORE_ADDR start_pc = (pc & ~(amd64obsd_page_size - 1));
  const gdb_byte osigreturn[] =
  {
    0x48, 0xc7, 0xc0,
    0x67, 0x00, 0x00, 0x00,	/* movq $SYS_sigreturn, %rax */
    0xcd, 0x80			/* int $0x80 */
  };
  const gdb_byte sigreturn[] =
  {
    0x48, 0xc7, 0xc0,
    0x67, 0x00, 0x00, 0x00,	/* movq $SYS_sigreturn, %rax */
    0x0f, 0x05			/* syscall */
  };
  size_t buflen = (sizeof sigreturn) + 1;
  gdb_byte *buf;
  const char *name;

  /* If the function has a valid symbol name, it isn't a
     trampoline.  */
  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name != NULL)
    return 0;

  /* If the function lives in a valid section (even without a starting
     point) it isn't a trampoline.  */
  if (find_pc_section (pc) != NULL)
    return 0;

  /* If we can't read the instructions at START_PC, return zero.  */
  buf = (gdb_byte *) alloca ((sizeof sigreturn) + 1);
  if (!safe_frame_unwind_memory (this_frame, start_pc + 6, buf, buflen))
    return 0;

  /* Check for sigreturn(2).  Depending on how the assembler encoded
     the `movq %rsp, %rdi' instruction, the code starts at offset 6 or
     7.  OpenBSD 5.0 and later use the `syscall' instruction.  Older
     versions use `int $0x80'.  Check for both.  */
  if (memcmp (buf, sigreturn, sizeof sigreturn)
      && memcmp (buf + 1, sigreturn, sizeof sigreturn)
      && memcmp (buf, osigreturn, sizeof osigreturn)
      && memcmp (buf + 1, osigreturn, sizeof osigreturn))
    return 0;

  return 1;
}
Ejemplo n.º 13
0
static int
i386obsd_sigtramp_p (struct frame_info *this_frame)
{
  CORE_ADDR pc = get_frame_pc (this_frame);
  CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
  /* The call sequence invoking sigreturn(2).  */
  const gdb_byte sigreturn[] =
  {
    0xb8,
    0x67, 0x00, 0x00, 0x00,	/* movl $SYS_sigreturn, %eax */
    0xcd, 0x80			/* int $0x80 */
  };
  size_t buflen = sizeof sigreturn;
  const int *offset;
  gdb_byte *buf;
  const char *name;

  /* If the function has a valid symbol name, it isn't a
     trampoline.  */
  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name != NULL)
    return 0;

  /* If the function lives in a valid section (even without a starting
     point) it isn't a trampoline.  */
  if (find_pc_section (pc) != NULL)
    return 0;

  /* Allocate buffer.  */
  buf = alloca (buflen);

  /* Loop over all offsets.  */
  for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++)
    {
      /* If we can't read the instructions, return zero.  */
      if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
				     buf, buflen))
	return 0;

      /* Check for sigreturn(2).  */
      if (memcmp (buf, sigreturn, buflen) == 0)
	return 1;
    }

  return 0;
}
Ejemplo n.º 14
0
static struct trad_frame_cache *
ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  struct trad_frame_cache *cache;
  CORE_ADDR addr, base, func;
  gdb_byte buf[PPC_INSN_SIZE];
  int i;

  if (*this_cache)
    return *this_cache;

  cache = trad_frame_cache_zalloc (this_frame);
  *this_cache = cache;

  func = get_frame_pc (this_frame);
  func &= ~(ppcfbsd_page_size - 1);
  if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf))
    return cache;

  base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch));
  addr = base + 0x10 + 2 * tdep->wordsize;
  for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize)
    {
      int regnum = i + tdep->ppc_gp0_regnum;
      trad_frame_set_reg_addr (cache, regnum, addr);
    }
  trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr);
  addr += tdep->wordsize;
  trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr);
  /* SRR0?  */
  addr += tdep->wordsize;

  /* Construct the frame ID using the function start.  */
  trad_frame_set_id (cache, frame_id_build (base, func));

  return cache;
}
Ejemplo n.º 15
0
static int
ppcobsd_sigtramp_frame_sniffer (const struct frame_unwind *self,
				struct frame_info *this_frame,
				void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR pc = get_frame_pc (this_frame);
  CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1));
  const int *offset;
  const char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name)
    return 0;

  for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++)
    {
      gdb_byte buf[2 * PPC_INSN_SIZE];
      unsigned long insn;

      if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
				     buf, sizeof buf))
	continue;

      /* Check for "li r0,SYS_sigreturn".  */
      insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order);
      if (insn != 0x38000067)
	continue;

      /* Check for "sc".  */
      insn = extract_unsigned_integer (buf + PPC_INSN_SIZE,
				       PPC_INSN_SIZE, byte_order);
      if (insn != 0x44000002)
	continue;

      return 1;
    }

  return 0;
}
Ejemplo n.º 16
0
static CORE_ADDR
tramp_frame_start (const struct tramp_frame *tramp,
		   struct frame_info *this_frame, CORE_ADDR pc)
{
  struct gdbarch *gdbarch = get_frame_arch (this_frame);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  int ti;

  /* Check if we can use this trampoline.  */
  if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
    return 0;

  /* Search through the trampoline for one that matches the
     instruction sequence around PC.  */
  for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
    {
      CORE_ADDR func = pc - tramp->insn_size * ti;
      int i;

      for (i = 0; 1; i++)
	{
	  gdb_byte buf[sizeof (tramp->insn[0])];
	  ULONGEST insn;

	  if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
	    return func;
	  if (!safe_frame_unwind_memory (this_frame,
					 func + i * tramp->insn_size,
					 buf, tramp->insn_size))
	    break;
	  insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
	  if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
	    break;
	}
    }
  /* Trampoline doesn't match.  */
  return 0;
}
Ejemplo n.º 17
0
static int
vaxobsd_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  CORE_ADDR start_pc = (pc & ~(vaxobsd_page_size - 1));
  CORE_ADDR sigreturn_addr = start_pc + vaxobsd_sigreturn_offset;
  gdb_byte *buf;
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name)
    return 0;

  buf = alloca(sizeof vaxobsd_sigreturn);
  if (!safe_frame_unwind_memory (next_frame, sigreturn_addr,
				 buf, sizeof vaxobsd_sigreturn))
    return 0;

  if (memcmp(buf, vaxobsd_sigreturn, sizeof vaxobsd_sigreturn) == 0)
    return 1;

  return 0;
}
static int
ppcobsd_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  CORE_ADDR start_pc = (pc & ~(ppcobsd_page_size - 1));
  const int *offset;
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (name)
    return 0;

  for (offset = ppcobsd_sigreturn_offset; *offset != -1; offset++)
    {
      gdb_byte buf[2 * PPC_INSN_SIZE];
      unsigned long insn;

      if (!safe_frame_unwind_memory (next_frame, start_pc + *offset,
				     buf, sizeof buf))
	continue;

      /* Check for "li r0,SYS_sigreturn".  */
      insn = extract_unsigned_integer (buf, PPC_INSN_SIZE);
      if (insn != 0x38000067)
	continue;

      /* Check for "sc".  */
      insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, PPC_INSN_SIZE);
      if (insn != 0x44000002)
	continue;

      return 1;
    }

  return 0;
}
Ejemplo n.º 19
0
static CORE_ADDR
mn10300_analyze_prologue (struct frame_info *fi, 
			  void **this_cache, 
			  CORE_ADDR pc)
{
  CORE_ADDR func_addr, func_end, addr, stop;
  long stack_extra_size = 0;
  int imm_size;
  unsigned char buf[4];
  int status;
  int movm_args = 0;
  int fpregmask = 0;
  char *name;
  int frame_in_fp = 0;

  /* Use the PC in the frame if it's provided to look up the
     start of this function.

     Note: kevinb/2003-07-16: We used to do the following here:
	pc = (fi ? get_frame_pc (fi) : pc);
     But this is (now) badly broken when called from analyze_dummy_frame().
  */
  if (fi)
    {
      pc = (pc ? pc : get_frame_pc (fi));
    }

  /* Find the start of this function.  */
  status = find_pc_partial_function (pc, &name, &func_addr, &func_end);

  /* Do nothing if we couldn't find the start of this function 

     MVS: comment went on to say "or if we're stopped at the first
     instruction in the prologue" -- but code doesn't reflect that, 
     and I don't want to do that anyway.  */
  if (status == 0)
    {
      addr = pc;
      goto finish_prologue;
    }

  /* If we're in start, then give up.  */
  if (strcmp (name, "start") == 0)
    {
      addr = pc;
      goto finish_prologue;
    }

  /* Figure out where to stop scanning.  */
  stop = fi ? pc : func_end;

  /* Don't walk off the end of the function.  */
  stop = stop > func_end ? func_end : stop;

  /* Start scanning on the first instruction of this function.  */
  addr = func_addr;

  /* Suck in two bytes.  */
  if (addr + 2 > stop || !safe_frame_unwind_memory (fi, addr, buf, 2))
    goto finish_prologue;

  /* First see if this insn sets the stack pointer from a register; if
     so, it's probably the initialization of the stack pointer in _start,
     so mark this as the bottom-most frame.  */
  if (buf[0] == 0xf2 && (buf[1] & 0xf3) == 0xf0)
    {
      goto finish_prologue;
    }

  /* Now look for movm [regs],sp, which saves the callee saved registers.

     At this time we don't know if fi->frame is valid, so we only note
     that we encountered a movm instruction.  Later, we'll set the entries
     in fsr.regs as needed.  */
  if (buf[0] == 0xcf)
    {
      /* Extract the register list for the movm instruction.  */
      movm_args = buf[1];

      addr += 2;

      /* Quit now if we're beyond the stop point.  */
      if (addr >= stop)
	goto finish_prologue;

      /* Get the next two bytes so the prologue scan can continue.  */
      if (!safe_frame_unwind_memory (fi, addr, buf, 2))
	goto finish_prologue;
    }

  if (AM33_MODE == 2)
    {
      /* Determine if any floating point registers are to be saved.
	 Look for one of the following three prologue formats:

	[movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)]

	 add -SIZE,sp       add -SIZE,sp       add -SIZE,sp
	 fmov fs#,(sp)      mov sp,a0/a1       mov sp,a0/a1
	 fmov fs#,(#,sp)    fmov fs#,(a0/a1+)  add SIZE2,a0/a1
	 ...                ...                fmov fs#,(a0/a1+)
	 ...                ...                ...
	 fmov fs#,(#,sp)    fmov fs#,(a0/a1+)  fmov fs#,(a0/a1+)

	[mov sp,a3]        [mov sp,a3]
	[add -SIZE2,sp]    [add -SIZE2,sp]                                 */

      /* First, look for add -SIZE,sp (i.e. add imm8,sp  (0xf8feXX)
                                         or add imm16,sp (0xfafeXXXX)
                                         or add imm32,sp (0xfcfeXXXXXXXX)) */
      imm_size = 0;
      if (buf[0] == 0xf8 && buf[1] == 0xfe)
	imm_size = 1;
      else if (buf[0] == 0xfa && buf[1] == 0xfe)
	imm_size = 2;
      else if (buf[0] == 0xfc && buf[1] == 0xfe)
	imm_size = 4;
      if (imm_size != 0)
	{
	  /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size"
	     is the address of the next instruction. Don't modify "addr" until
	     the next "floating point prologue" instruction is found. If this
	     is not a prologue that saves floating point registers we need to
	     be able to back out of this bit of code and continue with the
	     prologue analysis. */
	  if (addr + 2 + imm_size < stop)
	    {
	      if (!safe_frame_unwind_memory (fi, addr + 2 + imm_size, buf, 3))
		goto finish_prologue;
	      if ((buf[0] & 0xfc) == 0x3c)
		{
		  /* Occasionally, especially with C++ code, the "fmov"
		     instructions will be preceded by "mov sp,aN"
		     (aN => a0, a1, a2, or a3).

		     This is a one byte instruction:  mov sp,aN = 0011 11XX
		     where XX is the register number.

		     Skip this instruction by incrementing addr. (We're
		     committed now.) The "fmov" instructions will have the
		     form "fmov fs#,(aN+)" in this case, but that will not
		     necessitate a change in the "fmov" parsing logic below. */

		  addr++;

		  if ((buf[1] & 0xfc) == 0x20)
		    {
		      /* Occasionally, especially with C++ code compiled with
			 the -fomit-frame-pointer or -O3 options, the
			 "mov sp,aN" instruction will be followed by an
			 "add #,aN" instruction. This indicates the
			 "stack_size", the size of the portion of the stack
			 containing the arguments. This instruction format is:
			 add #,aN = 0010 00XX YYYY YYYY
			 where XX        is the register number
			       YYYY YYYY is the constant.
			 Note the size of the stack (as a negative number) in
			 the frame info structure. */
		      if (fi)
			stack_extra_size += -buf[2];

		      addr += 2;
		    }
		}

	      if ((buf[0] & 0xfc) == 0x3c ||
		  buf[0] == 0xf9 || buf[0] == 0xfb)
		{
		  /* An "fmov" instruction has been found indicating that this
		     prologue saves floating point registers (or, as described
		     above, a "mov sp,aN" and possible "add #,aN" have been
		     found and we will assume an "fmov" follows). Process the
		     consecutive "fmov" instructions. */
		  for (addr += 2 + imm_size;;addr += imm_size)
		    {
		      int regnum;

		      /* Read the "fmov" instruction. */
		      if (addr >= stop ||
			  !safe_frame_unwind_memory (fi, addr, buf, 4))
			goto finish_prologue;

		      if (buf[0] != 0xf9 && buf[0] != 0xfb)
			break;

		      /* Get the floating point register number from the 
			 2nd and 3rd bytes of the "fmov" instruction:
			 Machine Code: 0000 00X0 YYYY 0000 =>
			 Regnum: 000X YYYY */
		      regnum = (buf[1] & 0x02) << 3;
		      regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f;

		      /* Add this register number to the bit mask of floating
			 point registers that have been saved. */
		      fpregmask |= 1 << regnum;
		  
		      /* Determine the length of this "fmov" instruction.
			 fmov fs#,(sp)   => 3 byte instruction
			 fmov fs#,(#,sp) => 4 byte instruction */
		      imm_size = (buf[0] == 0xf9) ? 3 : 4;
		    }
		}
	      else
		{
		  /* No "fmov" was found. Reread the two bytes at the original
		     "addr" to reset the state. */
		  if (!safe_frame_unwind_memory (fi, addr, buf, 2))
		    goto finish_prologue;
		}
	    }
	  /* else the prologue consists entirely of an "add -SIZE,sp"
	     instruction. Handle this below. */
	}
Ejemplo n.º 20
0
static CORE_ADDR
tilegx_analyze_prologue (struct gdbarch* gdbarch,
			 CORE_ADDR start_addr, CORE_ADDR end_addr,
			 struct tilegx_frame_cache *cache,
			 struct frame_info *next_frame)
{
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  CORE_ADDR next_addr;
  CORE_ADDR prolog_end = end_addr;
  gdb_byte instbuf[32 * TILEGX_BUNDLE_SIZE_IN_BYTES];
  CORE_ADDR instbuf_start;
  unsigned int instbuf_size;
  int status;
  bfd_uint64_t bundle;
  struct tilegx_decoded_instruction
    decoded[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
  int num_insns;
  struct tilegx_reverse_regs reverse_frame[TILEGX_NUM_PHYS_REGS];
  struct tilegx_reverse_regs
    new_reverse_frame[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
  int dest_regs[TILEGX_MAX_INSTRUCTIONS_PER_BUNDLE];
  int reverse_frame_valid, prolog_done, branch_seen, lr_saved_on_stack_p;
  LONGEST prev_sp_value;
  int i, j;

  if (start_addr >= end_addr
      || (start_addr % TILEGX_BUNDLE_ALIGNMENT_IN_BYTES) != 0)
    return end_addr;

  /* Initialize the reverse frame.  This maps the CURRENT frame's
     registers to the outer frame's registers (the frame on the
     stack goes the other way).  */
  memcpy (&reverse_frame, &template_reverse_regs, sizeof (reverse_frame));

  prolog_done = 0;
  branch_seen = 0;
  prev_sp_value = 0;
  lr_saved_on_stack_p = 0;

  /* To cut down on round-trip overhead, we fetch multiple bundles
     at once.  These variables describe the range of memory we have
     prefetched.  */
  instbuf_start = 0;
  instbuf_size = 0;

  for (next_addr = start_addr;
       next_addr < end_addr;
       next_addr += TILEGX_BUNDLE_SIZE_IN_BYTES)
    {
      /* Retrieve the next instruction.  */
      if (next_addr - instbuf_start >= instbuf_size)
	{
	  /* Figure out how many bytes to fetch.  Don't span a page
	     boundary since that might cause an unnecessary memory
	     error.  */
	  unsigned int size_on_same_page = 4096 - (next_addr & 4095);

	  instbuf_size = sizeof instbuf;

	  if (instbuf_size > size_on_same_page)
	    instbuf_size = size_on_same_page;

	  instbuf_size = min (instbuf_size, (end_addr - next_addr));
	  instbuf_start = next_addr;

	  status = safe_frame_unwind_memory (next_frame, instbuf_start,
					     instbuf, instbuf_size);
	  if (status == 0)
	    memory_error (TARGET_XFER_E_IO, next_addr);
	}

      reverse_frame_valid = 0;

      bundle = extract_unsigned_integer (&instbuf[next_addr - instbuf_start],
					 8, byte_order);

      num_insns = parse_insn_tilegx (bundle, next_addr, decoded);

      for (i = 0; i < num_insns; i++)
	{
	  struct tilegx_decoded_instruction *this_insn = &decoded[i];
	  int64_t *operands = (int64_t *) this_insn->operand_values;
	  const struct tilegx_opcode *opcode = this_insn->opcode;

	  switch (opcode->mnemonic)
	    {
	    case TILEGX_OPC_ST:
	      if (cache
		  && reverse_frame[operands[0]].state == REVERSE_STATE_VALUE
		  && reverse_frame[operands[1]].state
		  == REVERSE_STATE_REGISTER)
		{
		  LONGEST saved_address = reverse_frame[operands[0]].value;
		  unsigned saved_register
		    = (unsigned) reverse_frame[operands[1]].value;

		  /* realreg >= 0 and addr != -1 indicates that the
		     value of saved_register is in memory location
		     saved_address.  The value of realreg is not
		     meaningful in this case but it must be >= 0.
		     See trad-frame.h.  */
		  cache->saved_regs[saved_register].realreg = saved_register;
		  cache->saved_regs[saved_register].addr = saved_address;
		} 
	      else if (cache
		       && (operands[0] == TILEGX_SP_REGNUM) 
		       && (operands[1] == TILEGX_LR_REGNUM))
		lr_saved_on_stack_p = 1;
	      break;
	    case TILEGX_OPC_ADDI:
	    case TILEGX_OPC_ADDLI:
	      if (cache
		  && operands[0] == TILEGX_SP_REGNUM
		  && operands[1] == TILEGX_SP_REGNUM
		  && reverse_frame[operands[1]].state == REVERSE_STATE_REGISTER)
		{
		  /* Special case.  We're fixing up the stack frame.  */
		  uint64_t hopefully_sp
		    = (unsigned) reverse_frame[operands[1]].value;
		  short op2_as_short = (short) operands[2];
		  signed char op2_as_char = (signed char) operands[2];

		  /* Fix up the sign-extension.  */
		  if (opcode->mnemonic == TILEGX_OPC_ADDI)
		    op2_as_short = op2_as_char;
		  prev_sp_value = (cache->saved_regs[hopefully_sp].addr
				   - op2_as_short);

		  new_reverse_frame[i].state = REVERSE_STATE_VALUE;
		  new_reverse_frame[i].value
		    = cache->saved_regs[hopefully_sp].addr;
		  trad_frame_set_value (cache->saved_regs,
					hopefully_sp, prev_sp_value);
		}
	      else
		{
		  short op2_as_short = (short) operands[2];
		  signed char op2_as_char = (signed char) operands[2];

		  /* Fix up the sign-extension.  */
		  if (opcode->mnemonic == TILEGX_OPC_ADDI)
		    op2_as_short = op2_as_char;

		  new_reverse_frame[i] = reverse_frame[operands[1]];
		  if (new_reverse_frame[i].state == REVERSE_STATE_VALUE)
		    new_reverse_frame[i].value += op2_as_short;
		  else
		    new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		}
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_ADD:
	      if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
		  && reverse_frame[operands[2]].state == REVERSE_STATE_VALUE)
		{
		  /* We have values -- we can do this.  */
		  new_reverse_frame[i] = reverse_frame[operands[2]];
		  new_reverse_frame[i].value
		    += reverse_frame[operands[i]].value;
		}
	      else
		{
		  /* We don't know anything about the values.  Punt.  */
		  new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		}
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_MOVE:
	      new_reverse_frame[i] = reverse_frame[operands[1]];
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_MOVEI:
	    case TILEGX_OPC_MOVELI:
	      new_reverse_frame[i].state = REVERSE_STATE_VALUE;
	      new_reverse_frame[i].value = operands[1];
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_ORI:
	      if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE)
		{
		  /* We have a value in A -- we can do this.  */
		  new_reverse_frame[i] = reverse_frame[operands[1]];
		  new_reverse_frame[i].value
		    = reverse_frame[operands[1]].value | operands[2];
		}
	      else if (operands[2] == 0)
		{
		  /* This is a move.  */
		  new_reverse_frame[i] = reverse_frame[operands[1]];
		}
	      else
		{
		  /* We don't know anything about the values.  Punt.  */
		  new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		}
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_OR:
	      if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
		  && reverse_frame[operands[1]].value == 0)
		{
		  /* This is a move.  */
		  new_reverse_frame[i] = reverse_frame[operands[2]];
		}
	      else if (reverse_frame[operands[2]].state == REVERSE_STATE_VALUE
		       && reverse_frame[operands[2]].value == 0)
		{
		  /* This is a move.  */
		  new_reverse_frame[i] = reverse_frame[operands[1]];
		}
	      else
		{
		  /* We don't know anything about the values.  Punt.  */
		  new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		}
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;
	    case TILEGX_OPC_SUB:
	      if (reverse_frame[operands[1]].state == REVERSE_STATE_VALUE
		  && reverse_frame[operands[2]].state == REVERSE_STATE_VALUE)
		{
		  /* We have values -- we can do this.  */
		  new_reverse_frame[i] = reverse_frame[operands[1]];
		  new_reverse_frame[i].value
		    -= reverse_frame[operands[2]].value;
		}
	      else
		{
		  /* We don't know anything about the values.  Punt.  */
		  new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		}
	      reverse_frame_valid |= 1 << i;
	      dest_regs[i] = operands[0];
	      break;

	    case TILEGX_OPC_FNOP:
	    case TILEGX_OPC_INFO:
	    case TILEGX_OPC_INFOL:
	      /* Nothing to see here, move on.
		 Note that real NOP is treated as a 'real' instruction
		 because someone must have intended that it be there.
		 It therefore terminates the prolog.  */
	      break;

	    case TILEGX_OPC_J:
	    case TILEGX_OPC_JAL:

	    case TILEGX_OPC_BEQZ:
	    case TILEGX_OPC_BEQZT:
	    case TILEGX_OPC_BGEZ:
	    case TILEGX_OPC_BGEZT:
	    case TILEGX_OPC_BGTZ:
	    case TILEGX_OPC_BGTZT:
	    case TILEGX_OPC_BLBC:
	    case TILEGX_OPC_BLBCT:
	    case TILEGX_OPC_BLBS:
	    case TILEGX_OPC_BLBST:
	    case TILEGX_OPC_BLEZ:
	    case TILEGX_OPC_BLEZT:
	    case TILEGX_OPC_BLTZ:
	    case TILEGX_OPC_BLTZT:
	    case TILEGX_OPC_BNEZ:
	    case TILEGX_OPC_BNEZT:

	    case TILEGX_OPC_IRET:
	    case TILEGX_OPC_JALR:
	    case TILEGX_OPC_JALRP:
	    case TILEGX_OPC_JR:
	    case TILEGX_OPC_JRP:
	    case TILEGX_OPC_SWINT0:
	    case TILEGX_OPC_SWINT1:
	    case TILEGX_OPC_SWINT2:
	    case TILEGX_OPC_SWINT3:
	      /* We're really done -- this is a branch.  */
	      branch_seen = 1;
	      prolog_done = 1;
	      break;
	    default:
	      /* We don't know or care what this instruction is.
		 All we know is that it isn't part of a prolog, and if
		 there's a destination register, we're trashing it.  */
	      prolog_done = 1;
	      for (j = 0; j < opcode->num_operands; j++)
		{
		  if (this_insn->operands[j]->is_dest_reg)
		    {
		      dest_regs[i] = operands[j];
		      new_reverse_frame[i].state = REVERSE_STATE_UNKNOWN;
		      reverse_frame_valid |= 1 << i;
		      break;
		    }
		}
	      break;
	    }
	}

      /* Now update the reverse frames.  */
      for (i = 0; i < num_insns; i++)
	{
	  /* ISSUE: Does this properly handle "network" registers?  */
	  if ((reverse_frame_valid & (1 << i))
	      && dest_regs[i] != TILEGX_ZERO_REGNUM)
	    reverse_frame[dest_regs[i]] = new_reverse_frame[i];
	}

      if (prev_sp_value != 0)
	{
	  /* GCC uses R52 as a frame pointer.  Have we seen "move r52, sp"?  */
	  if (reverse_frame[TILEGX_R52_REGNUM].state == REVERSE_STATE_REGISTER
	      && reverse_frame[TILEGX_R52_REGNUM].value == TILEGX_SP_REGNUM)
	  {
	    reverse_frame[TILEGX_R52_REGNUM].state = REVERSE_STATE_VALUE;
	    reverse_frame[TILEGX_R52_REGNUM].value = prev_sp_value;
	  }

	  prev_sp_value = 0;
	}

      if (prolog_done && prolog_end == end_addr)
	{
	  /* We found non-prolog code.	As such, _this_ instruction
	     is the one after the prolog.  We keep processing, because
	     there may be more prolog code in there, but this is what
	     we'll return.  */
	  /* ISSUE: There may not have actually been a prologue, and
	     we may have simply skipped some random instructions.  */
	  prolog_end = next_addr;
	}
      if (branch_seen)
	{
	  /* We saw a branch.  The prolog absolutely must be over.  */
	  break;
	}
    }

  if (prolog_end == end_addr && cache)
    {
      /* We may have terminated the prolog early, and we're certainly
	 at THIS point right now.  It's possible that the values of
	 registers we need are currently actually in other registers
	 (and haven't been written to memory yet).  Go find them.  */
      for (i = 0; i < TILEGX_NUM_PHYS_REGS; i++)
	{
	  if (reverse_frame[i].state == REVERSE_STATE_REGISTER
	      && reverse_frame[i].value != i)
	    {
	      unsigned saved_register = (unsigned) reverse_frame[i].value;

	      cache->saved_regs[saved_register].realreg = i;
	      cache->saved_regs[saved_register].addr = (LONGEST) -1;
	    }
	}
    }

  if (lr_saved_on_stack_p)
    {
      cache->saved_regs[TILEGX_LR_REGNUM].realreg = TILEGX_LR_REGNUM;
      cache->saved_regs[TILEGX_LR_REGNUM].addr =
	cache->saved_regs[TILEGX_SP_REGNUM].addr;
    }

  return prolog_end;
}