Пример #1
0
static void
frv_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
                          int reg, const gdb_byte *buffer)
{
  if (reg == iacc0_regnum)
    {
      regcache_raw_write (regcache, iacc0h_regnum, buffer);
      regcache_raw_write (regcache, iacc0l_regnum, (bfd_byte *) buffer + 4);
    }
  else if (accg0_regnum <= reg && reg <= accg7_regnum)
    {
      /* The accg raw registers have four values in each slot with the
         lowest register number occupying the first byte.  */

      int raw_regnum = accg0123_regnum + (reg - accg0_regnum) / 4;
      int byte_num = (reg - accg0_regnum) % 4;
      char buf[4];

      regcache_raw_read (regcache, raw_regnum, buf);
      buf[byte_num] = ((bfd_byte *) buffer)[0];
      regcache_raw_write (regcache, raw_regnum, buf);
    }
}
Пример #2
0
static void
m68k_store_return_value (struct type *type, struct regcache *regcache,
			 const gdb_byte *valbuf)
{
  int len = TYPE_LENGTH (type);

  if (len <= 4)
    regcache_raw_write_part (regcache, M68K_D0_REGNUM, 4 - len, len, valbuf);
  else if (len <= 8)
    {
      regcache_raw_write_part (regcache, M68K_D0_REGNUM, 8 - len,
			       len - 4, valbuf);
      regcache_raw_write (regcache, M68K_D1_REGNUM, valbuf + (len - 4));
    }
  else
    internal_error (__FILE__, __LINE__,
		    _("Cannot store return value of %d bytes long."), len);
}
Пример #3
0
static void
fetch_core_registers (char *core_reg_sect, unsigned core_reg_size,
		      int which, CORE_ADDR reg_addr)
{
  char *srcp = core_reg_sect;
  int regsize = mips_isa_regsize (current_gdbarch);
  int regno;

  /* If regsize is 8, this is a N32 or N64 core file.
     If regsize is 4, this is an O32 core file.  */
  if (core_reg_size != regsize * NUM_REGS)
    {
      warning (_("wrong size gregset struct in core file"));
      return;
    }

  for (regno = 0; regno < NUM_REGS; regno++)
    {
      regcache_raw_write (current_regcache, regno, srcp);
      srcp += regsize;
    }
}
Пример #4
0
static void
ppc_push_argument (struct ppc_stack_abi *abi, 
		   struct ppc_stack_context *c, struct value *arg,
		   int argno, int do_copy, int floatonly)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);

  struct type *type = check_typedef (value_type (arg));
  int len = TYPE_LENGTH (type);

  gdb_byte buf[16];

  c->argoffset = ROUND_UP (c->argoffset, 4);

  switch (TYPE_CODE (type)) {
      
  case TYPE_CODE_FLT:
    {
      if (c->freg <= abi->last_freg)
	{
	  struct value *rval;
	  struct type *rtype;
	  int rlen;
	  /* APPLE LOCAL: If the thing is already a long double type,
	     don't cast it to a builtin type double, since there are two
	     long double types, and we will pass an 16 byte long double
	     wrong if we assume it is an 8 byte double.  */
	  if (strcmp (TYPE_NAME (type), "long double") != 0)
	    {
	      rval  = value_cast (builtin_type_double, arg);
	      rtype = check_typedef (value_type (rval));
	      rlen = TYPE_LENGTH (rtype);
	    }
	  else
	    {
	      rval = arg;
	      rtype = type;
	      rlen = len;
	    }

	  /* APPLE LOCAL: GCC 4.0 has 16 byte long doubles */
	  if ((len != 4) && (len != 8) && (len != 16))
	    error ("floating point parameter had unexpected size");

	  if (rlen != 8 && rlen != 16)
	    error ("floating point parameter had unexpected size");

	  if (do_copy)
	    regcache_raw_write (current_regcache, FP0_REGNUM + c->freg, 
				value_contents (rval));
	  if (do_copy && ! floatonly && abi->fregs_shadow_gregs)
	    ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, len, value_contents (arg));
	  if (do_copy && ! floatonly && abi->regs_shadow_stack)
	    write_memory (c->sp + c->argoffset, value_contents (arg), len);

	  c->freg++;
	  /* APPLE LOCAL: We took up two registers...  */
	  if (rlen == 16)
	    c->freg++;

	  if (! floatonly && (abi->fregs_shadow_gregs) && (c->greg <= abi->last_greg))
	    c->greg += len / 4;
	  if (! floatonly && abi->regs_shadow_stack)
	    c->argoffset += len;
	}
      else if (! floatonly)
	{
	  if ((len != 4) && (len != 8) && (len != 16))
	    error ("floating point parameter had unexpected size");

	  c->argoffset = ROUND_UP (c->argoffset, len);
	  if (do_copy)
	    write_memory (c->sp + c->argoffset, value_contents (arg), len);
	  c->argoffset += len;
	}
      break;
    }

  case TYPE_CODE_INT:
  case TYPE_CODE_ENUM:
  case TYPE_CODE_PTR:
  case TYPE_CODE_REF:
    {
      int nregs;
      gdb_byte *val_contents;

      if (floatonly)
	break;

      /* APPLE LOCAL: Huge Hack...  The problem is that if we are a 32
	 bit app on Mac OS X, the registers are really 64 bits, but we
	 don't want to pass all 64 bits.  So if we get passed a value
	 that came from a register, and it's length is > the wordsize,
	 cast it to the wordsize first before passing it in.  */
      if (VALUE_REGNUM (arg) != -1 && len == 8 && tdep->wordsize == 4)
	{
	  len = 4;
	  val_contents = value_contents (arg) + 4;
	}
      else
	val_contents = value_contents (arg);
      /* END APPLE LOCAL  */

      nregs = (len <= 4) ? 1 : 2;
      if ((len != 1) && (len != 2) && (len != 4) && (len != 8))
	error ("integer parameter had unexpected size");

      if (c->greg <= abi->last_greg)
	{
	  /* If the parameter fits in the remaining argument registers, write it to
	     the registers, and to the stack if the abi requires it. */

	  if (do_copy)
	    {
	      /* Split the argument between registers & the stack if it
		 doesn't fit in the remaining registers.  */
	      int regs_avaliable = abi->last_greg - c->greg + 1;
	      if (regs_avaliable >= nregs)
		regs_avaliable = nregs;

	      ppc_copy_into_greg (current_regcache, c->greg, 
				  tdep->wordsize, regs_avaliable * 4, val_contents);
	    }
	  if (do_copy && abi->regs_shadow_stack)
	    write_memory (c->sp + c->argoffset, val_contents, len);

	  c->greg += nregs;
	  if (abi->regs_shadow_stack)
	    c->argoffset += (nregs * 4);
	}
      else 
	{
	  /* If we've filled up the registers, then just write it on the stack. */

	  if (do_copy)
	    write_memory (c->sp + c->argoffset, val_contents, len);
	  c->argoffset += (nregs * 4);
	}
      break;
    }

  case TYPE_CODE_STRUCT:
  case TYPE_CODE_UNION:
    {
      if (! abi->structs_with_args)
	{
	  if (floatonly)
	    break;

	  if (len > 4)
	    {
	      /* Rounding to the nearest multiple of 8 may not be necessary,
		 but it is safe.  Particularly since we don't know the
		 field types of the structure */
	      c->structoffset = ROUND_UP (c->structoffset, 8);
	      if (do_copy)
		{
		  write_memory (c->sp + c->structoffset, value_contents (arg), len);
		  store_unsigned_integer (buf, 4, c->sp + c->structoffset);
		}
	      c->structoffset += ROUND_UP (len, 8);
	    }
	  else
	    if (do_copy)
	      {
		memset (buf, 0, 4);
		memcpy (buf, value_contents (arg), len);
	      }

	  if (c->greg <= abi->last_greg)
	    {
	      if (do_copy)
		ppc_copy_into_greg (current_regcache, c->greg, tdep->wordsize, 4, buf);
	      c->greg++;
	    }
	  else
	    {
	      if (do_copy)
		write_memory (c->sp + c->argoffset, buf, 4);
	      c->argoffset += 4;
	    }
	  break;
	}
      else
	{
	  int i;
	  int regspace = (abi->last_greg - c->greg + 1) * 4;
	  int stackspace = (len <= regspace) ? 0 : (len - regspace);
	  int writereg = (regspace > len) ? len : regspace;
	  int writestack = abi->regs_shadow_stack ? len : stackspace;

	  for (i = 0; i < TYPE_NFIELDS (type); i++)
	    {
	      struct value *subarg = value_field (arg, i);

	      ppc_push_argument (abi, c, subarg, argno, do_copy, 1);
	    }

	  if (floatonly)
	    break;

	  if (do_copy)
	    {
	      gdb_byte *ptr = value_contents (arg);
	      if (len < 4)
		{
		  memset (buf, 0, 4);
		  if ((len == 1) || (len == 2))
		    memcpy (buf + 4 - len, ptr, len);
		  else
		    memcpy (buf, ptr, len);
		  ptr = buf;
		}
	      ppc_copy_into_greg (current_regcache, c->greg, 
				  tdep->wordsize, (writereg < 4) ? 4 : writereg, ptr);
	      write_memory (c->sp + c->argoffset, ptr,
			    (writestack < 4) ? 4 : writestack);
	    }

	  c->greg += ROUND_UP (writereg, 4) / 4;
	  c->argoffset += writestack;
	}
      break;
    }

  case TYPE_CODE_ARRAY:
    {
      if (floatonly)
	break;

      if (! TYPE_VECTOR (type))
	error ("non-vector array type");
      if (len != 16)
	error ("unexpected vector length");

      if (c->vreg <= abi->last_vreg)
	{
	  if (do_copy)
	    regcache_raw_write (current_regcache, tdep->ppc_vr0_regnum + c->vreg,
				value_contents (arg));
	  c->vreg++;
	}
      else
	{
	  /* Vector arguments must be aligned to 16 bytes on
	     the stack. */
	  c->argoffset = ROUND_UP (c->argoffset, 16);
	  if (do_copy)
	    write_memory (c->sp + c->argoffset, value_contents (arg), len);
	  c->argoffset += len;
	}
      break;
    }

  default:
    error ("argument %d has unknown type code 0x%x (%s)",
	   argno, TYPE_CODE (type),
	   type_code_name (TYPE_CODE (type)));
  }

  return;
}
Пример #5
0
static CORE_ADDR
m88k_store_arguments (struct regcache *regcache, int nargs,
		      struct value **args, CORE_ADDR sp)
{
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  int num_register_words = 0;
  int num_stack_words = 0;
  int i;

