Пример #1
0
Файл: cdata.c Проект: ktap/ktap
void kp_cdata_ptr_set(ktap_state_t *ks, ktap_cdata_t *cd,
		      ktap_val_t *key, ktap_val_t *val)
{
	ktap_number idx;
	csymbol *cs;
	size_t size;
	char *addr;

	if (!is_number(key)) {
		kp_error(ks, "array index should be number\n");
		return;
	}
	idx = nvalue(key);
	if (unlikely(idx < 0 || (cd_ptr_nmemb(cd) >= 0
					&& idx >= cd_ptr_nmemb(cd)))) {
		kp_error(ks, "array index out of bound\n");
		return;
	}

	cs = csym_ptr_deref(ks, cd_csym(ks, cd));
	if (kp_cdata_type_match(ks, cs, val)) {
		kp_error(ks, "array member should be %s type\n", csym_name(cs));
		return;
	}
	size = csym_size(ks, cs);
	addr = cd_ptr(cd);
	addr += size * idx;
	kp_cdata_unpack(ks, addr, cs, val);
}
Пример #2
0
Файл: cdata.c Проект: ktap/ktap
void kp_cdata_ptr_get(ktap_state_t *ks, ktap_cdata_t *cd,
		      ktap_val_t *key, ktap_val_t *val)
{
	ktap_number idx;
	csymbol *cs;
	size_t size;
	char *addr;
	csymbol_id cs_id;

	if (!is_number(key)) {
		kp_error(ks, "array index should be number\n");
		return;
	}
	idx = nvalue(key);
	if (unlikely(idx < 0 || (cd_ptr_nmemb(cd) >= 0
					&& idx >= cd_ptr_nmemb(cd)))) {
		kp_error(ks, "array index out of bound\n");
		return;
	}

	cs_id = csym_ptr_deref_id(cd_csym(ks, cd));
	cs = id_to_csym(ks, cs_id);
	size = csym_size(ks, cs);
	addr = cd_ptr(cd);
	addr += size * idx;

	kp_cdata_init(ks, val, addr, -1, cs_id);
	kp_cdata_pack(ks, val, addr, cs);
}
Пример #3
0
Файл: cdata.c Проект: ktap/ktap
static void kp_cdata_value(ktap_state_t *ks, ktap_val_t *val, void **out_addr,
			   size_t *out_size, void **temp)
{
	ktap_cdata_t *cd;
	csymbol *cs;
	ffi_type type;

	switch (ttypenv(val)) {
	case KTAP_TYPE_BOOLEAN:
		*out_addr = &bvalue(val);
		*out_size = sizeof(int);
		return;
	case KTAP_TYPE_LIGHTUSERDATA:
		*out_addr = pvalue(val);
		*out_size = sizeof(void *);
		return;
	case KTAP_TYPE_NUMBER:
		*out_addr = &nvalue(val);
		*out_size = sizeof(ktap_number);
		return;
	case KTAP_TYPE_STRING:
		*temp = (void *)svalue(val);
		*out_addr = temp;
		*out_size = sizeof(void *);
		return;
	}

	cd = cdvalue(val);
	cs = cd_csym(ks, cd);
	type = csym_type(cs);
	*out_size = csym_size(ks, cs);
	switch (type) {
	case FFI_VOID:
		kp_error(ks, "Error: Cannot copy data from void type\n");
		return;
	case FFI_UINT8:
	case FFI_INT8:
	case FFI_UINT16:
	case FFI_INT16:
	case FFI_UINT32:
	case FFI_INT32:
	case FFI_UINT64:
	case FFI_INT64:
		*out_addr = &cd_int(cd);
		return;
	case FFI_PTR:
		*out_addr = &cd_ptr(cd);
		return;
	case FFI_STRUCT:
	case FFI_UNION:
		*out_addr = cd_record(cd);
		return;
	case FFI_FUNC:
	case FFI_UNKNOWN:
		kp_error(ks, "Error: internal error for csymbol %s\n",
				csym_name(cs));
		return;
	}
}
Пример #4
0
Файл: cdata.c Проект: ktap/ktap
/* Check whether or not type is matched before packing */
void kp_cdata_pack(ktap_state_t *ks, ktap_val_t *val, char *src, csymbol *cs)
{
	size_t size = csym_size(ks, cs), val_size;
	void *val_addr, *temp;

	kp_cdata_value(ks, val, &val_addr, &val_size, &temp);
	if (size > val_size)
		size = val_size;
	memmove(val_addr, src, size);
	memset(val_addr + size, 0, val_size - size);
}
Пример #5
0
Файл: cdata.c Проект: ktap/ktap
/* Check whether or not type is matched before unpacking */
void kp_cdata_unpack(ktap_state_t *ks, char *dst, csymbol *cs, ktap_val_t *val)
{
	size_t size = csym_size(ks, cs), val_size;
	void *val_addr, *temp;

	kp_cdata_value(ks, val, &val_addr, &val_size, &temp);
	if (val_size > size)
		val_size = size;
	memmove(dst, val_addr, val_size);
	memset(dst + val_size, 0, size - val_size);
}
Пример #6
0
static void ffi_unpack(ktap_state_t *ks, char *dst, csymbol_func *csf,
		int idx, int align)
{
	StkId arg = kp_arg(ks, idx + 1);
	csymbol *cs = ffi_get_arg_csym(ks, csf, idx);
	size_t size = csym_size(ks, cs);

	/* initialize the destination section */
	memset(dst, 0, ALIGN(size, align));

	kp_cdata_unpack(ks, dst, cs, arg);
}
Пример #7
0
Файл: cdata.c Проект: ktap/ktap
ktap_cdata_t *kp_cdata_new_record(ktap_state_t *ks, void *val, csymbol_id id)
{
	ktap_cdata_t *cd;
	size_t size;

	cd = kp_cdata_new(ks, id);

	/* if val == NULL, allocate new empty space */
	if (val == NULL) {
		size = csym_size(ks, id_to_csym(ks, id));
		cd_record(cd) = kp_rawobj_alloc(ks, size);
	} else
		cd_record(cd) = val;

	return cd;
}
Пример #8
0
Файл: cdata.c Проект: ktap/ktap
/* argument nmemb here indicates the length of array that is pointed to,
 * -1 for unknown */
