Ejemplo n.º 1
0
static int
sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, const char *name)
{
  CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
  unsigned long insn;
  const int *offset;

  if (name)
    return 0;

  for (offset = sparc64obsd_sigreturn_offset; *offset != -1; offset++)
    {
      /* Check for "restore %g0, SYS_sigreturn, %g1".  */
      insn = sparc_fetch_instruction (start_pc + *offset);
      if (insn != 0x83e82067)
	continue;

      /* Check for "t ST_SYSCALL".  */
      insn = sparc_fetch_instruction (start_pc + *offset + 8);
      if (insn != 0x91d02000)
	continue;

      return 1;
    }

  return 0;
}
Ejemplo n.º 2
0
CORE_ADDR
sparc_analyze_prologue (CORE_ADDR pc, CORE_ADDR current_pc,
			struct sparc_frame_cache *cache)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
  unsigned long insn;
  int offset = 0;
  int dest = -1;

  if (current_pc <= pc)
    return current_pc;

  /* We have to handle to "Procedure Linkage Table" (PLT) special.  On
     SPARC the linker usually defines a symbol (typically
     _PROCEDURE_LINKAGE_TABLE_) at the start of the .plt section.
     This symbol makes us end up here with PC pointing at the start of
     the PLT and CURRENT_PC probably pointing at a PLT entry.  If we
     would do our normal prologue analysis, we would probably conclude
     that we've got a frame when in reality we don't, since the
     dynamic linker patches up the first PLT with some code that
     starts with a SAVE instruction.  Patch up PC such that it points
     at the start of our PLT entry.  */
  if (tdep->plt_entry_size > 0 && in_plt_section (current_pc, NULL))
    pc = current_pc - ((current_pc - pc) % tdep->plt_entry_size);

  insn = sparc_fetch_instruction (pc);

  /* Recognize a SETHI insn and record its destination.  */
  if (X_OP (insn) == 0 && X_OP2 (insn) == 0x04)
    {
      dest = X_RD (insn);
      offset += 4;

      insn = sparc_fetch_instruction (pc + 4);
    }

  /* Allow for an arithmetic operation on DEST or %g1.  */
  if (X_OP (insn) == 2 && X_I (insn)
      && (X_RD (insn) == 1 || X_RD (insn) == dest))
    {
      offset += 4;

      insn = sparc_fetch_instruction (pc + 8);
    }

  /* Check for the SAVE instruction that sets up the frame.  */
  if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3c)
    {
      cache->frameless_p = 0;
      return pc + offset + 4;
    }

  return pc;
}
Ejemplo n.º 3
0
static int
sparc_is_unimp_insn (CORE_ADDR pc)
{
  const unsigned long insn = sparc_fetch_instruction (pc);
  
  return ((insn & 0xc1c00000) == 0);
}
Ejemplo n.º 4
0
static int
sparc64obsd_pc_in_sigtramp (CORE_ADDR pc, char *name)
{
  CORE_ADDR start_pc = (pc & ~(sparc64obsd_page_size - 1));
  unsigned long insn;

  if (name)
    return 0;

  /* Check for "restore %g0, SYS_sigreturn, %g1".  */
  insn = sparc_fetch_instruction (start_pc + 0xe8);
  if (insn != 0x83e82067)
    return 0;

  /* Check for "t ST_SYSCALL".  */
  insn = sparc_fetch_instruction (start_pc + 0xf0);
  if (insn != 0x91d02000)
    return 0;

  return 1;
}
Ejemplo n.º 5
0
static CORE_ADDR
sparc32_skip_prologue (CORE_ADDR start_pc)
{
  struct symtab_and_line sal;
  CORE_ADDR func_start, func_end;
  struct sparc_frame_cache cache;

  /* This is the preferred method, find the end of the prologue by
     using the debugging information.  */
  if (find_pc_partial_function (start_pc, NULL, &func_start, &func_end))
    {
      sal = find_pc_line (func_start, 0);

      if (sal.end < func_end
	  && start_pc <= sal.end)
	return sal.end;
    }

  start_pc = sparc_analyze_prologue (start_pc, 0xffffffffUL, &cache);

  /* The psABI says that "Although the first 6 words of arguments
     reside in registers, the standard stack frame reserves space for
     them.".  It also suggests that a function may use that space to
     "write incoming arguments 0 to 5" into that space, and that's
     indeed what GCC seems to be doing.  In that case GCC will
     generate debug information that points to the stack slots instead
     of the registers, so we should consider the instructions that
     write out these incoming arguments onto the stack.  Of course we
     only need to do this if we have a stack frame.  */

  while (!cache.frameless_p)
    {
      unsigned long insn = sparc_fetch_instruction (start_pc);

      /* Recognize instructions that store incoming arguments in
         %i0...%i5 into the corresponding stack slot.  */
      if (X_OP (insn) == 3 && (X_OP3 (insn) & 0x3c) == 0x04 && X_I (insn)
	  && (X_RD (insn) >= 24 && X_RD (insn) <= 29) && X_RS1 (insn) == 30
	  && X_SIMM13 (insn) == 68 + (X_RD (insn) - 24) * 4)
	{
	  start_pc += 4;
	  continue;
	}

      break;
    }

  return start_pc;
}
Ejemplo n.º 6
0
static CORE_ADDR
sparc_analyze_control_transfer (struct gdbarch *arch,
				CORE_ADDR pc, CORE_ADDR *npc)
{
  unsigned long insn = sparc_fetch_instruction (pc);
  int conditional_p = X_COND (insn) & 0x7;
  int branch_p = 0;
  long offset = 0;			/* Must be signed for sign-extend.  */

  if (X_OP (insn) == 0 && X_OP2 (insn) == 3 && (insn & 0x1000000) == 0)
    {
      /* Branch on Integer Register with Prediction (BPr).  */
      branch_p = 1;
      conditional_p = 1;
    }
  else if (X_OP (insn) == 0 && X_OP2 (insn) == 6)
    {
      /* Branch on Floating-Point Condition Codes (FBfcc).  */
      branch_p = 1;
      offset = 4 * X_DISP22 (insn);
    }
  else if (X_OP (insn) == 0 && X_OP2 (insn) == 5)
    {
      /* Branch on Floating-Point Condition Codes with Prediction
         (FBPfcc).  */
      branch_p = 1;
      offset = 4 * X_DISP19 (insn);
    }
  else if (X_OP (insn) == 0 && X_OP2 (insn) == 2)
    {
      /* Branch on Integer Condition Codes (Bicc).  */
      branch_p = 1;
      offset = 4 * X_DISP22 (insn);
    }
  else if (X_OP (insn) == 0 && X_OP2 (insn) == 1)
    {
      /* Branch on Integer Condition Codes with Prediction (BPcc).  */
      branch_p = 1;
      offset = 4 * X_DISP19 (insn);
    }
  else if (X_OP (insn) == 2 && X_OP3 (insn) == 0x3a)
    {
      /* Trap instruction (TRAP).  */
      return gdbarch_tdep (arch)->step_trap (insn);
    }

  /* FIXME: Handle DONE and RETRY instructions.  */

  if (branch_p)
    {
      if (conditional_p)
	{
	  /* For conditional branches, return nPC + 4 iff the annul
	     bit is 1.  */
	  return (X_A (insn) ? *npc + 4 : 0);
	}
      else
	{
	  /* For unconditional branches, return the target if its
	     specified condition is "always" and return nPC + 4 if the
	     condition is "never".  If the annul bit is 1, set *NPC to
	     zero.  */
	  if (X_COND (insn) == 0x0)
	    pc = *npc, offset = 4;
	  if (X_A (insn))
	    *npc = 0;

	  gdb_assert (offset != 0);
	  return pc + offset;
	}
    }

  return 0;
}