  for (i = 0; i < nargs; i++)
    {
      struct type *type = value_type (args[i]);
      int len = TYPE_LENGTH (type);

      if (m88k_integral_or_pointer_p (type) && len < 4)
	{
	  args[i] = value_cast (builtin_type (gdbarch)->builtin_int32,
				args[i]);
	  type = value_type (args[i]);
	  len = TYPE_LENGTH (type);
	}

      if (m88k_in_register_p (type))
	{
	  int num_words = 0;

	  if (num_register_words % 2 == 1 && m88k_8_byte_align_p (type))
	    num_words++;

	  num_words += ((len + 3) / 4);
	  if (num_register_words + num_words <= 8)
	    {
	      num_register_words += num_words;
	      continue;
	    }

	  /* We've run out of available registers.  Pass the argument
             on the stack.  */
	}

      if (num_stack_words % 2 == 1 && m88k_8_byte_align_p (type))
	num_stack_words++;

      num_stack_words += ((len + 3) / 4);
    }

  /* Allocate stack space.  */
  sp = align_down (sp - 32 - num_stack_words * 4, 16);
  num_stack_words = num_register_words = 0;

  for (i = 0; i < nargs; i++)
    {
      const bfd_byte *valbuf = value_contents (args[i]);
      struct type *type = value_type (args[i]);
      int len = TYPE_LENGTH (type);
      int stack_word = num_stack_words;

      if (m88k_in_register_p (type))
	{
	  int register_word = num_register_words;

	  if (register_word % 2 == 1 && m88k_8_byte_align_p (type))
	    register_word++;

	  gdb_assert (len == 4 || len == 8);

	  if (register_word + len / 8 < 8)
	    {
	      int regnum = M88K_R2_REGNUM + register_word;

	      regcache_raw_write (regcache, regnum, valbuf);
	      if (len > 4)
		regcache_raw_write (regcache, regnum + 1, valbuf + 4);

	      num_register_words = (register_word + len / 4);
	      continue;
	    }
	}

      if (stack_word % 2 == -1 && m88k_8_byte_align_p (type))
	stack_word++;

      write_memory (sp + stack_word * 4, valbuf, len);
      num_stack_words = (stack_word + (len + 3) / 4);
    }