ktap_cdata_t *kp_cdata_new_ptr(ktap_state_t *ks, void *addr,
			     int nmemb, csymbol_id id, int to_allocate)
{
	ktap_cdata_t *cd;
	size_t memb_size;
	csymbol_id deref_id;

	cd = kp_cdata_new(ks, id);

	if (to_allocate) {
		/* allocate new empty space */
		deref_id = csym_ptr_deref_id(id_to_csym(ks, id));
		memb_size = csym_size(ks, id_to_csym(ks, deref_id));
		cd_ptr(cd) = kp_rawobj_alloc(ks, memb_size * nmemb);
	} else {
		cd_ptr(cd) = addr;
	}

	cd_ptr_nmemb(cd) = nmemb;

	return cd;
}
Пример #9
0
static void ffi_call_x86_64(ktap_state_t *ks, csymbol_func *csf, void *rvalue)
{
	int i;
	int gpr_nr;
	int arg_bytes; /* total bytes needed for exceeded args in stack */
	int mem_bytes; /* total bytes needed for memory storage */
	char *stack, *stack_p, *gpr_p, *arg_p, *mem_p, *tmp_p;
	int arg_nr;
	csymbol *rsym;
	ffi_type rtype;
	size_t rsize;
	bool ret_in_memory;
	/* New stack to call C function */
	char space[NEWSTACK_SIZE];

	arg_nr = kp_arg_nr(ks);
	rsym = csymf_ret(ks, csf);
	rtype = csym_type(rsym);
	rsize = csym_size(ks, rsym);
	ret_in_memory = false;
	if (rtype == FFI_STRUCT || rtype == FFI_UNION) {
		if (rsize > 16) {
			rvalue = kp_malloc(ks, rsize);
			rtype = FFI_VOID;
			ret_in_memory = true;
		} else {
			/* much easier to always copy 16 bytes from registers */
			rvalue = kp_malloc(ks, 16);
		}
	}

	gpr_nr = 0;
	arg_bytes = mem_bytes = 0;
	if (ret_in_memory)
		gpr_nr++;
	/* calculate bytes needed for stack */
	for (i = 0; i < arg_nr; i++) {
		csymbol *cs = ffi_get_arg_csym(ks, csf, i);
		size_t size = csym_size(ks, cs);
		size_t align = csym_align(ks, cs);
		enum arg_status st = IN_REGISTER;
		int n_gpr_nr = 0;
		if (size > 32) {
			st = IN_MEMORY;
			n_gpr_nr = 1;
		} else if (size > 16)
			st = IN_STACK;
		else
			n_gpr_nr = ALIGN(size, GPR_SIZE) / GPR_SIZE;

		if (gpr_nr + n_gpr_nr > MAX_GPR) {
			if (st == IN_MEMORY)
				arg_bytes += GPR_SIZE;
			else
				st = IN_STACK;
		} else
			gpr_nr += n_gpr_nr;
		if (st == IN_STACK) {
			arg_bytes = ALIGN(arg_bytes, align);
			arg_bytes += size;
			arg_bytes = ALIGN(arg_bytes, STACK_ALIGNMENT);
		}
		if (st == IN_MEMORY) {
			mem_bytes = ALIGN(mem_bytes, align);
			mem_bytes += size;
			mem_bytes = ALIGN(mem_bytes, STACK_ALIGNMENT);
		}
	}

	/* apply space to fake stack for C function call */
	if (16 + REDZONE_SIZE + MAX_GPR_SIZE + arg_bytes +
			mem_bytes + 6 * 8 >= NEWSTACK_SIZE) {
		kp_error(ks, "Unable to handle that many arguments by now\n");
		return;
	}
	stack = space;
	/* 128 bytes below %rsp is red zone */
	/* stack should be 16-bytes aligned */
	stack_p = ALIGN_STACK(stack + REDZONE_SIZE, 16);
	/* save general purpose registers here */
	gpr_p = stack_p;
	memset(gpr_p, 0, MAX_GPR_SIZE);
	/* save arguments in stack here */
	arg_p = gpr_p + MAX_GPR_SIZE;
	/* save arguments in memory here */
	mem_p = arg_p + arg_bytes;
	/* set additional space as temporary space */
	tmp_p = mem_p + mem_bytes;

	/* copy arguments here */
	gpr_nr = 0;
	if (ret_in_memory) {
		memcpy(gpr_p, &rvalue, GPR_SIZE);
		gpr_p += GPR_SIZE;
		gpr_nr++;
	}
	for (i = 0; i < arg_nr; i++) {
		csymbol *cs = ffi_get_arg_csym(ks, csf, i);
		size_t size = csym_size(ks, cs);
		size_t align = csym_align(ks, cs);
		enum arg_status st = IN_REGISTER;
		int n_gpr_nr = 0;
		if (size > 32) {
			st = IN_MEMORY;
			n_gpr_nr = 1;
		} else if (size > 16)
			st = IN_STACK;
		else
			n_gpr_nr = ALIGN(size, GPR_SIZE) / GPR_SIZE;

		if (st == IN_MEMORY)
			mem_p = ALIGN_STACK(mem_p, align);
		/* Tricky way about storing it above mem_p. It won't overflow
		 * because temp region can be temporarily used if necesseary. */
		ffi_unpack(ks, mem_p, csf, i, GPR_SIZE);
		if (gpr_nr + n_gpr_nr > MAX_GPR) {
			if (st == IN_MEMORY) {
				memcpy(arg_p, &mem_p, GPR_SIZE);
				arg_p += GPR_SIZE;
			} else
				st = IN_STACK;
		} else {
			memcpy(gpr_p, mem_p, n_gpr_nr * GPR_SIZE);
			gpr_p += n_gpr_nr * GPR_SIZE;
			gpr_nr += n_gpr_nr;
		}
		if (st == IN_STACK) {
			arg_p = ALIGN_STACK(arg_p, align);
			memcpy(arg_p, mem_p, size);
			arg_p += size;
			arg_p = ALIGN_STACK(arg_p, STACK_ALIGNMENT);
		}
		if (st == IN_MEMORY) {
			mem_p += size;
			mem_p = ALIGN_STACK(mem_p, STACK_ALIGNMENT);
		}
	}

	kp_verbose_printf(ks, "Stack location: %p -redzone- %p -general purpose "
			"register used- %p -zero- %p -stack for argument- %p"
			" -memory for argument- %p -temp stack-\n",
			stack, stack_p, gpr_p, stack_p + MAX_GPR_SIZE,
			arg_p, mem_p);
	kp_verbose_printf(ks, "GPR number: %d; arg in stack: %d; "
			"arg in mem: %d\n",
			gpr_nr, arg_bytes, mem_bytes);
	kp_verbose_printf(ks, "Return: address %p type %d\n", rvalue, rtype);
	kp_verbose_printf(ks, "Number of register used: %d\n", gpr_nr);
	kp_verbose_printf(ks, "Start FFI call on %p\n", csf->addr);
	ffi_call_assem_x86_64(stack_p, tmp_p, csf->addr, rvalue, rtype);
}