Beispiel #1
0
int cp_ctype_free()
{
	int i;
	csymbol *cs;

	if (cts.stack)
		free(cts.stack);

	if (cs_arr) {
		for (i = 0; i < cs_nr; i++) {
			cs = &cs_arr[i];
			if (csym_type(cs) == FFI_FUNC) {
				if (csym_func(cs)->arg_ids)
					free(csym_func(cs)->arg_ids);
			} else if (csym_type(cs) == FFI_STRUCT) {
				if (csym_struct(cs)->members)
					free(csym_struct(cs)->members);
			}
		}
		free(cs_arr);
	}

	if (cte_arr) {
		free(cte_arr);
	}

	return 0;
}
Beispiel #2
0
Datei: cdata.c Projekt: ktap/ktap
ktap_cdata_t *kp_cdata_new_by_id(ktap_state_t *ks, void *val, csymbol_id id)
{
	csymbol *cs = id_to_csym(ks, id);

	switch (csym_type(cs)) {
	case FFI_VOID:
		kp_error(ks, "Error: Cannot new a void type\n");
		return NULL;
	case FFI_UINT8:
	case FFI_INT8:
	case FFI_UINT16:
	case FFI_INT16:
	case FFI_UINT32:
	case FFI_INT32:
	case FFI_UINT64:
	case FFI_INT64:
		return kp_cdata_new_number(ks, val, id);
	case FFI_PTR:
		return kp_cdata_new_ptr(ks, val, 0, id, 0);
	case FFI_STRUCT:
	case FFI_UNION:
		return kp_cdata_new_record(ks, val, id);
	case FFI_FUNC:
		kp_error(ks, "Error: Cannot new a function type\n");
		return NULL;
	case FFI_UNKNOWN:
	default:
		kp_error(ks, "Error: unknown csymbol type %s\n", csym_name(cs));
		return NULL;
	}
}
Beispiel #3
0
Datei: cdata.c Projekt: ktap/ktap
/* Init its cdata type, but not its actual value */
static void kp_cdata_init(ktap_state_t *ks, ktap_val_t *val, void *addr, int len,
			  csymbol_id id)
{
	ffi_type type = csym_type(id_to_csym(ks, id));

	switch (type) {
	case FFI_PTR:
		set_cdata(val, kp_cdata_new_ptr(ks, addr, len, id, 0));
		break;
	case FFI_STRUCT:
	case FFI_UNION:
		set_cdata(val, kp_cdata_new_record(ks, addr, id));
		break;
	case FFI_UINT8:
	case FFI_INT8:
	case FFI_UINT16:
	case FFI_INT16:
	case FFI_UINT32:
	case FFI_INT32:
	case FFI_UINT64:
	case FFI_INT64:
		/* set all these value into ktap_number(long) */
		set_number(val, 0);
		break;
	default:
		set_cdata(val, kp_cdata_new(ks, id));
		break;
	}
}
Beispiel #4
0
static void init_builtin_type(struct cp_ctype *ct, ffi_type ftype)
{
	csymbol cs;
	int cs_id;

	csym_type(&cs) = ftype;
	strncpy(csym_name(&cs), ffi_type_name(ftype), CSYM_NAME_MAX_LEN);
	cs_id = cp_ctype_reg_csymbol(&cs);

	memset(ct, 0, sizeof(*ct));
	ct->ffi_cs_id = cs_id;
	switch (ftype) {
	case FFI_VOID:		ct_set_type(ct, VOID_TYPE, 0); break;
	case FFI_UINT8:		ct_set_type(ct, INT8_TYPE, 1); break;
	case FFI_INT8:		ct_set_type(ct, INT8_TYPE, 0); break;
	case FFI_UINT16:	ct_set_type(ct, INT16_TYPE, 1); break;
	case FFI_INT16:		ct_set_type(ct, INT16_TYPE, 0); break;
	case FFI_UINT32:	ct_set_type(ct, INT32_TYPE, 1); break;
	case FFI_INT32:		ct_set_type(ct, INT32_TYPE, 0); break;
	case FFI_UINT64:	ct_set_type(ct, INT64_TYPE, 1); break;
	case FFI_INT64:		ct_set_type(ct, INT64_TYPE, 0); break;
	default:		break;
	}
	ct->base_size = ffi_type_size(ftype);
	ct->align_mask = ffi_type_align(ftype) - 1;
	ct->is_defined = 1;
}
Beispiel #5
0
Datei: cdata.c Projekt: 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;
	}
}
Beispiel #6
0
int cp_symbol_build_func(struct cp_ctype *type, const char *fname, int fn_size)
{
	int i = 1, arg_nr, id;
	int *argsym_id_arr;
	csymbol nfcs;
	csymbol_func *fcs;

	if (cts.top == 0 || fn_size < 0 || !fname) {
		cp_error("invalid function definition.\n");
	}

	argsym_id_arr = NULL;
	memset(&nfcs, 0, sizeof(csymbol));
	csym_type(&nfcs) = FFI_FUNC;

	strncpy(csym_name(&nfcs), fname, fn_size);

	fcs = csym_func(&nfcs);
	fcs->has_var_arg = type->has_var_arg;
	/* Type needed for handling variable args handle */
	if (fcs->has_var_arg && !ctype_lookup_type("void *"))
		cp_symbol_build_pointer(ctype_lookup_type("void"));

	/* Fetch start address of function  */
	fcs->addr = (void *)find_kernel_symbol(csym_name(&nfcs));
	if (!fcs->addr)
		cp_error("wrong function address for %s\n", csym_name(&nfcs));

	/* bottom of the stack is return type */
	fcs->ret_id = ct_stack_ct(0)->ffi_cs_id;

	/* the rest is argument type */
	if (cts.top == 1) {
		/* function takes no argument */
		arg_nr = 0;
	} else {
		arg_nr = cts.top - 1;
		argsym_id_arr = malloc(arg_nr * sizeof(int));
		if (!argsym_id_arr)
			cp_error("failed to allocate memory for function args.\n");
		for (i = 0; i < arg_nr; i++) {
			argsym_id_arr[i] = ct_stack_ct(i+1)->ffi_cs_id;
		}
	}
	fcs->arg_nr = arg_nr;
	fcs->arg_ids = argsym_id_arr;

	id = cp_ctype_reg_csymbol(&nfcs);

	/* clear stack since we have consumed all the ctypes */
	ctype_stack_reset();

	return id;
}
Beispiel #7
0
void cp_ctype_dump_stack()
{
	int i;
	struct cp_ctype *ct;

	printf("---------------------------\n");
	printf("start of ctype stack (%d) dump: \n", cts.top);
	for (i = 0; i < cts.top; i++) {
		ct = ct_stack_ct(i);
		printf("[%d] -> cp_ctype: %d, sym_type: %d, pointer: %d "
			"symbol_id: %d, name: %s\n",
			i, ct->type,
			csym_type(ct_ffi_cs(ct)), ct->pointers, ct->ffi_cs_id,
			ct_stack(i)->name);
	}
}
Beispiel #8
0
static int ffi_set_return(ktap_state_t *ks, void *rvalue, csymbol_id ret_id)
{
	ktap_cdata_t *cd;
	ffi_type type = csym_type(id_to_csym(ks, ret_id));

	/* push return value to ktap stack */
	switch (type) {
	case FFI_VOID:
		return 0;
	case FFI_UINT8:
	case FFI_INT8:
	case FFI_UINT16:
	case FFI_INT16:
	case FFI_UINT32:
	case FFI_INT32:
	case FFI_UINT64:
	case FFI_INT64:
		set_number(ks->top, (ktap_number)rvalue);
		break;
	case FFI_PTR:
		cd = kp_cdata_new_ptr(ks, rvalue, -1, ret_id, 0);
		set_cdata(ks->top, cd);
		break;
	case FFI_STRUCT:
	case FFI_UNION:
		cd = kp_cdata_new_record(ks, rvalue, ret_id);
		set_cdata(ks->top, cd);
		break;
	case FFI_FUNC:
	case FFI_UNKNOWN:
		kp_error(ks, "Error: Have not support ffi_type %s\n",
				ffi_type_name(type));
		return 0;
	}
	incr_top(ks);
	return 1;
}
Beispiel #9
0
Datei: cdata.c Projekt: ktap/ktap
/* Notice: Even if the types are matched, there may exist the lost of
 * data in the unpack process due to precision */
int kp_cdata_type_match(ktap_state_t *ks, csymbol *cs, ktap_val_t *val)
{
	ffi_type type;

	type = csym_type(cs);
	if (type == FFI_FUNC)
		goto error;

	switch (ttypenv(val)) {
	case KTAP_TYPE_LIGHTUSERDATA:
		if (type != FFI_PTR) goto error;
		break;
	case KTAP_TYPE_BOOLEAN:
	case KTAP_TYPE_NUMBER:
		if (type != FFI_UINT8 && type != FFI_INT8
		&& type != FFI_UINT16 && type != FFI_INT16
		&& type != FFI_UINT32 && type != FFI_INT32
		&& type != FFI_UINT64 && type != FFI_INT64)
			goto error;
		break;
	case KTAP_TYPE_STRING:
		if (type != FFI_PTR && type != FFI_UINT8 && type != FFI_INT8)
			goto error;
		break;
	case KTAP_TYPE_CDATA:
		if (cs != cd_csym(ks, cdvalue(val)))
			goto error;
		break;
	default:
		goto error;
	}
	return 0;

error:
	return -1;
}
Beispiel #10
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);
}