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; }
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(); }
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; }