Exemplo n.º 1
0
static int kplib_table_new(ktap_state *ks)
{
	ktap_tab *h;
	int narr = 0, nrec = 0;

	if (kp_arg_nr(ks) >= 1) {
		kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
		narr = nvalue(kp_arg(ks, 1));
	}

	if (kp_arg_nr(ks) >= 2) {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		nrec = nvalue(kp_arg(ks, 2));
	}

	h = kp_tab_new(ks, narr, nrec);
	if (!h) {
		set_nil(ks->top);
	} else {
		set_table(ks->top, h);
	}

	incr_top(ks);
	return 1;
}
Exemplo n.º 2
0
static int kplib_ffi_new(ktap_state *ks)
{
	int n = kp_arg_nr(ks), array_size;
	csymbol_id cs_id;
	ktap_cdata *cd;

	if (unlikely(n != 2)) {
		/* this is not likely to happen since ffi.new arguments are
		 * generated by compiler */
		set_nil(ks->top++);
		kp_error(ks, "wrong number of arguments\n");
		return 1;
	}

	kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
	kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);

	cs_id = nvalue(kp_arg(ks, 1));
	array_size = nvalue(kp_arg(ks, 2));

	if (unlikely(cs_id > max_csym_id(ks)))
		kp_error(ks, "invalid csymbol id\n");

	kp_verbose_printf(ks, "ffi.new symbol %s with length %d\n",
			id_to_csym(ks, cs_id)->name, array_size);

	cd = kp_cdata_new_ptr(ks, NULL, array_size, cs_id, 1);
	set_cdata(ks->top, cd);
	incr_top(ks);

	return 1;
}
Exemplo n.º 3
0
static int kplib_sort_pairs(ktap_state *ks)
{
	ktap_value *v = kp_arg(ks, 1);
	ktap_closure *cmp_func = NULL;
	ktap_tab *t;

	if (is_table(v)) {
		t = hvalue(v);
	} else if (is_ptable(v)) {
		t = kp_ptab_synthesis(ks, phvalue(v));
	} else if (is_nil(v)) {
		kp_error(ks, "table is nil in pairs\n");
		return 0;
	} else {
		kp_error(ks, "wrong argument for pairs\n");
		return 0;
	}

	if (kp_arg_nr(ks) > 1) {
		kp_arg_check(ks, 2, KTAP_TYPE_FUNCTION);
		cmp_func = clvalue(kp_arg(ks, 2));
	}

	kp_tab_sort(ks, t, cmp_func); 
	set_cfunction(ks->top++, table_sort_iter_next);
	set_table(ks->top++, t);
	set_nil(ks->top++);
	return 3;
}
Exemplo n.º 4
0
static int kplib_backtrace(ktap_state *ks)
{
	struct stack_trace trace;
	int skip = 10, max_entries = 10;
	int n = kp_arg_nr(ks);
	ktap_btrace *bt;

	if (n >= 1) {
		kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
		skip = nvalue(kp_arg(ks, 1));
	}
	if (n >= 2) {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		max_entries = nvalue(kp_arg(ks, 2));
		max_entries = min(max_entries, KTAP_MAX_STACK_ENTRIES);
	}

	bt = kp_percpu_data(ks, KTAP_PERCPU_DATA_BTRACE);

	trace.nr_entries = 0;
	trace.skip = skip;
	trace.max_entries = max_entries;
	trace.entries = (unsigned long *)(bt + 1);
	save_stack_trace(&trace);

	bt->nr_entries = trace.nr_entries;
	set_btrace(ks->top, bt);
	incr_top(ks);
	return 1;
}
Exemplo n.º 5
0
Arquivo: lib_ffi.c Projeto: cofyc/ktap
static int kplib_ffi_cast(ktap_state *ks)
{
	int n = kp_arg_nr(ks);
	unsigned long addr;
	csymbol_id cs_id;
	ktap_cdata *cd;

	if (unlikely(n != 2)) {
		/* this is not likely to happen since ffi.cast arguments are
		 * generated by compiler */
		set_nil(ks->top++);
		kp_error(ks, "wrong number of arguments\n");
		return 1;
	}

	kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
	kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);

	cs_id = nvalue(kp_arg(ks, 1));
	addr = nvalue(kp_arg(ks, 2));

	if (unlikely(cs_id > max_csym_id(ks)))
		kp_error(ks, "invalid csymbol id\n");

	cd = kp_cdata_new_record(ks, (void *)addr, cs_id);
	set_cdata(ks->top, cd);
	incr_top(ks);
	return 1;
}
Exemplo n.º 6
0
Arquivo: lib_ffi.c Projeto: ktap/ktap
static int kplib_ffi_new(ktap_state_t *ks)
{
	int n = kp_arg_nr(ks);
	csymbol_id cs_id = kp_arg_checknumber(ks, 1);
	int array_size = kp_arg_checknumber(ks, 2);
	int is_array = kp_arg_checknumber(ks, 3);
	ktap_cdata_t *cd;

	if (unlikely(n != 3)) {
		/* this is not likely to happen since ffi.new arguments are
		 * generated by compiler */
		set_nil(ks->top++);
		kp_error(ks, "wrong number of arguments\n");
		return 1;
	}

	if (unlikely(cs_id > max_csym_id(ks)))
		kp_error(ks, "invalid csymbol id\n");

	kp_verbose_printf(ks, "ffi.new symbol %s with length %d\n",
			id_to_csym(ks, cs_id)->name, array_size);

	if (is_array)
		cd = kp_cdata_new_ptr(ks, NULL, array_size, cs_id, 1);
	else
		cd = kp_cdata_new_by_id(ks, NULL, cs_id);
	set_cdata(ks->top, cd);
	incr_top(ks);

	return 1;
}
Exemplo n.º 7
0
static int kplib_ptable(ktap_state *ks)
{
	ktap_ptab *ph;
	int narr = 0, nrec = 0;

	if (kp_arg_nr(ks) >= 1) {
		kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
		narr = nvalue(kp_arg(ks, 1));
	}

	if (kp_arg_nr(ks) >= 2) {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		nrec = nvalue(kp_arg(ks, 2));
	}

	ph = kp_ptab_new(ks, narr, nrec);
	set_ptable(ks->top, ph);
	incr_top(ks);
	return 1;
}
Exemplo n.º 8
0
static int kplib_print(ktap_state_t *ks)
{
	int i;
	int n = kp_arg_nr(ks);

	for (i = 1; i <= n; i++) {
		ktap_val_t *arg = kp_arg(ks, i);
		if (i > 1)
			kp_puts(ks, "\t");
		kp_obj_show(ks, arg);
	}

	kp_puts(ks, "\n");
	return 0;
}
Exemplo n.º 9
0
static int kplib_print_backtrace(ktap_state *ks)
{
	int skip = 10, max_entries = 10;
	int n = kp_arg_nr(ks);

	if (n >= 1) {
		kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);
		skip = nvalue(kp_arg(ks, 1));
	}
	if (n >= 2) {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		max_entries = nvalue(kp_arg(ks, 2));
		max_entries = min(max_entries, KTAP_MAX_STACK_ENTRIES);
	}

	kp_transport_print_backtrace(ks, skip, max_entries);
	return 0;
}
Exemplo n.º 10
0
static int ktap_lib_table_count(ktap_state *ks)
{
	ktap_table *tbl;
	ktap_value *k = kp_arg(ks, 2);
	int n;

	kp_arg_check(ks, 1, KTAP_TTABLE);

	tbl = hvalue(kp_arg(ks, 1));

	if (kp_arg_nr(ks) > 2)
		n = nvalue(kp_arg(ks, 3));
	else
		n = 1;

	kp_table_atomic_inc(ks, tbl, k, n);

	return 0;
}
Exemplo n.º 11
0
/*
 * use gdb to get field offset of struct task_struct, for example:
 *
 * gdb vmlinux
 * (gdb)p &(((struct task_struct *)0).prio)
 */
