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; }
void __cp_symbol_dump_struct(csymbol *cs) { int i; csymbol *ncs; csymbol_struct *stcs = csym_struct(cs); printf("=== [%s] definition ==================\n", csym_name(cs)); for (i = 0; i < stcs->memb_nr; i++) { printf("\t(%d) ", i); printf("csym_id: %d, ", stcs->members[i].id); ncs = &cs_arr[stcs->members[i].id]; printf("name: %s, ffi_ctype: %d, %s\n", stcs->members[i].name, ncs->type, csym_name(ncs)); } }
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; } }
void kp_cdata_record_set(ktap_state_t *ks, ktap_cdata_t *cd, ktap_val_t *key, ktap_val_t *val) { const char *mb_name; csymbol *cs, *mb_cs; csymbol_struct *csst; struct_member *mb; char *addr; if (!is_shrstring(key)) { kp_error(ks, "struct member name should be string\n"); return; } mb_name = svalue(key); cs = cd_csym(ks, cd); csst = csym_struct(cs); mb = csymst_mb_by_name(ks, csst, mb_name); if (mb == NULL) { kp_error(ks, "struct member %s doesn't exist\n", mb_name); return; } mb_cs = id_to_csym(ks, mb->id); if (kp_cdata_type_match(ks, mb_cs, val)) { kp_error(ks, "struct member should be %s type\n", csym_name(mb_cs)); return; } addr = cd_record(cd); addr += csym_record_mb_offset_by_name(ks, cs, mb_name); kp_cdata_unpack(ks, addr, mb_cs, val); }
void kp_cdata_ptr_set(ktap_state_t *ks, ktap_cdata_t *cd, ktap_val_t *key, ktap_val_t *val) { ktap_number idx; csymbol *cs; size_t size; char *addr; if (!is_number(key)) { kp_error(ks, "array index should be number\n"); return; } idx = nvalue(key); if (unlikely(idx < 0 || (cd_ptr_nmemb(cd) >= 0 && idx >= cd_ptr_nmemb(cd)))) { kp_error(ks, "array index out of bound\n"); return; } cs = csym_ptr_deref(ks, cd_csym(ks, cd)); if (kp_cdata_type_match(ks, cs, val)) { kp_error(ks, "array member should be %s type\n", csym_name(cs)); return; } size = csym_size(ks, cs); addr = cd_ptr(cd); addr += size * idx; kp_cdata_unpack(ks, addr, cs, val); }
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; }
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; } }
void __cp_symbol_dump_func(csymbol *cs) { int i; csymbol *ncs; csymbol_func *fcs = csym_func(cs); printf("=== [%s] function definition =============\n", csym_name(cs)); ncs = cp_csymf_ret(fcs); printf("address: %p\n", fcs->addr); printf("return type: \n"); printf("\tcsym_id: %d, ffi_ctype: %d, %s\n", fcs->ret_id, ncs->type, csym_name(ncs)); printf("args type (%d): \n", fcs->arg_nr); for (i = 0; i < csymf_arg_nr(fcs); i++) { printf("\t (%d) ", i); printf("csym_id: %d, ", fcs->arg_ids[i]); ncs = cp_csymf_arg(fcs, i); printf("ffi_ctype: %d, %s\n", ncs->type, csym_name(ncs)); } }
/* build pointer symbol from given csymbol */ int cp_symbol_build_pointer(struct cp_ctype *ct) { int id, ret; csymbol ncspt; csymbol *ref_cs = ct_ffi_cs(ct); /* TODO: Check correctness of multi-level pointer 24.11.2013(unihorn) */ memset(&ncspt, 0, sizeof(csymbol)); ncspt.type = FFI_PTR; ret = sprintf(ncspt.name, "%s *", csym_name(ref_cs)); assert(ret < MAX_TYPE_NAME_LEN); csym_set_ptr_deref_id(&ncspt, ct->ffi_cs_id); id = cp_ctype_reg_csymbol(&ncspt); return id; }
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; } }
/* push ctype to stack, create new csymbol if needed */ void cp_push_ctype_with_name(struct cp_ctype *ct, const char *name, int nlen) { int i; struct cp_ctype *nct; if (ctype_stack_free_space() < 1) ctype_stack_grow(4); /* we have to check pointer here because does type lookup by name * before parsing '*', and for pointers, ct will always be the * original type */ if (ct->pointers) { for (i = 0; i < cte_nr; i++) { nct = &(cte_arr[i].ct); if (nct->type == ct->type && nct->pointers == ct->pointers) { break; } } if (i == cte_nr) { /* pointer type not found * create a new pointer symbol for this type */ /* associate ctype with new csymbol */ ct->ffi_cs_id = cp_symbol_build_pointer(ct); /* register wit new pointer name */ cp_ctype_reg_type(csym_name(ct_ffi_cs(ct)), ct); } else { /* pointer type already registered, reinstantiate ct */ *ct = cte_arr[i].ct; } } memset(ct_stack(cts.top), 0, sizeof(cp_ctype_entry)); ct_stack(cts.top)->ct = *ct; if (name) strncpy(ct_stack(cts.top)->name, name, nlen); cts.top++; }