Beispiel #1
0
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;
}
Beispiel #2
0
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();
}
Beispiel #5
0
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;
}
Beispiel #6
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);
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}
Beispiel #9
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));
  }
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #13
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);
}