static int kplib_curr_taskinfo(ktap_state *ks)
{
	int offset;
	int fetch_bytes;

	kp_arg_check(ks, 1, KTAP_TYPE_NUMBER);

	offset = nvalue(kp_arg(ks, 1));
	
	if (kp_arg_nr(ks) == 1)
		fetch_bytes = 4; /* default fetch 4 bytes*/
	else {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		fetch_bytes = nvalue(kp_arg(ks, 2));
	}

	if (offset >= sizeof(struct task_struct)) {
		set_nil(ks->top++);
		kp_error(ks, "access out of bound value of task_struct\n");
		return 1;
	}

#define RET_VALUE ((unsigned long)current + offset)

	switch (fetch_bytes) {
	case 4:
		set_number(ks->top, *(unsigned int *)RET_VALUE);
		break;
	case 8:
		set_number(ks->top, *(unsigned long *)RET_VALUE);
		break;
	default:
		kp_error(ks, "unsupported fetch bytes in curr_task_info\n");
		set_nil(ks->top);
		break;
	}

#undef RET_VALUE

	incr_top(ks);
	return 1;
}
Exemplo n.º 12
0
static int kplib_histogram(ktap_state *ks)
{
	ktap_value *v = kp_arg(ks, 1);
	int n = HISTOGRAM_DEFAULT_TOP_NUM;

	if (kp_arg_nr(ks) >= 2) {
		kp_arg_check(ks, 2, KTAP_TYPE_NUMBER);
		n = nvalue(kp_arg(ks, 2));
		if (n > 1000)
			n = 1000;
	}

	n = max(n, HISTOGRAM_DEFAULT_TOP_NUM);

	if (is_table(v))
		kp_tab_histogram(ks, hvalue(v), n);
	else if (is_ptable(v))
		kp_ptab_histogram(ks, phvalue(v), n);

	return 0;
}
Exemplo n.º 13
0
static int kplib_ffi_free(ktap_state *ks)
{
	int n = kp_arg_nr(ks);
	ktap_cdata *cd;

	if (n != 1) {
		set_nil(ks->top++);
		kp_error(ks, "wrong number of arguments\n");
		return 1;
	}

	kp_arg_check(ks, 1, KTAP_TYPE_CDATA);

	cd = cdvalue(kp_arg(ks, 1));

	if (cd_type(ks, cd) != FFI_PTR)
		kp_error(ks, "could free pointer cdata only\n");

	kp_cdata_free_ptr(ks, cd);

	return 0;
}
Exemplo n.º 14
0
/*
 * Call C into function
 * First argument should be function symbol address, argument types
 * and return type.
 * Left arguments should be arguments for calling the C function.
 * Types between Ktap and C are converted automatically.
 * Only support x86_64 function call by now
 */
