Example #1
0
struct trad_frame_saved_reg *
sparc64nbsd_sigcontext_saved_regs (CORE_ADDR sigcontext_addr,
				   struct frame_info *next_frame)
{
  struct trad_frame_saved_reg *saved_regs;
  CORE_ADDR addr, sp;
  int regnum, delta;

  saved_regs = trad_frame_alloc_saved_regs (next_frame);

  /* The registers are saved in bits and pieces scattered all over the
     place.  The code below records their location on the assumption
     that the part of the signal trampoline that saves the state has
     been executed.  */

  saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
  saved_regs[SPARC64_PC_REGNUM].addr = sigcontext_addr + 16;
  saved_regs[SPARC64_NPC_REGNUM].addr = sigcontext_addr + 24;
  saved_regs[SPARC64_STATE_REGNUM].addr = sigcontext_addr + 32;
  saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 40;
  saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 48;

  /* The remaining `global' registers and %y are saved in the `local'
     registers.  */
  delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
  for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
    saved_regs[regnum].realreg = regnum + delta;
  saved_regs[SPARC64_Y_REGNUM].realreg = SPARC_L1_REGNUM;

  /* The remaining `out' registers can be found in the current frame's
     `in' registers.  */
  delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
  for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
    saved_regs[regnum].realreg = regnum + delta;
  saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;

  /* The `local' and `in' registers have been saved in the register
     save area.  */
  addr = saved_regs[SPARC_SP_REGNUM].addr;
  sp = get_frame_memory_unsigned (next_frame, addr, 8);
  for (regnum = SPARC_L0_REGNUM, addr = sp + BIAS;
       regnum <= SPARC_I7_REGNUM; regnum++, addr += 8)
    saved_regs[regnum].addr = addr;

  /* Handle StackGhost.  */
  {
    ULONGEST wcookie = sparc_fetch_wcookie ();

    if (wcookie != 0)
      {
	ULONGEST i7;

	addr = saved_regs[SPARC_I7_REGNUM].addr;
	i7 = get_frame_memory_unsigned (next_frame, addr, 8);
	trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
      }
  }

  /* TODO: Handle the floating-point registers.  */

  return saved_regs;
}
Example #2
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;
  ULONGEST inst, inst2;
  LONGEST offset;
  int regnum;
  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 (status, 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;
}
Example #3
0
struct trad_frame_saved_reg *
sparc32nbsd_sigcontext_saved_regs (struct frame_info *next_frame)
{
  struct trad_frame_saved_reg *saved_regs;
  CORE_ADDR addr, sigcontext_addr;
  int regnum, delta;
  ULONGEST psr;

  saved_regs = trad_frame_alloc_saved_regs (next_frame);

  /* We find the appropriate instance of `struct sigcontext' at a
     fixed offset in the signal frame.  */
  addr = frame_unwind_register_unsigned (next_frame, SPARC_FP_REGNUM);
  sigcontext_addr = addr + 64 + 16;

  /* The registers are saved in bits and pieces scattered all over the
     place.  The code below records their location on the assumption
     that the part of the signal trampoline that saves the state has
     been executed.  */

  saved_regs[SPARC_SP_REGNUM].addr = sigcontext_addr + 8;
  saved_regs[SPARC32_PC_REGNUM].addr = sigcontext_addr + 12;
  saved_regs[SPARC32_NPC_REGNUM].addr = sigcontext_addr + 16;
  saved_regs[SPARC32_PSR_REGNUM].addr = sigcontext_addr + 20;
  saved_regs[SPARC_G1_REGNUM].addr = sigcontext_addr + 24;
  saved_regs[SPARC_O0_REGNUM].addr = sigcontext_addr + 28;

  /* The remaining `global' registers and %y are saved in the `local'
     registers.  */
  delta = SPARC_L0_REGNUM - SPARC_G0_REGNUM;
  for (regnum = SPARC_G2_REGNUM; regnum <= SPARC_G7_REGNUM; regnum++)
    saved_regs[regnum].realreg = regnum + delta;
  saved_regs[SPARC32_Y_REGNUM].realreg = SPARC_L1_REGNUM;

  /* The remaining `out' registers can be found in the current frame's
     `in' registers.  */
  delta = SPARC_I0_REGNUM - SPARC_O0_REGNUM;
  for (regnum = SPARC_O1_REGNUM; regnum <= SPARC_O5_REGNUM; regnum++)
    saved_regs[regnum].realreg = regnum + delta;
  saved_regs[SPARC_O7_REGNUM].realreg = SPARC_I7_REGNUM;

  /* The `local' and `in' registers have been saved in the register
     save area.  */
  addr = saved_regs[SPARC_SP_REGNUM].addr;
  addr = get_frame_memory_unsigned (next_frame, addr, 4);
  for (regnum = SPARC_L0_REGNUM;
       regnum <= SPARC_I7_REGNUM; regnum++, addr += 4)
    saved_regs[regnum].addr = addr;

  /* Handle StackGhost.  */
  {
    ULONGEST wcookie = sparc_fetch_wcookie ();

    if (wcookie != 0)
      {
	ULONGEST i7;

	addr = saved_regs[SPARC_I7_REGNUM].addr;
	i7 = get_frame_memory_unsigned (next_frame, addr, 4);
	trad_frame_set_value (saved_regs, SPARC_I7_REGNUM, i7 ^ wcookie);
      }
  }

  /* The floating-point registers are only saved if the EF bit in %prs
     has been set.  */

#define PSR_EF	0x00001000

  addr = saved_regs[SPARC32_PSR_REGNUM].addr;
  psr = get_frame_memory_unsigned (next_frame, addr, 4);
  if (psr & PSR_EF)
    {
      CORE_ADDR sp;

      sp = frame_unwind_register_unsigned (next_frame, SPARC_SP_REGNUM);
      saved_regs[SPARC32_FSR_REGNUM].addr = sp + 96;
      for (regnum = SPARC_F0_REGNUM, addr = sp + 96 + 8;
	   regnum <= SPARC_F31_REGNUM; regnum++, addr += 4)
	saved_regs[regnum].addr = addr;
    }

  return saved_regs;
}