Esempio n. 1
0
int
arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr)
{
  if (arm_is_thumb_mode ())
    {
      *pcptr = MAKE_THUMB_ADDR (*pcptr);
      return arm_breakpoint_kind_from_pc (pcptr);
    }
  else
    {
      return arm_breakpoint_kind_from_pc (pcptr);
    }
}
Esempio n. 2
0
/* When PC is at a syscall instruction, return the PC of the next
   instruction to be executed.  */
static CORE_ADDR
get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self)
{
  CORE_ADDR next_pc = 0;
  CORE_ADDR pc = regcache_read_pc (self->regcache);
  int is_thumb = arm_is_thumb_mode ();
  ULONGEST svc_number = 0;
  struct regcache *regcache = self->regcache;

  if (is_thumb)
    {
      collect_register (regcache, 7, &svc_number);
      next_pc = pc + 2;
    }
  else
    {
      unsigned long this_instr;
      unsigned long svc_operand;

      target_read_memory (pc, (unsigned char *) &this_instr, 4);
      svc_operand = (0x00ffffff & this_instr);

      if (svc_operand)  /* OABI.  */
	{
	  svc_number = svc_operand - 0x900000;
	}
      else /* EABI.  */
	{
	  collect_register (regcache, 7, &svc_number);
	}

      next_pc = pc + 4;
    }

  /* This is a sigreturn or sigreturn_rt syscall.  */
  if (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn)
    {
      /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so
	 update IS_THUMB.   */
      next_pc = arm_sigreturn_next_pc (regcache, svc_number, &is_thumb);
    }

  /* Addresses for calling Thumb functions have the bit 0 set.  */
  if (is_thumb)
    next_pc = MAKE_THUMB_ADDR (next_pc);

  return next_pc;
}
Esempio n. 3
0
static CORE_ADDR
arm_linux_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
		          int struct_return, CORE_ADDR struct_addr)
{
  char *fp;
  int argnum, argreg, nstack_size;

  /* Walk through the list of args and determine how large a temporary
     stack is required.  Need to take care here as structs may be
     passed on the stack, and we have to to push them.  */
  nstack_size = -4 * REGISTER_SIZE;	/* Some arguments go into A1-A4.  */

  if (struct_return)			/* The struct address goes in A1.  */
    nstack_size += REGISTER_SIZE;

  /* Walk through the arguments and add their size to nstack_size.  */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      int len;
      struct type *arg_type;

      arg_type = check_typedef (VALUE_TYPE (args[argnum]));
      len = TYPE_LENGTH (arg_type);

      /* ANSI C code passes float arguments as integers, K&R code
         passes float arguments as doubles.  Correct for this here.  */
      if (TYPE_CODE_FLT == TYPE_CODE (arg_type) && REGISTER_SIZE == len)
	nstack_size += FP_REGISTER_VIRTUAL_SIZE;
      else
	nstack_size += len;
    }

  /* Allocate room on the stack, and initialize our stack frame
     pointer.  */
  fp = NULL;
  if (nstack_size > 0)
    {
      sp -= nstack_size;
      fp = (char *) sp;
    }

  /* Initialize the integer argument register pointer.  */
  argreg = ARM_A1_REGNUM;

  /* The struct_return pointer occupies the first parameter passing
     register.  */
  if (struct_return)
    write_register (argreg++, struct_addr);

  /* Process arguments from left to right.  Store as many as allowed
     in the parameter passing registers (A1-A4), and save the rest on
     the temporary stack.  */
  for (argnum = 0; argnum < nargs; argnum++)
    {
      int len;
      char *val;
      CORE_ADDR regval;
      enum type_code typecode;
      struct type *arg_type, *target_type;

      arg_type = check_typedef (VALUE_TYPE (args[argnum]));
      target_type = TYPE_TARGET_TYPE (arg_type);
      len = TYPE_LENGTH (arg_type);
      typecode = TYPE_CODE (arg_type);
      val = (char *) VALUE_CONTENTS (args[argnum]);

      /* ANSI C code passes float arguments as integers, K&R code
         passes float arguments as doubles.  The .stabs record for 
         for ANSI prototype floating point arguments records the
         type as FP_INTEGER, while a K&R style (no prototype)
         .stabs records the type as FP_FLOAT.  In this latter case
         the compiler converts the float arguments to double before
         calling the function.  */
      if (TYPE_CODE_FLT == typecode && REGISTER_SIZE == len)
	{
	  DOUBLEST dblval;
	  dblval = extract_floating (val, len);
	  len = TARGET_DOUBLE_BIT / TARGET_CHAR_BIT;
	  val = alloca (len);
	  store_floating (val, len, dblval);
	}

      /* If the argument is a pointer to a function, and it is a Thumb
         function, set the low bit of the pointer.  */
      if (TYPE_CODE_PTR == typecode
	  && NULL != target_type
	  && TYPE_CODE_FUNC == TYPE_CODE (target_type))
	{
	  CORE_ADDR regval = extract_address (val, len);
	  if (arm_pc_is_thumb (regval))
	    store_address (val, len, MAKE_THUMB_ADDR (regval));
	}

      /* Copy the argument to general registers or the stack in
         register-sized pieces.  Large arguments are split between
         registers and stack.  */
      while (len > 0)
	{
	  int partial_len = len < REGISTER_SIZE ? len : REGISTER_SIZE;

	  if (argreg <= ARM_LAST_ARG_REGNUM)
	    {
	      /* It's an argument being passed in a general register.  */
	      regval = extract_address (val, partial_len);
	      write_register (argreg++, regval);
	    }
	  else
	    {
	      /* Push the arguments onto the stack.  */
	      write_memory ((CORE_ADDR) fp, val, REGISTER_SIZE);
	      fp += REGISTER_SIZE;
	    }

	  len -= partial_len;
	  val += partial_len;
	}
    }

  /* Return adjusted stack pointer.  */
  return sp;
}
Esempio n. 4
0
CORE_ADDR
arm_linux_get_next_pcs_fixup (struct arm_get_next_pcs *self,
			      CORE_ADDR nextpc)
{
  /* The Linux kernel offers some user-mode helpers in a high page.  We can
     not read this page (as of 2.6.23), and even if we could then we
     couldn't set breakpoints in it, and even if we could then the atomic
     operations would fail when interrupted.  They are all (tail) called
     as functions and return to the address in LR.  However, when GDB single
     step this instruction, this instruction isn't executed yet, and LR
     may not be updated yet.  In other words, GDB can get the target
     address from LR if this instruction isn't BL or BLX.  */
  if (nextpc > 0xffff0000)
    {
      int bl_blx_p = 0;
      CORE_ADDR pc = regcache_read_pc (self->regcache);
      int pc_incr = 0;

      if (self->ops->is_thumb (self))
	{
	  unsigned short inst1
	    = self->ops->read_mem_uint (pc, 2, self->byte_order_for_code);

	  if (bits (inst1, 8, 15) == 0x47 && bit (inst1, 7))
	    {
	      /* BLX Rm */
	      bl_blx_p = 1;
	      pc_incr = 2;
	    }
	  else if (thumb_insn_size (inst1) == 4)
	    {
	      unsigned short inst2;

	      inst2 = self->ops->read_mem_uint (pc + 2, 2,
						self->byte_order_for_code);

	      if ((inst1 & 0xf800) == 0xf000 && bits (inst2, 14, 15) == 0x3)
		{
		  /* BL <label> and BLX <label> */
		  bl_blx_p = 1;
		  pc_incr = 4;
		}
	    }

	  pc_incr = MAKE_THUMB_ADDR (pc_incr);
	}
      else
	{
	  unsigned int insn
	    = self->ops->read_mem_uint (pc, 4, self->byte_order_for_code);

	  if (bits (insn, 28, 31) == INST_NV)
	    {
	      if (bits (insn, 25, 27) == 0x5) /* BLX <label> */
		bl_blx_p = 1;
	    }
	  else
	    {
	      if (bits (insn, 24, 27) == 0xb  /* BL <label> */
		  || bits (insn, 4, 27) == 0x12fff3 /* BLX Rm */)
		bl_blx_p = 1;
	    }

	  pc_incr = 4;
	}

      /* If the instruction BL or BLX, the target address is the following
	 instruction of BL or BLX, otherwise, the target address is in LR
	 already.  */
      if (bl_blx_p)
	nextpc = pc + pc_incr;
      else
	nextpc = regcache_raw_get_unsigned (self->regcache, ARM_LR_REGNUM);
    }
  return nextpc;
}