/* * 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_t *ks) { int offset = kp_arg_checknumber(ks, 1); int fetch_bytes = kp_arg_checkoptnumber(ks, 2, 4); /* fetch 4 bytes */ 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 load_constants(struct load_state *S, ktap_proto *f) { int i,n; n = READ_INT(S); f->sizek = n; f->k = NEW_VECTOR(S, n * sizeof(ktap_value)); for (i = 0; i < n; i++) set_nil(&f->k[i]); for (i=0; i < n; i++) { ktap_value *o = &f->k[i]; int t = READ_CHAR(S); switch (t) { case KTAP_TNIL: set_nil(o); break; case KTAP_TBOOLEAN: set_boolean(o, READ_CHAR(S)); break; case KTAP_TNUMBER: /* * todo: kernel not support fp, check double when * loading */ set_number(o, READ_NUMBER(S)); break; case KTAP_TSTRING: set_string(o, READ_STRING(S)); break; default: kp_error(S->ks, "ktap: load_constants: " "unknow ktap_value\n"); return -1; } } n = READ_INT(S); f->p = NEW_VECTOR(S, n * sizeof(ktap_proto)); f->sizep = n; for (i = 0; i < n; i++) f->p[i] = NULL; for (i = 0; i < n; i++) { f->p[i] = kp_newproto(S->ks); if (load_function(S, f->p[i])) return -1; } return 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; }
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_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; }
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; }
ktap_upval *kp_obj_newupval(ktap_state *ks) { ktap_upval *uv; uv = &kp_obj_newobject(ks, KTAP_TYPE_UPVAL, sizeof(ktap_upval), NULL)->uv; uv->v = &uv->u.value; set_nil(uv->v); return uv; }
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; }
ktap_tab_t *kp_tab_new(void) { int hsize, i; ktap_tab_t *t = malloc(sizeof(ktap_tab_t)); t->gct = ~KTAP_TTAB; hsize = 1024; t->hmask = hsize - 1; t->node = (ktap_node_t *)malloc(hsize * sizeof(ktap_node_t)); t->freetop = &t->node[hsize]; t->asize = 0; for (i = 0; i <= t->hmask; i++) { set_nil(&t->node[i].val); set_nil(&t->node[i].key); } return t; }
/* * 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 table_sort_iter_next(ktap_state *ks) { ktap_tab *t = hvalue(ks->top - 2); if (kp_tab_sort_next(ks, t, ks->top-1)) { ks->top += 1; return 2; } else { ks->top -= 1; set_nil(ks->top++); return 1; } }
void kp_obj_clone(ktap_state *ks, const ktap_value *o, ktap_value *newo, ktap_gcobject **list) { if (is_btrace(o)) { int nr_entries = btvalue(o)->nr_entries; ktap_btrace *bt; bt = kp_obj_newbacktrace(ks, nr_entries, list); memcpy((unsigned long *)(bt + 1), btvalue(o) + 1, nr_entries * sizeof(unsigned long)); set_btrace(newo, bt); } else { kp_error(ks, "cannot clone ktap value type %d\n", ttype(o)); set_nil(newo); } }
/** * 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; }
ktap_val_t *kp_tab_set(ktap_tab_t *t, const ktap_val_t *key) { const ktap_val_t *v = kp_tab_get(t, key); if (v != niltv) { return (ktap_val_t *)v; } else { if (t->freetop == t->node) { int size = (t->hmask + 1) * sizeof(ktap_node_t); t->node = realloc(t->node, size * 2); memset(t->node + t->hmask + 1, 0, size); t->freetop = t->node + (t->hmask + 1) * 2; t->hmask = (t->hmask + 1) * 2 - 1; } ktap_node_t *n = --t->freetop; set_obj(gkey(n), key); set_nil(gval(n)); return gval(n); } }
static int kplib_pairs(ktap_state *ks) { ktap_value *v = kp_arg(ks, 1); 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; } set_cfunction(ks->top++, table_iter_next); set_table(ks->top++, t); set_nil(ks->top++); return 3; }
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; }