size_t value_size(struct value *val, struct value_dict *arguments) { if (val->size != (size_t)-1) return val->size; if (val->type->type != ARGTYPE_ARRAY) return val->size = type_sizeof(val->inferior, val->type); struct value length; if (expr_eval(val->type->u.array_info.length, val, arguments, &length) < 0) return (size_t)-1; size_t l; int o = value_extract_word(&length, (long *)&l, arguments); value_destroy(&length); if (o < 0) return (size_t)-1; size_t elt_size = type_sizeof(val->inferior, val->type->u.array_info.elt_type); if (elt_size == (size_t)-1) return (size_t)-1; return val->size = elt_size * l; }
void value_set_word(struct value *value, long word) { size_t sz = type_sizeof(value->inferior, value->type); assert(sz != (size_t)-1); assert(sz <= sizeof(value->u.value)); value->where = VAL_LOC_WORD; union word_data u = {}; switch (sz) { case 0: u.l = 0; break; case 1: u.u8 = word; break; case 2: u.u16 = word; break; case 4: u.u32 = word; break; case 8: u.u64 = word; break; default: assert(sz != sz); abort(); } value->u.value = u.l; }
struct fetch_context * arch_fetch_arg_init(enum tof type, struct process *proc, struct arg_type_info *ret_info) { struct fetch_context *context = malloc(sizeof(*context)); { struct process *mainp = proc; while (mainp->libraries == NULL && mainp->parent != NULL) mainp = mainp->parent; context->hardfp = mainp->libraries->arch.hardfp; } if (context == NULL || fetch_register_banks(proc, context) < 0) { free(context); return NULL; } if (ret_info->type == ARGTYPE_STRUCT || ret_info->type == ARGTYPE_ARRAY) { size_t sz = type_sizeof(proc, ret_info); assert(sz != (size_t)-1); if (sz > 4) { /* XXX double cast */ context->ret_struct = (arch_addr_t)context->regs.uregs[0]; context->ncrn++; } } return context; }
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 value_equal(struct value *val1, struct value *val2, struct value_dict *arguments) { size_t sz1 = type_sizeof(val1->inferior, val1->type); size_t sz2 = type_sizeof(val2->inferior, val2->type); if (sz1 == (size_t)-1 || sz2 == (size_t)-1) return -1; if (sz1 != sz2) return 0; unsigned char *data1 = value_get_data(val1, arguments); unsigned char *data2 = value_get_data(val2, arguments); if (data1 == NULL || data2 == NULL) return -1; return memcmp(data1, data2, sz1) == 0 ? 1 : 0; }
int value_extract_buf(struct value *value, unsigned char *tgt, struct value_dict *arguments) { size_t sz = type_sizeof(value->inferior, value->type); if (sz == (size_t)-1) return -1; return value_extract_buf_sz(value, tgt, sz, arguments); }
int arch_fetch_arg_next(struct fetch_context *ctx, enum tof type, struct Process *proc, struct arg_type_info *info, struct value *valuep) { size_t sz = type_sizeof(proc, info); if (sz == (size_t)-1) return -1; switch (info->type) { case ARGTYPE_VOID: value_set_word(valuep, 0); return 0; case ARGTYPE_STRUCT: if (type_get_fp_equivalent(info) != NULL) /* fall through */ case ARGTYPE_FLOAT: case ARGTYPE_DOUBLE: return allocate_fpr(ctx, proc, info, valuep, sz); /* Structures<4 bytes on s390 and structures<8 bytes * on s390x are passed in register. On s390, long * long and structures<8 bytes are passed in two * consecutive registers (if two are available). */ if (sz <= (s390x(ctx) ? 8 : 4)) return allocate_gpr(ctx, proc, info, valuep, sz); else if (sz <= 8) return allocate_gpr_pair(ctx, proc, info, valuep, sz); /* fall through */ case ARGTYPE_ARRAY: if (value_pass_by_reference(valuep) < 0) return -1; /* fall through */ case ARGTYPE_INT: case ARGTYPE_UINT: case ARGTYPE_LONG: case ARGTYPE_ULONG: case ARGTYPE_CHAR: case ARGTYPE_SHORT: case ARGTYPE_USHORT: case ARGTYPE_POINTER: return allocate_gpr(ctx, proc, info, valuep, sz); default: assert(info->type != info->type); abort(); } return -1; }
int value_clone(struct value *retp, const struct value *val) { *retp = *val; if (val->where == VAL_LOC_COPY) { assert(val->inferior != NULL); size_t size = type_sizeof(val->inferior, val->type); if (size == (size_t)-1) return -1; retp->u.address = malloc(size); if (retp->u.address == NULL) return -1; memcpy(retp->u.address, val->u.address, size); } return 0; }
static unsigned int type_sizeof(ir_unit_t *iu, int index) { ir_type_t *it = type_get(iu, index); switch(it->it_code) { case IR_TYPE_VOID: return 0; case IR_TYPE_INT1: case IR_TYPE_INT8: return 1; case IR_TYPE_INT16: return 2; case IR_TYPE_INT32: case IR_TYPE_FLOAT: return 4; case IR_TYPE_INT64: case IR_TYPE_DOUBLE: return 8; case IR_TYPE_INTx: if(it->it_bits <= 32) return 4; if(it->it_bits <= 64) { return 8; } goto bad; case IR_TYPE_POINTER: return 4; case IR_TYPE_STRUCT: return it->it_struct.size; case IR_TYPE_ARRAY: return type_sizeof(iu, it->it_array.element_type) * it->it_array.num_elements; default: bad: parser_error(iu, "Unable to compute size of type %s\n", type_str(iu, it)); } }
int value_is_zero(struct value *val, struct value_dict *arguments) { unsigned char *data = value_get_data(val, arguments); if (data == NULL) return -1; size_t sz = type_sizeof(val->inferior, val->type); if (sz == (size_t)-1) return -1; int zero = 1; size_t j; for (j = 0; j < sz; ++j) { if (data[j] != 0) { zero = 0; break; } } return zero; }
int value_extract_word(struct value *value, long *retp, struct value_dict *arguments) { size_t sz = type_sizeof(value->inferior, value->type); if (sz == (size_t)-1) return -1; assert(sz <= sizeof(value->u.value)); if (sz == 0) { *retp = 0; return 0; } union word_data u = {}; if (value_extract_buf_sz(value, u.buf, sz, arguments) < 0) return -1; switch (sz) { case 1: *retp = (long)u.u8; return 0; case 2: *retp = (long)u.u16; return 0; case 4: *retp = (long)u.u32; return 0; case 8: *retp = (long)u.u64; return 0; default: assert(sz != sz); 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; }
static void types_new_rec_handler(struct ir_unit *iu, int op, unsigned int argc, const ir_arg_t *argv) { ir_type_t it; const char *ctx = "types"; assert(iu->iu_types_created == 0); switch(op) { case TYPE_CODE_NUMENTRY: if(argc < 1) parser_error(iu, "%s: Short NUMENTRY record", ctx); VECTOR_SET_CAPACITY(&iu->iu_types, argv[0].i64); return; case TYPE_CODE_VOID: it.it_code = IR_TYPE_VOID; break; case TYPE_CODE_FLOAT: it.it_code = IR_TYPE_FLOAT; break; case TYPE_CODE_DOUBLE: it.it_code = IR_TYPE_DOUBLE; break; case TYPE_CODE_INTEGER: if(argv[0].i64 == 1) { it.it_code = IR_TYPE_INT1; } else if(argv[0].i64 == 8) { it.it_code = IR_TYPE_INT8; } else if(argv[0].i64 == 16) { it.it_code = IR_TYPE_INT16; } else if(argv[0].i64 == 32) { it.it_code = IR_TYPE_INT32; } else if(argv[0].i64 == 64) { it.it_code = IR_TYPE_INT64; } else if(argv[0].i64 < 64) { it.it_code = IR_TYPE_INTx; it.it_bits = argv[0].i64; } else { parser_error(iu, "%s: Integer width %d bit not supported", ctx, (int)argv[0].i64); } break; case TYPE_CODE_ARRAY: it.it_code = IR_TYPE_ARRAY; it.it_array.num_elements = argv[0].i64; it.it_array.element_type = argv[1].i64; break; case TYPE_CODE_STRUCT_NAME: free(iu->iu_current_struct_name); iu->iu_current_struct_name = read_str_from_argv(argc, argv); return; case TYPE_CODE_STRUCT_NAMED: it.it_struct.name = iu->iu_current_struct_name; iu->iu_current_struct_name = NULL; if(0) case TYPE_CODE_STRUCT_ANON: it.it_struct.name = NULL; it.it_code = IR_TYPE_STRUCT; it.it_struct.num_elements = argc - 1; it.it_struct.elements = malloc(it.it_struct.num_elements * sizeof(it.it_struct.elements[0])); { const int packed = !!argv[0].i64; int offset = 0; int ba = 1; // Biggest alignment for(int i = 0; i < it.it_struct.num_elements; i++) { int t = argv[i + 1].i64; it.it_struct.elements[i].type = t; int s = type_sizeof(iu, t); if(!packed) { int a = type_alignment(iu ,t); offset = VMIR_ALIGN(offset, a); ba = MAX(ba, a); } it.it_struct.elements[i].offset = offset; offset += s; } it.it_struct.size = packed ? offset : VMIR_ALIGN(offset, ba); it.it_struct.alignment = ba; } break; case TYPE_CODE_POINTER: it.it_code = IR_TYPE_POINTER; it.it_pointer.pointee = argv[0].i64; break; case TYPE_CODE_FUNCTION: if(argc < 2) parser_error(iu, "%s: Invalid # of args (%d) for function type", ctx, argc); it.it_code = IR_TYPE_FUNCTION; it.it_function.varargs = argv[0].i64; it.it_function.return_type = argv[1].i64; it.it_function.num_parameters = argc - 2; it.it_function.parameters = malloc(it.it_function.num_parameters * sizeof(int)); for(int i = 0; i < it.it_function.num_parameters; i++) it.it_function.parameters[i] = argv[2 + i].i64; break; case TYPE_CODE_METADATA: it.it_code = IR_TYPE_METADATA; break; case TYPE_CODE_LABEL: it.it_code = IR_TYPE_LABEL; break; case TYPE_CODE_OPAQUE: it.it_code = IR_TYPE_OPAQUE; break; case TYPE_CODE_VECTOR: printf("Vector of %s x %d\n", type_str_index(iu, argv[1].i64), (int)argv[0].i64); // break; default: printargs(argv, argc); parser_error(iu, "%s: Unknown op %d", ctx, op); } VECTOR_PUSH_BACK(&iu->iu_types, it); }