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_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_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 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_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 ktap_lib_pairs(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); ktap_table *t; if (G(ks)->mainthread != ks) { kp_error(ks, "only mainthread can call table pairs\n"); return -1; } if (ttistable(v)) { t = hvalue(v); } else if (ttisaggrtable(v)) { t = kp_aggrtable_synthesis(ks, ahvalue(v)); } else if (isnil(v)) { kp_error(ks, "table is nil in pairs\n"); return 0; } else { kp_error(ks, "wrong argument for pairs\n"); return 0; } setfvalue(ks->top++, ktap_lib_next); sethvalue(ks->top++, t); setnilvalue(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; }
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; }
/** * 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_len(ktap_state *ks) { int len = kp_obj_len(ks, kp_arg(ks, 1)); if (len < 0) return -1; set_number(ks->top, len); incr_top(ks); return 1; }
static int kplib_histogram(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); if (is_table(v)) kp_tab_histogram(ks, hvalue(v)); else if (is_ptable(v)) kp_ptab_histogram(ks, phvalue(v)); return 0; }
static int ktap_lib_len(ktap_state *ks) { int len = kp_objlen(ks, kp_arg(ks, 1)); if (len < 0) return -1; setnvalue(ks->top, len); 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; }
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 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); }
/** * 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 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; }
static int ktap_lib_histogram(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); if (G(ks)->mainthread != ks) { kp_error(ks, "only mainthread can call table historgram\n"); return -1; } if (ttistable(v)) kp_table_histogram(ks, hvalue(v)); else if (ttisaggrtable(v)) kp_aggrtable_histogram(ks, ahvalue(v)); return 0; }
static int ffi_type_check(ktap_state_t *ks, csymbol_func *csf, int idx) { StkId arg; csymbol *cs; if (idx >= csymf_arg_nr(csf)) return 0; arg = kp_arg(ks, idx + 1); cs = csymf_arg(ks, csf, idx); if (!kp_cdata_type_match(ks, cs, arg)) return 0; else { kp_error(ks, "Cannot convert to csymbol %s for arg %d\n", csym_name(cs), idx); 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 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_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 kplib_stringof(ktap_state_t *ks) { ktap_val_t *v = kp_arg(ks, 1); const ktap_str_t *ts = NULL; if (itype(v) == KTAP_TEVENTSTR) { ts = kp_event_stringify(ks); } else if (itype(v) == KTAP_TKIP) { char str[KSYM_SYMBOL_LEN]; SPRINT_SYMBOL(str, nvalue(v)); ts = kp_str_newz(ks, str); } if (unlikely(!ts)) return -1; set_string(ks->top++, ts); return 1; }
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; }