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; } }
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)); } }
/* * 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)); }
static csymbol *ffi_get_arg_csym(ktap_state_t *ks, csymbol_func *csf, int idx) { StkId arg; csymbol *cs; if (idx < csymf_arg_nr(csf)) return csymf_arg(ks, csf, idx); arg = kp_arg(ks, idx + 1); cs = id_to_csym(ks, ffi_get_csym_id(ks, "void *")); switch (ttypenv(arg)) { case KTAP_TYPE_LIGHTUSERDATA: case KTAP_TYPE_BOOLEAN: case KTAP_TYPE_NUMBER: case KTAP_TYPE_STRING: return cs; case KTAP_TYPE_CDATA: return cd_csym(ks, cdvalue(arg)); default: kp_error(ks, "Error: Cannot get type for arg %d\n", idx); return cs; } }