From: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> This patch adds following features to vm: * load csymbols from vm chunk file * call C functions using ffi call module * ffi library with functions that are designed to meet general usage for ffi module. Signed-off-by: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> Signed-off-by: Qingping Hou <qingping.hou@xxxxxxxxx> --- interpreter/kp_load.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++- interpreter/kp_obj.c | 6 ++++ interpreter/kp_tab.c | 2 +- interpreter/kp_vm.c | 35 +++++++++++++++++++-- interpreter/ktap.h | 9 ++++++ interpreter/lib_ffi.c | 50 +++++++++++++++++++++++++++++ 6 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 interpreter/lib_ffi.c diff --git a/interpreter/kp_load.c b/interpreter/kp_load.c index 2e3fd37..70006b5 100644 --- a/interpreter/kp_load.c +++ b/interpreter/kp_load.c @@ -31,6 +31,7 @@ #include "kp_str.h" #include "kp_tab.h" #include "kp_vm.h" +#include "kp_ffi.h" #define KTAPC_TAIL "\x19\x93\r\n\x1a\n" @@ -52,6 +53,7 @@ struct load_state { } while(0) #define NEW_VECTOR(S, size) kp_malloc(S->ks, size) +#define FREE_VECTOR(S, v) kp_free(S->ks, v) #define GET_CURRENT(S) &S->buff[S->pos] #define ADD_POS(S, size) S->pos += size @@ -141,7 +143,7 @@ static int load_constants(struct load_state *S, ktap_proto *f) kp_error(S->ks, "ktap: load_constants: " "unknow ktap_value\n"); return -1; - + } } @@ -255,6 +257,84 @@ static int load_header(struct load_state *S) return -1; } +#ifdef CONFIG_KTAP_FFI +static void load_csymbol_func(struct load_state *S, csymbol *cs) +{ + csymbol_func *csf = csym_func(cs); + int arg_nr = csymf_arg_nr(csf); + + if (arg_nr > 0) { + csf->arg_ids = NEW_VECTOR(S, arg_nr*sizeof(int)); + READ_VECTOR(S, csf->arg_ids, arg_nr*sizeof(int)); + } else { + csf->arg_ids = NULL; + } +} + +static void load_csymbol_struct(struct load_state *S, csymbol *cs) +{ + csymbol_struct *csst = csym_struct(cs); + int mb_nr = csymst_mb_nr(csst); + + csst->members = NEW_VECTOR(S, mb_nr*sizeof(struct_member)); + READ_VECTOR(S, csst->members, mb_nr*sizeof(struct_member)); +} + +static int load_csymbols(struct load_state *S) +{ + csymbol *cs_arr, *cs; + int i, csym_nr; + + /* read number of csymbols */ + csym_nr = READ_INT(S); + if (csym_nr <= 0) { + ffi_set_csym_arr(S->ks, 0, NULL); + return 0; + } + + /* csymbol size safty check */ + if (sizeof(csymbol) != READ_INT(S)) { + kp_error(S->ks, "invalid csymbol size in chunk\n"); + return -1; + } + + cs_arr = NEW_VECTOR(S, sizeof(csymbol)*csym_nr); + for (i = 0; i < csym_nr; i++) { + cs = &cs_arr[i]; + READ_VECTOR(S, cs, sizeof(csymbol)); + switch (cs->type) { + case FFI_FUNC: + load_csymbol_func(S, cs); + break; + case FFI_STRUCT: + load_csymbol_struct(S, cs); + break; + default: + break; + } + } + + ffi_set_csym_arr(S->ks, csym_nr, cs_arr); + + return 0; +} +#else +static int load_csymbols(struct load_state *S) +{ + int csym_nr = READ_INT(S); + + /* if FFI is disabled in ktapc, csym_nr should be 0 */ + if (csym_nr != 0) { + /* skip corrupted csymbol chunk */ + int cs_size = READ_INT(S); + ADD_POS(S, cs_size*csym_nr); + kp_error(S->ks, "VM compiled without FFI support!\n"); + return -1; + } + + return 0; +} +#endif static int verify_code(struct load_state *S, ktap_proto *f) { @@ -277,6 +357,10 @@ ktap_closure *kp_load(ktap_state *ks, unsigned char *buff) if (ret) return NULL; + ret = load_csymbols(&S); + if (ret) + return NULL; + cl = kp_newclosure(ks, 1); if (!cl) return cl; @@ -309,6 +393,7 @@ ktap_closure *kp_load(ktap_state *ks, unsigned char *buff) } verify_code(&S, cl->p); + return cl; } diff --git a/interpreter/kp_obj.c b/interpreter/kp_obj.c index 4d0c5ed..7787e94 100644 --- a/interpreter/kp_obj.c +++ b/interpreter/kp_obj.c @@ -27,6 +27,7 @@ #include "kp_obj.h" #include "kp_str.h" #include "kp_tab.h" +#include "kp_ffi.h" #ifdef __KERNEL__ #include <linux/slab.h> @@ -235,6 +236,11 @@ void kp_showobj(ktap_state *ks, const ktap_value *v) kp_table_dump(ks, hvalue(v)); break; #ifdef __KERNEL__ +#ifdef CONFIG_KTAP_FFI + case KTAP_TCDATA: + kp_cdata_dump(ks, cdvalue(v)); + break; +#endif case KTAP_TEVENT: kp_transport_event_write(ks, evalue(v)); break; diff --git a/interpreter/kp_tab.c b/interpreter/kp_tab.c index 24c87d5..dc368b6 100644 --- a/interpreter/kp_tab.c +++ b/interpreter/kp_tab.c @@ -956,7 +956,7 @@ int kp_table_length(ktap_state *ks, ktap_table *t) len++; } - + kp_table_unlock(t); return len; } diff --git a/interpreter/kp_vm.c b/interpreter/kp_vm.c index e2d774b..7696f16 100644 --- a/interpreter/kp_vm.c +++ b/interpreter/kp_vm.c @@ -36,6 +36,7 @@ #include "kp_tab.h" #include "kp_transport.h" #include "kp_vm.h" +#include "kp_ffi.h" #define KTAP_MIN_RESERVED_STACK_SIZE 20 #define KTAP_STACK_SIZE 120 /* enlarge this value for big stack */ @@ -316,6 +317,10 @@ static int precall(ktap_state *ks, StkId func, int nresults) ktap_cfunction f; ktap_callinfo *ci; ktap_proto *p; +#ifdef CONFIG_KTAP_FFI + ktap_cdata *cd; + csymbol *cs; +#endif StkId base; ptrdiff_t funcr = savestack(ks, func); int n; @@ -335,7 +340,7 @@ static int precall(ktap_state *ks, StkId func, int nresults) n = (*f)(ks); poscall(ks, ks->top - n); return 1; - case KTAP_TCLOSURE: + case KTAP_TCLOSURE: p = clvalue(func)->p; if (checkstack(ks, p->maxstacksize)) @@ -358,6 +363,30 @@ static int precall(ktap_state *ks, StkId func, int nresults) ci->callstatus = CIST_KTAP; ks->top = ci->top; return 0; +#ifdef CONFIG_KTAP_FFI + case KTAP_TCDATA: + cd = cdvalue(func); + + if (checkstack(ks, KTAP_MIN_RESERVED_STACK_SIZE)) + return 1; + + if (cd_type(ks, cd) != FFI_FUNC) + kp_error(ks, "Value in cdata is not a c funcion\n"); + cs = cd_csym(ks, cd); + kp_verbose_printf(ks, "calling ffi function [%s] with address %p\n", + csym_name(cs), csym_func_addr(cs)); + + ci = next_ci(ks); + ci->nresults = nresults; + ci->func = restorestack(ks, funcr); + ci->top = ks->top + KTAP_MIN_RESERVED_STACK_SIZE; + ci->callstatus = 0; + + n = kp_ffi_call(ks, csym_func(cs)); + kp_verbose_printf(ks, "returned from ffi call...\n"); + poscall(ks, ks->top - n); + return 1; +#endif default: kp_error(ks, "attempt to call nil function\n"); } @@ -1004,7 +1033,7 @@ static int kp_init_arguments(ktap_state *ks, int argc, char __user **user_argv) ktap_value arg_tsval; char **argv; int i, ret; - + set_string(&arg_tsval, kp_tstring_new(ks, "arg")); set_table(&arg_tblval, arg_tbl); kp_table_setvalue(ks, global_tbl, &arg_tsval, &arg_tblval); @@ -1350,6 +1379,7 @@ void kp_final_exit(ktap_state *ks) kp_probe_exit(ks); /* free all resources got by ktap */ + kp_ffi_free_symbol(ks); kp_tstring_freeall(ks); kp_free_all_gcobject(ks); cfunction_cache_exit(ks); @@ -1448,6 +1478,7 @@ ktap_state *kp_newstate(ktap_parm *parm, struct dentry *dir) kp_init_kdebuglib(ks); kp_init_timerlib(ks); kp_init_ansilib(ks); + kp_init_ffilib(ks); if (alloc_kp_percpu_data(ks)) goto out; diff --git a/interpreter/ktap.h b/interpreter/ktap.h index dda3b2d..06ede8c 100644 --- a/interpreter/ktap.h +++ b/interpreter/ktap.h @@ -35,6 +35,15 @@ void kp_init_oslib(ktap_state *ks); void kp_init_kdebuglib(ktap_state *ks); void kp_init_timerlib(ktap_state *ks); void kp_init_ansilib(ktap_state *ks); +#ifdef CONFIG_KTAP_FFI +void kp_init_ffilib(ktap_state *ks); +#else +static void __maybe_unused kp_init_ffilib(ktap_state *ks) +{ + return; +} +#endif + int kp_probe_init(ktap_state *ks); void kp_probe_exit(ktap_state *ks); diff --git a/interpreter/lib_ffi.c b/interpreter/lib_ffi.c new file mode 100644 index 0000000..35a7d93 --- /dev/null +++ b/interpreter/lib_ffi.c @@ -0,0 +1,50 @@ +/* + * ffi.c - ktapvm kernel module ffi library + * + * This file is part of ktap by Jovi Zhangwei. + * + * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@xxxxxxxxx>. + * + * ktap is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * ktap is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "../include/ktap_types.h" +#include "ktap.h" +#include "kp_vm.h" +#include "kp_ffi.h" + +/*@TODO Design how to implement ffi helper functions 22.11 2013 (unihorn)*/ + +static int kp_ffi_new(ktap_state *ks) +{ + /*@TODO finish this 08.11 2013 (houqp)*/ + return 0; +} + +static int kp_ffi_sizeof(ktap_state *ks) +{ + /*@TODO finish this 08.11 2013 (houqp)*/ + return 0; +} + +static const ktap_Reg ffi_funcs[] = { + {"sizeof", kp_ffi_sizeof}, + {"new", kp_ffi_new}, + {NULL} +}; + +void kp_init_ffilib(ktap_state *ks) +{ + kp_register_lib(ks, "ffi", ffi_funcs); +} -- 1.8.1.2