  return sp;
}
Пример #6
0
static CORE_ADDR
i386_darwin_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
			     struct regcache *regcache, CORE_ADDR bp_addr,
			     int nargs, struct value **args, CORE_ADDR sp,
			     int struct_return, CORE_ADDR struct_addr)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  gdb_byte buf[4];
  int i;
  int write_pass;

  /* Determine the total space required for arguments and struct
     return address in a first pass, then push arguments in a second pass.  */

  for (write_pass = 0; write_pass < 2; write_pass++)
    {
      int args_space = 0;
      int num_m128 = 0;

      if (struct_return)
	{
	  if (write_pass)
	    {
	      /* Push value address.  */
	      store_unsigned_integer (buf, 4, byte_order, struct_addr);
	      write_memory (sp, buf, 4);
	    }
          args_space += 4;
	}

      for (i = 0; i < nargs; i++)
	{
          struct type *arg_type = value_enclosing_type (args[i]);

          if (i386_m128_p (arg_type) && num_m128 < 4)
            {
              if (write_pass)
                {
                  const gdb_byte *val = value_contents_all (args[i]);
                  regcache_raw_write
                    (regcache, I387_MM0_REGNUM(tdep) + num_m128, val);
                }
              num_m128++;
            }
          else
            {
              args_space = align_up (args_space,
				     i386_darwin_arg_type_alignment (arg_type));
              if (write_pass)
                write_memory (sp + args_space,
                              value_contents_all (args[i]),
			      TYPE_LENGTH (arg_type));

              /* The System V ABI says that:
                 
                 "An argument's size is increased, if necessary, to make it a
                 multiple of [32-bit] words.  This may require tail padding,
                 depending on the size of the argument."
                 
                 This makes sure the stack stays word-aligned.  */
              args_space += align_up (TYPE_LENGTH (arg_type), 4);
            }
        }

      /* Darwin i386 ABI:
	 1.  The caller ensures that the stack is 16-byte aligned at the point
	     of the function call.  */
      if (!write_pass)
	sp = align_down (sp - args_space, 16);
    }

  /* Store return address.  */
  sp -= 4;
  store_unsigned_integer (buf, 4, byte_order, bp_addr);
  write_memory (sp, buf, 4);

  /* Finally, update the stack pointer...  */
  store_unsigned_integer (buf, 4, byte_order, sp);
  regcache_cooked_write (regcache, I386_ESP_REGNUM, buf);

  /* ...and fake a frame pointer.  */
  regcache_cooked_write (regcache, I386_EBP_REGNUM, buf);

  /* MarkK wrote: This "+ 8" is all over the place:
     (i386_frame_this_id, i386_sigtramp_frame_this_id,
     i386_dummy_id).  It's there, since all frame unwinders for
     a given target have to agree (within a certain margin) on the
     definition of the stack address of a frame.  Otherwise frame id
     comparison might not work correctly.  Since DWARF2/GCC uses the
     stack address *before* the function call as a frame's CFA.  On
     the i386, when %ebp is used as a frame pointer, the offset
     between the contents %ebp and the CFA as defined by GCC.  */
  return sp + 8;
}