Example #1
0
static int
allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
		    struct arg_type_info *info, struct value *valuep,
		    size_t sz)
{
	/* Note: here we shouldn't see large composite types, those
	 * are passed by reference, which is handled below.  Here we
	 * only deal with integers, floats, small structs, etc.  */

	size_t a;
	if (s390x(ctx)) {
		assert(sz <= 8);
		a = 8;
	} else {
		/* Note: double is 8 bytes.  */
		assert(sz <= 8);
		a = 4;
	}

	size_t off = sz < a ? a - sz : 0;
	value_in_inferior(valuep, ctx->stack_pointer + off);

	ctx->stack_pointer += sz > a ? sz : a;
	return 0;
}
Example #2
0
int
arch_fetch_retval(struct fetch_context *ctx, enum tof type,
		  struct process *proc, struct arg_type_info *info,
		  struct value *valuep)
{
	if (fetch_register_banks(proc, ctx) < 0)
		return -1;

	if (ctx->hardfp && !ctx->in_varargs) {
		int rc;
		if ((rc = consider_vfp(ctx, proc, info, valuep)) != 1)
			return rc;
	}

	size_t sz = type_sizeof(proc, info);
	assert(sz != (size_t)-1);

	switch (info->type) {
		unsigned char *data;

	case ARGTYPE_VOID:
		return 0;

	case ARGTYPE_FLOAT:
	case ARGTYPE_DOUBLE:
		if (ctx->hardfp && !ctx->in_varargs) {
			unsigned char *data = value_reserve(valuep, sz);
			if (data == NULL)
				return -1;
			memmove(data, &ctx->fpregs, sz);
			return 0;
		}
		goto pass_in_registers;

	case ARGTYPE_ARRAY:
	case ARGTYPE_STRUCT:
		if (sz > 4) {
			value_in_inferior(valuep, ctx->ret_struct);
			return 0;
		}
		/* Fall through.  */

	case ARGTYPE_CHAR:
	case ARGTYPE_SHORT:
	case ARGTYPE_USHORT:
	case ARGTYPE_INT:
	case ARGTYPE_UINT:
	case ARGTYPE_LONG:
	case ARGTYPE_ULONG:
	case ARGTYPE_POINTER:
	pass_in_registers:
		if ((data = value_reserve(valuep, sz)) == NULL)
			return -1;
		memmove(data, ctx->regs.uregs, sz);
		return 0;
	}
	assert(info->type != info->type);
	abort();
}
Example #3
0
int
arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
		    struct process *proc,
		    struct arg_type_info *info, struct value *valuep)
{
	const size_t sz = type_sizeof(proc, info);
	assert(sz != (size_t)-1);

	if (ctx->hardfp && !ctx->in_varargs) {
		int rc;
		if ((rc = consider_vfp(ctx, proc, info, valuep)) != 1)
			return rc;
	}

	/* IHI0042E_aapcs: If the argument requires double-word
	 * alignment (8-byte), the NCRN is rounded up to the next even
	 * register number.  */
	const size_t al = type_alignof(proc, info);
	assert(al != (size_t)-1);
	if (al == 8)
		ctx->ncrn = ((ctx->ncrn + 1) / 2) * 2;

	/* If the size in words of the argument is not more than r4
	 * minus NCRN, the argument is copied into core registers,
	 * starting at the NCRN.  */
	/* If the NCRN is less than r4 and the NSAA is equal to the
	 * SP, the argument is split between core registers and the
	 * stack.  */

	const size_t words = (sz + 3) / 4;
	if (ctx->ncrn < 4 && ctx->nsaa == ctx->sp) {
		unsigned char *data = value_reserve(valuep, words * 4);
		if (data == NULL)
			return -1;
		size_t i;
		for (i = 0; i < words && ctx->ncrn < 4; ++i) {
			memcpy(data, &ctx->regs.uregs[ctx->ncrn++], 4);
			data += 4;
		}
		const size_t rest = (words - i) * 4;
		if (rest > 0) {
			umovebytes(proc, ctx->nsaa, data, rest);
			ctx->nsaa += rest;
		}
		return 0;
	}

	assert(ctx->ncrn == 4);

	/* If the argument required double-word alignment (8-byte),
	 * then the NSAA is rounded up to the next double-word
	 * address.  */
	if (al == 8)
		/* XXX double cast.  */
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 7) / 8) * 8);
	else
		ctx->nsaa = (arch_addr_t)((((uintptr_t)ctx->nsaa + 3) / 4) * 4);

	value_in_inferior(valuep, ctx->nsaa);
	ctx->nsaa += sz;

	return 0;
}