From: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> ffi type is the basic type used in ffi module, which has fixed size and alignment. csymbol means symbol for c type, which is designed to represent all possible c types in its format. It doesn't contain any real value or data. ktap_cdata is the uniform cdata type in ktap. It is an instance of csymbol, which binds a csymbol with the real data. It mainly exists in the vm stack. Signed-off-by: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> Signed-off-by: Qingping Hou <qingping.hou@xxxxxxxxx> --- include/ktap_types.h | 42 +++++++- interpreter/ffi/ffi_type.c | 50 +++++++++ interpreter/kp_ffi.h | 259 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+), 1 deletion(-) create mode 100644 interpreter/ffi/ffi_type.c create mode 100644 interpreter/kp_ffi.h diff --git a/include/ktap_types.h b/include/ktap_types.h index 9cbd938..68a7877 100644 --- a/include/ktap_types.h +++ b/include/ktap_types.h @@ -8,6 +8,7 @@ typedef char u8; #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <stdint.h> #endif typedef struct ktap_parm { @@ -246,6 +247,29 @@ typedef struct ktap_stringtable { int size; } ktap_stringtable; +#ifdef CONFIG_KTAP_FFI +typedef int csymbol_id; +typedef struct csymbol csymbol; + +/* global ffi state maintained in each ktap vm instance */ +typedef struct ffi_state { + ktap_table *ctable; + int csym_nr; + csymbol *csym_arr; +} ffi_state; + +/* instance of csymbol */ +typedef struct ktap_cdata { + CommonHeader; + csymbol_id id; + union { + uint64_t i; + void *p; /* pointer address */ + void *st; /* struct member data */ + } u; +} ktap_cdata; +#endif + typedef struct ktap_stats { int mem_allocated; int nr_mem_allocate; @@ -300,6 +324,9 @@ typedef struct ktap_global_state { int wait_user; ktap_closure *trace_end_closure; struct ktap_stats __percpu *stats; +#ifdef CONFIG_KTAP_FFI + ffi_state ffis; +#endif #endif int error; } ktap_global_state; @@ -342,6 +369,9 @@ union ktap_gcobject { struct ktap_upval uv; struct ktap_state th; /* thread */ struct ktap_btrace bt; /* backtrace object */ +#ifdef CONFIG_KTAP_FFI + struct ktap_cdata cd; +#endif }; #define gch(o) (&(o)->gch) @@ -376,11 +406,11 @@ union ktap_gcobject { #define KTAP_TTHREAD 7 #define KTAP_TPROTO 8 #define KTAP_TUPVAL 9 - #define KTAP_TEVENT 10 #define KTAP_TBTRACE 11 #define KTAP_TPTABLE 12 #define KTAP_TSTATDATA 13 +#define KTAP_TCDATA 14 /* * type number is ok so far, but it may collide later between * 16+ and | (1 << 4), so be careful on this. @@ -417,6 +447,7 @@ union ktap_gcobject { #define fvalue(o) (val_(o).f) #define evalue(o) (val_(o).p) #define btvalue(o) (&val_(o).gc->bt) +#define cdvalue(o) (&val_(o).gc->cd) #define is_nil(o) ((o)->type == KTAP_TNIL) #define is_boolean(o) ((o)->type == KTAP_TBOOLEAN) @@ -430,6 +461,9 @@ union ktap_gcobject { #define is_event(o) ((o)->type == KTAP_TEVENT) #define is_btrace(o) ((o)->type == KTAP_TBTRACE) #define is_needclone(o) is_btrace(o) +#ifdef CONFIG_KTAP_FFI +#define is_cdata(o) ((o)->type == KTAP_TCDATA) +#endif #define set_nil(obj) \ @@ -476,6 +510,12 @@ union ktap_gcobject { { ktap_value *io = (obj); \ val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TBTRACE); } +#ifdef CONFIG_KTAP_FFI +#define set_cdata(obj, x) \ + { ktap_value *io=(obj); \ + val_(io).gc = (ktap_gcobject *)(x); settype(io, KTAP_TCDATA); } +#endif + #define set_obj(obj1, obj2) \ { const ktap_value *io2 = (obj2); ktap_value *io1 = (obj1); \ io1->val = io2->val; io1->type = io2->type; } diff --git a/interpreter/ffi/ffi_type.c b/interpreter/ffi/ffi_type.c new file mode 100644 index 0000000..608756b --- /dev/null +++ b/interpreter/ffi/ffi_type.c @@ -0,0 +1,50 @@ +#include "../kp_ffi.h" +#ifdef __KERNEL__ +#include <linux/types.h> +#else +#include <stdint.h> +#endif + +#define CTYPE_MODE_HELPER(name, type) \ +struct _##name##_align { \ + type t1; \ + char c; \ + type t2; \ +}; + +#define CTYPE_MODE(name) \ +{ \ + offsetof(struct _##name##_align, c), \ + offsetof(struct _##name##_align, t2) - \ + offsetof(struct _##name##_align, c), \ + #name \ +} + +#define CTYPE_MODE_NAME(name) _##name##_mode + +/* ffi_ctype_mode should be corresponded to ffi_ctype */ +CTYPE_MODE_HELPER(uint8, uint8_t); +CTYPE_MODE_HELPER(int8, int8_t); +CTYPE_MODE_HELPER(uint16, uint16_t); +CTYPE_MODE_HELPER(int16, int16_t); +CTYPE_MODE_HELPER(uint32, uint32_t); +CTYPE_MODE_HELPER(int32, int32_t); +CTYPE_MODE_HELPER(uint64, uint64_t); +CTYPE_MODE_HELPER(int64, int64_t); +CTYPE_MODE_HELPER(pointer, void*); + +const ffi_mode ffi_type_modes[NUM_FFI_TYPE+1] = { + {0, 1, "void"}, + CTYPE_MODE(uint8), + CTYPE_MODE(int8), + CTYPE_MODE(uint16), + CTYPE_MODE(int16), + CTYPE_MODE(uint32), + CTYPE_MODE(int32), + CTYPE_MODE(uint64), + CTYPE_MODE(int64), + CTYPE_MODE(pointer), + {0, 1, "function"}, + {0, 1, "struct"}, + {0, 1, "unknown"}, +}; diff --git a/interpreter/kp_ffi.h b/interpreter/kp_ffi.h new file mode 100644 index 0000000..6a3cb9c --- /dev/null +++ b/interpreter/kp_ffi.h @@ -0,0 +1,259 @@ +#ifndef __KTAP_FFI_H__ +#define __KTAP_FFI_H__ + +#ifdef CONFIG_KTAP_FFI + +#include <stddef.h> +#include "../include/ktap_types.h" + + +typedef enum { + /* 0 - 4 */ + FFI_VOID, + FFI_UINT8, + FFI_INT8, + FFI_UINT16, + FFI_INT16, + /* 5 - 9 */ + FFI_UINT32, + FFI_INT32, + FFI_UINT64, + FFI_INT64, + FFI_PTR, + /* 10 - 12 */ + FFI_FUNC, + FFI_STRUCT, + FFI_UNKNOWN, +} ffi_type; + +#define NUM_FFI_TYPE ((int)FFI_UNKNOWN) + +typedef struct { + size_t size; + size_t align; + const char *name; +} ffi_mode; +extern const ffi_mode const ffi_type_modes[]; + +#define ffi_type_size(t) (ffi_type_modes[t].size) +#define ffi_type_align(t) (ffi_type_modes[t].align) +#define ffi_type_name(t) (ffi_type_modes[t].name) + + +#define CSYM_NAME_MAX_LEN 64 + +typedef struct csymbol_func { + void *addr; + csymbol_id ret_id; + int arg_nr; + csymbol_id *arg_ids; +} csymbol_func; + +typedef struct struct_member { + char name[CSYM_NAME_MAX_LEN]; + csymbol_id id; +} struct_member; + +typedef struct csymbol_struct { + int memb_nr; + struct_member *members; + size_t size; /* bytes used to store struct */ + /* alignment of the struct, 0 indicates uninitialization */ + size_t align; +} csymbol_struct; + + +/* + * used for symbol array; + */ + +typedef struct csymbol { + char name[CSYM_NAME_MAX_LEN]; + ffi_type type; + /* only used for non scalar C types */ + union { + csymbol_id p; /* for pointer */ + csymbol_func f; + csymbol_struct st; + csymbol_id td; /* for typedef */ + } u; +} csymbol; + +inline csymbol *ffi_get_csym_by_id(ktap_state *ks, csymbol_id id); + +static inline csymbol *id_to_csym(ktap_state *ks, csymbol_id id) +{ + return ffi_get_csym_by_id(ks, id); +} + +#define csym_type(cs) ((cs)->type) + +static inline char *csym_name(csymbol *cs) +{ + return cs->name; +} + +/* + * start of pointer symbol helper functions + */ +static inline csymbol_id csym_ptr_deref_id(csymbol *cs) +{ + return cs->u.p; +} + +static inline csymbol *csym_ptr_deref(ktap_state *ks, csymbol *cs) +{ + return id_to_csym(ks, csym_ptr_deref_id(cs)); +} + +static inline void csym_set_ptr_deref(csymbol *cs, csymbol_id id) +{ + cs->u.p = id; +} + +/* + * start of function symbol helper functions + */ +static inline csymbol_func *csym_func(csymbol *cs) +{ + return &cs->u.f; +} + +static inline csymbol *csymf_arg(ktap_state *ks, csymbol_func *csf, int idx) +{ + return id_to_csym(ks, csf->arg_ids[idx]); +} + +static inline csymbol *csymf_ret(ktap_state *ks, csymbol_func *csf) +{ + return id_to_csym(ks, csf->ret_id); +} + +static inline csymbol *csym_func_arg(ktap_state *ks, csymbol *cs, int idx) +{ + return csymf_arg(ks, csym_func(cs), idx); +} + +static inline csymbol_id *csymf_arg_ids(csymbol_func *csf) +{ + return csf->arg_ids; +} + +static inline int csymf_arg_nr(csymbol_func *csf) +{ + return csf->arg_nr; +} + +static inline int *csym_func_arg_ids(csymbol *cs) +{ + return csymf_arg_ids(csym_func(cs)); +} + +static inline csymbol_id csymf_ret_id(csymbol_func *csf) +{ + return csf->ret_id; +} + +static inline void *csymf_addr(csymbol_func *csf) +{ + return csf->addr; +} + +static inline void *csym_func_addr(csymbol *cs) +{ + return csymf_addr(csym_func(cs)); +} + +/* + * start of struct symbol helper functions + */ +static inline csymbol_struct *csym_struct(csymbol *cs) +{ + return &cs->u.st; +} + +static inline csymbol *csymst_mb(ktap_state *ks, csymbol_struct *csst, int idx) +{ + return id_to_csym(ks, csst->members[idx].id); +} + +static inline csymbol *csym_struct_mb(ktap_state *ks, csymbol *cs, int idx) +{ + return csymst_mb(ks, csym_struct(cs), idx); +} + +static inline int csymst_mb_nr(csymbol_struct *csst) +{ + return csst->memb_nr; +} + +/* + * following are used in ktap_cdata type + */ + +typedef struct ktap_cdata ktap_cdata; + +#define cd_csym_id(cd) ((cd)->id) +#define cd_set_csym_id(cd, id) (cd_csym_id(cd) = (id)) +#define cd_csym(ks, cd) (id_to_csym(ks, cd_csym_id(cd))) +#define cd_type(ks, cd) (cd_csym(ks, cd)->type) + +#define cd_int(cd) ((cd)->u.i) +#define cd_ptr(cd) ((cd)->u.p) +#define cd_struct(cd) ((cd)->u.st) + + +#ifdef __KERNEL__ + +struct ktap_state; +size_t csym_size(ktap_state *ks, csymbol *sym); +size_t csym_align(ktap_state *ks, csymbol *sym); +size_t csym_struct_offset(ktap_state *ks, csymbol_struct *csst, int idx); +void init_csym_struct(ktap_state *ks, csymbol_struct *csst); + +#ifdef __x86_64 + +enum arg_status { + IN_REGISTER, + IN_MEMORY, + IN_STACK, +}; + +#define ALIGN_STACK(v, a) ((void *)(ALIGN(((uint64_t)v), a))) +#define STACK_ALIGNMENT 8 +#define REDZONE_SIZE 128 +#define GPR_SIZE (sizeof(uint64_t)) +#define MAX_GPR 6 +#define MAX_GPR_SIZE (MAX_GPR * GPR_SIZE) + +#define ffi_call(ks, cf, rvalue) ffi_call_x86_64(ks, cf, rvalue) + +#else /* non-supported platform */ + +#define ffi_call(ks, cf, rvalue) ffi_call_unsupported(ks, cf, rvalue) + +#endif /* end for platform-specific setting */ + +void ffi_set_csym_arr(ktap_state *ks, int cs_nr, csymbol *new_arr); +void kp_ffi_free_symbol(ktap_state *ks); +csymbol_id ffi_get_csym_id(ktap_state *ks, char *name); +void setup_kp_ffi_symbol_table(ktap_state *ks); + +ktap_cdata *kp_cdata_new(ktap_state *ks); +void kp_cdata_dump(ktap_state *ks, ktap_cdata *cd); +ktap_cdata *kp_cdata_new_ptr(ktap_state *ks, void *addr, csymbol_id id); +ktap_cdata *kp_cdata_new_struct(ktap_state *ks, void *val, csymbol_id id); + +int kp_ffi_call(ktap_state *ks, csymbol_func *cf); +#endif /* for __KERNEL__ */ + +#else + +static void __maybe_unused kp_ffi_free_symbol(ktap_state *ks) +{ + return; +} + +#endif /* CONFIG_KTAP_FFI */ + +#endif /* __KTAP_FFI_H__ */ -- 1.8.1.2