[ktap] [PATCH 5/8] Integrate ffi call module into vm

  • From: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx>
  • To: ktap@xxxxxxxxxxxxx
  • Date: Tue, 26 Nov 2013 14:52:33 -0500

This patch adds following features to vm:
* loading csymbols from chunks
* calling 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 | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 interpreter/kp_obj.c  |  6 ++++
 interpreter/kp_tab.c  |  2 +-
 interpreter/kp_vm.c   | 35 ++++++++++++++++++++--
 interpreter/ktap.h    |  9 ++++++
 interpreter/lib_ffi.c | 62 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 190 insertions(+), 4 deletions(-)
 create mode 100644 interpreter/lib_ffi.c

diff --git a/interpreter/kp_load.c b/interpreter/kp_load.c
index 2e3fd37..543739e 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,79 @@ 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 void 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;
+       }
+
+       /* csymbol size safty check */
+       if (sizeof(csymbol) != READ_INT(S)) {
+               kp_error(S->ks, "invalid csymbol size in chunk\n");
+               return;
+       }
+
+       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);
+}
+#else
+static void 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) {
+               int cs_size = READ_INT(S);
+                /*skip corrupted csymbol chunk */
+               ADD_POS(S, cs_size*csym_nr);
+               kp_error(S->ks, "VM compiled with no FFI support!\n");
+       }
+}
+#endif
 
 static int verify_code(struct load_state *S, ktap_proto *f)
 {
@@ -277,6 +352,8 @@ ktap_closure *kp_load(ktap_state *ks, unsigned char *buff)
        if (ret)
                return NULL;
 
+       load_csymbols(&S);
+
        cl = kp_newclosure(ks, 1);
        if (!cl)
                return cl;
@@ -309,6 +386,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 c2fc7ef..0826fd5 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(cd) != FFI_FUNC)
+                       kp_error(ks, "Value in cdata is not a c funcion\n");
+               cs = cd_csym(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);
@@ -1320,6 +1349,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);
@@ -1418,6 +1448,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..8b12270
--- /dev/null
+++ b/interpreter/lib_ffi.c
@@ -0,0 +1,62 @@
+/*
+ * 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 int kp_ffi_current(ktap_state *ks)
+{
+       ktap_cdata *cd;
+
+       cd = kp_cdata_new_ptr(ks, current, ffi_get_csym_id("void *"));
+       set_cdata(ks->top, cd);
+       incr_top(ks);
+
+       return 1;
+}
+
+static const ktap_Reg ffi_funcs[] = {
+       {"sizeof", kp_ffi_sizeof},
+       {"new", kp_ffi_new},
+       {"current", kp_ffi_current},
+       {NULL}
+};
+
+void kp_init_ffilib(ktap_state *ks)
+{
+       kp_register_lib(ks, "ffi", ffi_funcs);
+}
-- 
1.8.3.4 (Apple Git-47)


Other related posts:

  • » [ktap] [PATCH 5/8] Integrate ffi call module into vm - Yicheng Qin