Beispiel #1
0
static CORE_ADDR
i386syl_sigcontext_addr (struct frame_info *next_frame)
{
  CORE_ADDR pc;
  CORE_ADDR sp;
  char buf[4];

  frame_unwind_register (next_frame, I386_ESP_REGNUM, buf);
  sp = extract_unsigned_integer (buf, 4);

  pc = i386syl_sigtramp_start (next_frame);
  if (pc)
  {
    /* The sigcontext structure lives on the stack, right after
       the signum argument.  We determine the address of the
       sigcontext structure by looking at the frame's stack
       pointer.  Keep in mind that the first instruction of the
       sigtramp code is "pop %eax".  If the PC is after this
       instruction, adjust the returned value accordingly.  */
    if (pc == frame_pc_unwind (next_frame))
      return sp + 4;
    return sp;
  }

  error ("Couldn't recognize signal trampoline.");
  return 0;
}
static const struct frame_unwind *
amd64_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (next_frame));

  /* We shouldn't even bother if we don't have a sigcontext_addr
     handler.  */
  if (tdep->sigcontext_addr == NULL)
    return NULL;

  if (tdep->sigtramp_p != NULL)
    {
      if (tdep->sigtramp_p (next_frame))
	return &amd64_sigtramp_frame_unwind;
    }

  if (tdep->sigtramp_start != 0)
    {
      CORE_ADDR pc = frame_pc_unwind (next_frame);

      gdb_assert (tdep->sigtramp_end != 0);
      if (pc >= tdep->sigtramp_start && pc < tdep->sigtramp_end)
	return &amd64_sigtramp_frame_unwind;
    }

  return NULL;
}
static CORE_ADDR
amd64_linux_sigtramp_start (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  gdb_byte buf[LINUX_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 (next_frame, pc, buf, sizeof buf))
    return 0;

  if (buf[0] != LINUX_SIGTRAMP_INSN0)
    {
      if (buf[0] != LINUX_SIGTRAMP_INSN1)
	return 0;

      pc -= LINUX_SIGTRAMP_OFFSET1;
      if (!safe_frame_unwind_memory (next_frame, pc, buf, sizeof buf))
	return 0;
    }

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

  return pc;
}
Beispiel #4
0
static struct sparc_frame_cache *
sparc64obsd_frame_cache (struct frame_info *next_frame, void **this_cache)
{
  struct sparc_frame_cache *cache;
  CORE_ADDR addr;

  if (*this_cache)
    return *this_cache;

  cache = sparc_frame_cache (next_frame, this_cache);
  gdb_assert (cache == *this_cache);

  /* If we couldn't find the frame's function, we're probably dealing
     with an on-stack signal trampoline.  */
  if (cache->pc == 0)
    {
      cache->pc = frame_pc_unwind (next_frame);
      cache->pc &= ~(sparc64obsd_page_size - 1);

      /* Since we couldn't find the frame's function, the cache was
         initialized under the assumption that we're frameless.  */
      cache->frameless_p = 0;
      addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
      cache->base = addr;
    }

  /* We find the appropriate instance of `struct sigcontext' at a
     fixed offset in the signal frame.  */
  addr = cache->base + BIAS + 128 + 16;
  cache->saved_regs = sparc64nbsd_sigcontext_saved_regs (addr, next_frame);

  return cache;
}
static CORE_ADDR
alpha_linux_sigcontext_addr (struct frame_info *next_frame)
{
  CORE_ADDR pc;
  ULONGEST sp;
  long off;

  pc = frame_pc_unwind (next_frame);
  frame_unwind_unsigned_register (next_frame, ALPHA_SP_REGNUM, &sp);

  off = alpha_linux_sigtramp_offset (pc);
  gdb_assert (off >= 0);

  /* __NR_rt_sigreturn has a couple of structures on the stack.  This is:

	struct rt_sigframe {
	  struct siginfo info;
	  struct ucontext uc;
        };

	offsetof (struct rt_sigframe, uc.uc_mcontext);
  */
  if (alpha_read_insn (pc - off + 4) == 0x201f015f)
    return sp + 176;

  /* __NR_sigreturn has the sigcontext structure at the top of the stack.  */
  return sp;
}
static struct trad_frame_cache *
vaxobsd_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
{
  struct trad_frame_cache *cache;
  CORE_ADDR addr, base, func;

  if (*this_cache)
    return *this_cache;

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

  func = frame_pc_unwind (next_frame);
  func &= ~(vaxobsd_page_size - 1);

  base = frame_unwind_register_unsigned (next_frame, VAX_SP_REGNUM);
  addr = get_frame_memory_unsigned (next_frame, base - 4, 4);

  trad_frame_set_reg_addr (cache, VAX_SP_REGNUM, addr + 8);
  trad_frame_set_reg_addr (cache, VAX_FP_REGNUM, addr + 12);
  trad_frame_set_reg_addr (cache, VAX_AP_REGNUM, addr + 16);
  trad_frame_set_reg_addr (cache, VAX_PC_REGNUM, addr + 20);
  trad_frame_set_reg_addr (cache, VAX_PS_REGNUM, addr + 24);

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

  return cache;
}
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;
}
Beispiel #8
0
static int
tramp_frame_sniffer (const struct frame_unwind *self,
		     struct frame_info *next_frame,
		     void **this_cache)
{
  const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  CORE_ADDR func;
  char *name;
  struct tramp_frame_cache *tramp_cache;

  /* 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;
  /* Finally, check that the trampoline matches at PC.  */
  func = tramp_frame_start (tramp, next_frame, pc);
  if (func == 0)
    return 0;
  tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
  tramp_cache->func = func;
  tramp_cache->tramp_frame = tramp;
  (*this_cache) = tramp_cache;
  return 1;
}
Beispiel #9
0
static void
ppc_linux_sigtramp_cache (struct frame_info *next_frame,
			  struct trad_frame_cache *this_cache,
			  CORE_ADDR func, LONGEST offset,
			  int bias)
{
  CORE_ADDR base;
  CORE_ADDR regs;
  CORE_ADDR gpregs;
  CORE_ADDR fpregs;
  int i;
  struct gdbarch *gdbarch = get_frame_arch (next_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);

  base = frame_unwind_register_unsigned (next_frame,
					 gdbarch_sp_regnum (current_gdbarch));
  if (bias > 0 && frame_pc_unwind (next_frame) != func)
    /* See below, some signal trampolines increment the stack as their
       first instruction, need to compensate for that.  */
    base -= bias;

  /* Find the address of the register buffer pointer.  */
  regs = base + offset;
  /* Use that to find the address of the corresponding register
     buffers.  */
  gpregs = read_memory_unsigned_integer (regs, tdep->wordsize);
  fpregs = gpregs + 48 * tdep->wordsize;

  /* General purpose.  */
  for (i = 0; i < 32; i++)
    {
      int regnum = i + tdep->ppc_gp0_regnum;
      trad_frame_set_reg_addr (this_cache, regnum, gpregs + i * tdep->wordsize);
    }
  trad_frame_set_reg_addr (this_cache,
			   gdbarch_pc_regnum (current_gdbarch),
			   gpregs + 32 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_ctr_regnum,
			   gpregs + 35 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_lr_regnum,
			   gpregs + 36 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_xer_regnum,
			   gpregs + 37 * tdep->wordsize);
  trad_frame_set_reg_addr (this_cache, tdep->ppc_cr_regnum,
			   gpregs + 38 * tdep->wordsize);

  if (ppc_floating_point_unit_p (gdbarch))
    {
      /* Floating point registers.  */
      for (i = 0; i < 32; i++)
	{
	  int regnum = i + gdbarch_fp0_regnum (current_gdbarch);
	  trad_frame_set_reg_addr (this_cache, regnum,
				   fpregs + i * tdep->wordsize);
	}
      trad_frame_set_reg_addr (this_cache, tdep->ppc_fpscr_regnum,
                         fpregs + 32 * tdep->wordsize);
    }
  trad_frame_set_id (this_cache, frame_id_build (base, func));
}
Beispiel #10
0
/* Here is a dummy implementation.  */
static struct frame_id
mn10300_unwind_dummy_id (struct gdbarch *gdbarch,
			 struct frame_info *next_frame)
{
  return frame_id_build (frame_sp_unwind (next_frame), 
			 frame_pc_unwind (next_frame));
}
CORE_ADDR
glibc_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
  /* The GNU dynamic linker is part of the GNU C library, and is used
     by all GNU systems (GNU/Hurd, GNU/Linux).  An unresolved PLT
     entry points to "_dl_runtime_resolve", which calls "fixup" to
     patch the PLT, and then passes control to the function.

     We look for the symbol `_dl_runtime_resolve', and find `fixup' in
     the same objfile.  If we are at the entry point of `fixup', then
     we set a breakpoint at the return address (at the top of the
     stack), and continue.
  
     It's kind of gross to do all these checks every time we're
     called, since they don't change once the executable has gotten
     started.  But this is only a temporary hack --- upcoming versions
     of GNU/Linux will provide a portable, efficient interface for
     debugging programs that use shared libraries.  */

  struct objfile *objfile;
  struct minimal_symbol *resolver 
    = find_minsym_and_objfile ("_dl_runtime_resolve", &objfile);

  if (resolver)
    {
      struct minimal_symbol *fixup
	= lookup_minimal_symbol ("fixup", NULL, objfile);

      if (fixup && SYMBOL_VALUE_ADDRESS (fixup) == pc)
	return frame_pc_unwind (get_current_frame ());
    }

  return 0;
}      
static struct frame_id
m88k_unwind_dummy_id (struct gdbarch *arch, struct frame_info *next_frame)
{
  CORE_ADDR sp;

  sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM);
  return frame_id_build (sp, frame_pc_unwind (next_frame));
}
Beispiel #13
0
static struct frame_id
sparc_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
  CORE_ADDR sp;

  sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
  return frame_id_build (sp, frame_pc_unwind (next_frame));
}
Beispiel #14
0
static void
amd64_sigtramp_frame_this_id (struct frame_info *next_frame,
			      void **this_cache, struct frame_id *this_id)
{
  struct x86_frame_cache *cache =
    amd64_sigtramp_frame_cache (next_frame, this_cache);

  (*this_id) = frame_id_build (cache->frame_base + 8, frame_pc_unwind (next_frame));
}
static int
i386nto_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  return name && strcmp ("__signalstub", name) == 0;
}
static int
amd64_sol2_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  return (name && (strcmp ("sigacthandler", name) == 0
		   || strcmp (name, "ucbsigvechandler") == 0));
}
Beispiel #17
0
static int
i386nbsd_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  return (nbsd_pc_in_sigtramp (pc, name)
	  || i386nbsd_sigtramp_offset (next_frame) >= 0);
}
struct m88k_frame_cache *
m88k_frame_cache (struct frame_info *next_frame, void **this_cache)
{
  struct m88k_frame_cache *cache;
  CORE_ADDR frame_sp;

  if (*this_cache)
    return *this_cache;

  cache = FRAME_OBSTACK_ZALLOC (struct m88k_frame_cache);
  cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
  cache->fp_offset = -1;

  cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
  if (cache->pc != 0)
    m88k_analyze_prologue (cache->pc, frame_pc_unwind (next_frame), cache);

  /* Calculate the stack pointer used in the prologue.  */
  if (cache->fp_offset != -1)
    {
      CORE_ADDR fp;

      fp = frame_unwind_register_unsigned (next_frame, M88K_R30_REGNUM);
      frame_sp = fp - cache->fp_offset;
    }
  else
    {
      /* If we know where the return address is saved, we can take a
         solid guess at what the frame pointer should be.  */
      if (cache->saved_regs[M88K_R1_REGNUM].addr != -1)
	cache->fp_offset = cache->saved_regs[M88K_R1_REGNUM].addr - 4;
      frame_sp = frame_unwind_register_unsigned (next_frame, M88K_R31_REGNUM);
    }

  /* Now that we know the stack pointer, adjust the location of the
     saved registers.  */
  {
    int regnum;

    for (regnum = M88K_R0_REGNUM; regnum < M88K_R31_REGNUM; regnum ++)
      if (cache->saved_regs[regnum].addr != -1)
	cache->saved_regs[regnum].addr += frame_sp;
  }

  /* Calculate the frame's base.  */
  cache->base = frame_sp - cache->sp_offset;
  trad_frame_set_value (cache->saved_regs, M88K_R31_REGNUM, cache->base);

  /* Identify SXIP with the return address in R1.  */
  cache->saved_regs[M88K_SXIP_REGNUM] = cache->saved_regs[M88K_R1_REGNUM];

  *this_cache = cache;
  return cache;
}
Beispiel #19
0
static struct frame_id
amd64_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
  gdb_byte buf[8];
  CORE_ADDR fp;

  frame_unwind_register (next_frame, AMD64_RBP_REGNUM, buf);
  fp = extract_unsigned_integer (buf, 8);

  return frame_id_build (fp + 16, frame_pc_unwind (next_frame));
}
Beispiel #20
0
CORE_ADDR
obsd_skip_solib_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
  struct minimal_symbol *msym;

  msym = lookup_minimal_symbol("_dl_bind", NULL, NULL);
  if (msym && SYMBOL_VALUE_ADDRESS (msym) == pc)
    return frame_pc_unwind (get_current_frame ());
  else
    return find_solib_trampoline_target (get_current_frame (), pc);
}
Beispiel #21
0
static const struct frame_unwind *
sparc64_sol2_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (sparc_sol2_pc_in_sigtramp (pc, name))
    return &sparc64_sol2_sigtramp_frame_unwind;

  return NULL;
}
static struct trad_frame_cache *
ppcobsd_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache)
{
  struct gdbarch *gdbarch = get_frame_arch (next_frame);
  struct gdbarch_tdep *tdep = gdbarch_tdep (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 *this_cache;

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

  func = frame_pc_unwind (next_frame);
  func &= ~(ppcobsd_page_size - 1);
  if (!safe_frame_unwind_memory (next_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);
  sigcontext_offset = (0x10000 - (insn & 0x0000ffff)) + 8;

  base = frame_unwind_register_unsigned (next_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;
}
Beispiel #23
0
static CORE_ADDR
mips_linux_skip_resolver (struct gdbarch *gdbarch, CORE_ADDR pc)
{
  struct minimal_symbol *resolver;

  resolver = lookup_minimal_symbol ("__dl_runtime_resolve", NULL, NULL);

  if (resolver && SYMBOL_VALUE_ADDRESS (resolver) == pc)
    return frame_pc_unwind (get_current_frame ());

  return 0;
}
Beispiel #24
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;
}
Beispiel #25
0
static const struct frame_unwind *
sparc64nbsd_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

  find_pc_partial_function (pc, &name, NULL, NULL);
  if (sparc64nbsd_pc_in_sigtramp (pc, name))
    {
      if (name == NULL || strncmp (name, "__sigtramp_sigcontext", 21))
	return &sparc64nbsd_sigcontext_frame_unwind;
    }

  return NULL;
}
Beispiel #26
0
static struct trad_frame_cache *
tramp_frame_cache (struct frame_info *next_frame,
		   void **this_cache)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  struct tramp_frame_cache *tramp_cache = (*this_cache);
  if (tramp_cache->trad_cache == NULL)
    {
      tramp_cache->trad_cache = trad_frame_cache_zalloc (next_frame);
      tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
				      next_frame,
				      tramp_cache->trad_cache,
				      tramp_cache->func);
    }
  return tramp_cache->trad_cache;
}
Beispiel #27
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;
}
Beispiel #28
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;
}
static int
amd64_linux_sigtramp_p (struct frame_info *next_frame)
{
  CORE_ADDR pc = frame_pc_unwind (next_frame);
  char *name;

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

  /* If we have NAME, we can optimize the search.  The trampoline is
     named __restore_rt.  However, it isn't dynamically exported from
     the shared C library, so the trampoline may appear to be part of
     the preceding function.  This should always be sigaction,
     __sigaction, or __libc_sigaction (all aliases to the same
     function).  */
  if (name == NULL || strstr (name, "sigaction") != NULL)
    return (amd64_linux_sigtramp_start (next_frame) != 0);

  return (strcmp ("__restore_rt", name) == 0);
}
static int
amd64obsd_trapframe_sniffer (const struct frame_unwind *self,
			     struct frame_info *next_frame,
			     void **this_prologue_cache)
{
  ULONGEST cs;
  char *name;

  /* Check Current Privilege Level and bail out if we're not executing
     in kernel space.  */
  cs = frame_unwind_register_unsigned (next_frame, AMD64_CS_REGNUM);
  if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
    return 0;

  find_pc_partial_function (frame_pc_unwind (next_frame), &name, NULL, NULL);
  return (name && ((strcmp (name, "calltrap") == 0)
		   || (strcmp (name, "osyscall1") == 0)
		   || (strcmp (name, "Xsyscall") == 0)
		   || (strncmp (name, "Xintr", 5) == 0)));
}