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; }
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; }
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; }
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; }
/** * function ansi.set_color2 - Set the ansi Select Graphic Rendition mode. * @fg: Foreground color to set. * @bg: Background color to set. * * Description: Sends ansi code for Select Graphic Rendition mode for the * given forground color, Black (30), Blue (34), Green (32), Cyan (36), * Red (31), Purple (35), Brown (33), Light Gray (37) and the given * background color, Black (40), Red (41), Green (42), Yellow (43), * Blue (44), Magenta (45), Cyan (46), White (47). */ static int ktap_lib_set_color2(ktap_state *ks) { int fg, bg; kp_arg_check(ks, 1, KTAP_TNUMBER); kp_arg_check(ks, 2, KTAP_TNUMBER); fg = nvalue(kp_arg(ks, 1)); bg = nvalue(kp_arg(ks, 2)); kp_printf(ks, "\033[%d;%dm", fg, bg); return 0; }
static int kplib_delete(ktap_state *ks) { kp_arg_check(ks, 1, KTAP_TYPE_TABLE); kp_tab_clear(ks, hvalue(kp_arg(ks, 1))); return 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; }
static int ktap_lib_aggr_avg(ktap_state *ks) { kp_arg_check(ks, 1, KTAP_TNUMBER); ks->aggr_accval = nvalue(kp_arg(ks, 1)); setaggrvalue(ks->top, AGGREGATION_TYPE_AVG); incr_top(ks); return 1; }
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; }
static int kplib_pairs(ktap_state_t *ks) { kp_arg_check(ks, 1, KTAP_TTAB); set_cfunc(ks->top++, (ktap_cfunction)kp_tab_next); set_table(ks->top++, hvalue(kp_arg(ks, 1))); set_nil(ks->top++); return 3; }
/** * function ansi.set_color3 - Set the ansi Select Graphic Rendition mode. * @fg: Foreground color to set. * @bg: Background color to set. * @attr: Color attribute to set. * * Description: Sends ansi code for Select Graphic Rendition mode for the * given forground color, Black (30), Blue (34), Green (32), Cyan (36), * Red (31), Purple (35), Brown (33), Light Gray (37), the given * background color, Black (40), Red (41), Green (42), Yellow (43), * Blue (44), Magenta (45), Cyan (46), White (47) and the color attribute * All attributes off (0), Intensity Bold (1), Underline Single (4), * Blink Slow (5), Blink Rapid (6), Image Negative (7). */ static int ktap_lib_set_color3(ktap_state *ks) { int fg, bg, attr; kp_arg_check(ks, 1, KTAP_TNUMBER); kp_arg_check(ks, 2, KTAP_TNUMBER); kp_arg_check(ks, 3, KTAP_TNUMBER); fg = nvalue(kp_arg(ks, 1)); bg = nvalue(kp_arg(ks, 2)); attr = nvalue(kp_arg(ks, 3)); if (attr) kp_printf(ks, "\033[%d;%d;%dm", fg, bg, attr); else kp_printf(ks, "\033[%d;%dm", fg, bg); return 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; }
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; }
/** * Returns a string representation for an IP address */ static int kplib_format_ip_addr(ktap_state *ks) { char ipstr[32]; __be32 ip; kp_arg_check(ks, 1, KTAP_TYPE_NUMBER); ip = (__be32)nvalue(kp_arg(ks, 1)); snprintf(ipstr, 32, "%pI4", &ip); set_string(ks->top, kp_str_new(ks, ipstr)); incr_top(ks); return 1; }
static int kplib_print_hist(ktap_state_t *ks) { int n ; kp_arg_check(ks, 1, KTAP_TTAB); n = kp_arg_checkoptnumber(ks, 2, HISTOGRAM_DEFAULT_TOP_NUM); n = min(n, 1000); n = max(n, HISTOGRAM_DEFAULT_TOP_NUM); kp_tab_print_hist(ks, hvalue(kp_arg(ks, 1)), n); return 0; }
static int ktap_lib_min(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); ktap_stat_data *sd; if (is_nil(v)) { set_number(ks->top, 0); incr_top(ks); return 1; } kp_arg_check(ks, 1, KTAP_TSTATDATA); sd = sdvalue(v); set_number(ks->top, sd->min); incr_top(ks); return 1; }
static int kplib_avg(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); ktap_stat_data *sd; if (is_nil(v)) { set_number(ks->top, 0); incr_top(ks); return 1; } kp_arg_check(ks, 1, KTAP_TYPE_STATDATA); sd = sdvalue(v); set_number(ks->top, sd->sum / sd->count); incr_top(ks); return 1; }
static int kplib_kernel_string(ktap_state *ks) { unsigned long addr; char str[256] = {0}; char *ret; kp_arg_check(ks, 1, KTAP_TYPE_NUMBER); addr = nvalue(kp_arg(ks, 1)); ret = strncpy((void *)str, (const void *)addr, 256); (void) &ret; /* Silence compiler warning. */ str[255] = '\0'; set_string(ks->top, kp_str_new_local(ks, str)); incr_top(ks); return 1; }
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; }
static int kplib_user_string(ktap_state *ks) { unsigned long addr; char str[256] = {0}; int ret; kp_arg_check(ks, 1, KTAP_TYPE_NUMBER); addr = nvalue(kp_arg(ks, 1)); pagefault_disable(); ret = __copy_from_user_inatomic((void *)str, (const void *)addr, 256); (void) &ret; /* Silence compiler warning. */ pagefault_enable(); str[255] = '\0'; set_string(ks->top, kp_str_new(ks, str)); incr_top(ks); return 1; }
/** * Return the source IP address for a given sock */ static int kplib_ip_sock_saddr(ktap_state *ks) { struct inet_sock *isk; int family; kp_arg_check(ks, 1, KTAP_TYPE_NUMBER); /* need to validate the address firstly */ isk = (struct inet_sock *)nvalue(kp_arg(ks, 1)); family = isk->sk.__sk_common.skc_family; if (family == AF_INET) { set_number(ks->top, isk->inet_rcv_saddr); } else { kp_error(ks, "ip_sock_saddr only support ipv4 now\n"); set_nil(ks->top); } incr_top(ks); return 1; }
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; }
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; }
static int kplib_delete(ktap_state_t *ks) { kp_arg_check(ks, 1, KTAP_TTAB); kp_tab_clear(hvalue(kp_arg(ks, 1))); return 0; }