int ffi_call(ktap_state_t *ks, csymbol_func *csf)
{
	int i;
	int expected_arg_nr, arg_nr;
	ktap_closure_t *cl;
	void *rvalue;

	expected_arg_nr = csymf_arg_nr(csf);
	arg_nr = kp_arg_nr(ks);

	/* check stack status for C call */
	if (!csf->has_var_arg && expected_arg_nr != arg_nr) {
		kp_error(ks, "wrong argument number %d, which should be %d\n",
				arg_nr, expected_arg_nr);
		goto out;
	}
	if (csf->has_var_arg && expected_arg_nr > arg_nr) {
		kp_error(ks, "argument number %d, which should be bigger than %d\n",
				arg_nr, expected_arg_nr);
		goto out;
	}

	/* maybe useful later, leave it here first */
	cl = clvalue(kp_arg(ks, arg_nr + 1));

	/* check the argument types */
	for (i = 0; i < arg_nr; i++) {
		if (ffi_type_check(ks, csf, i) < 0)
			goto out;
	}

	/* platform-specific calling workflow */
	ffi_call_arch(ks, csf, &rvalue);
	kp_verbose_printf(ks, "Finish FFI call\n");

out:
	return ffi_set_return(ks, rvalue, csymf_ret_id(csf));
}
Exemplo n.º 15
0
int kp_strfmt(ktap_state *ks, struct trace_seq *seq)
{
	int arg = 1;
	size_t sfl;
	ktap_value *arg_fmt = kp_arg(ks, 1);
	int argnum = kp_arg_nr(ks);
	const char *strfrmt, *strfrmt_end;

	strfrmt = svalue(arg_fmt);
	sfl = rawtsvalue(arg_fmt)->tsv.len;
	strfrmt_end = strfrmt + sfl;

	while (strfrmt < strfrmt_end) {
		if (*strfrmt != L_ESC)
			trace_seq_putc(seq, *strfrmt++);
		else if (*++strfrmt == L_ESC)
			trace_seq_putc(seq, *strfrmt++);
		else { /* format item */
			char form[MAX_FORMAT];

			if (++arg > argnum) {
				ktap_argerror(ks, arg, "no value");
				return -1;
			}

			strfrmt = scanformat(ks, strfrmt, form);
			switch (*strfrmt++) {
			case 'c':
				trace_seq_printf(seq, form,
						 nvalue(kp_arg(ks, arg)));
				break;
			case 'd':  case 'i': {
				ktap_number n = nvalue(kp_arg(ks, arg));
				INTFRM_T ni = (INTFRM_T)n;
				addlenmod(form, INTFRMLEN);
				trace_seq_printf(seq, form, ni);
				break;
			}
			case 'p': {
				char str[KSYM_SYMBOL_LEN];
				SPRINT_SYMBOL(str, nvalue(kp_arg(ks, arg)));
				trace_seq_puts(seq, str);
				break;
			}
			case 'o':  case 'u':  case 'x':  case 'X': {
				ktap_number n = nvalue(kp_arg(ks, arg));
				unsigned INTFRM_T ni = (unsigned INTFRM_T)n;
				addlenmod(form, INTFRMLEN);
				trace_seq_printf(seq, form, ni);
				break;
			}
			case 's': {
				ktap_value *v = kp_arg(ks, arg);
				const char *s;
				size_t l;

				if (isnil(v)) {
					trace_seq_puts(seq, "nil");
					return 0;
				}

				if (ttisevent(v)) {
					kp_event_tostring(ks, seq);
					return 0;
				}

				s = svalue(v);
				l = rawtsvalue(v)->tsv.len;
				if (!strchr(form, '.') && l >= 100) {
					/*
					 * no precision and string is too long
					 * to be formatted;
					 * keep original string
					 */
					trace_seq_puts(seq, s);
					break;
				} else {
					trace_seq_printf(seq, form, s);
					break;
				}
			}
			default: /* also treat cases `pnLlh' */
				kp_error(ks, "invalid option " KTAP_QL("%%%c")
					     " to " KTAP_QL("format"),
					     *(strfrmt - 1));
			}
		}
	}

	return 0;
}
Exemplo n.º 16
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);
}