From: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> When ktapc finds a 'cdef' token, it passes the C code to cparser module, which then generates c symbols accordingly. This patch also handles how to dump c symbols into vm chunk. Signed-off-by: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx> Signed-off-by: Qingping Hou <qingping.hou@xxxxxxxxx> --- userspace/dump.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ userspace/ktapc.h | 14 ++++++++++++ userspace/lex.c | 8 +++---- userspace/main.c | 4 ++++ userspace/parser.c | 50 +++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 133 insertions(+), 6 deletions(-) diff --git a/userspace/dump.c b/userspace/dump.c index 0a27a1c..a1958eb 100644 --- a/userspace/dump.c +++ b/userspace/dump.c @@ -31,6 +31,7 @@ #include "../include/ktap_opcodes.h" #include "ktapc.h" #include "../interpreter/kp_obj.h" +#include "cparser.h" typedef struct { @@ -171,6 +172,67 @@ static void DumpHeader(DumpState *D) DumpBlock(h, KTAPC_HEADERSIZE, D); } +#ifdef CONFIG_KTAP_FFI +static void DumpCSymbolFunc(csymbol *cs, DumpState *D) +{ + csymbol_func *csf = csym_func(cs); + + DumpBlock(cs, sizeof(csymbol), D); + /* dump csymbol index for argument types */ + DumpBlock(csf->arg_ids, csf->arg_nr*sizeof(int), D); +} + +static void DumpCSymbolStruct(csymbol *cs, DumpState *D) +{ + csymbol_struct *csst = csym_struct(cs); + + DumpBlock(cs, sizeof(csymbol), D); + /* dump csymbol index for argument types */ + DumpBlock(csst->members, csst->memb_nr*sizeof(struct_member), D); +} + +static void DumpCSymbols(DumpState *D) +{ + int i, cs_nr; + cp_csymbol_state *cs_state; + csymbol *cs, *cs_arr; + + cs_state = ctype_get_csym_state(); + cs_arr = cs_state->cs_arr; + cs_nr = cs_state->cs_nr; + + if (!cs_arr || cs_nr == 0) { + DumpInt(0, D); + return; + } + + /* dump number of csymbols */ + DumpInt(cs_nr, D); + /* dump size of csymbol, for safty check in vm */ + DumpInt(sizeof(csymbol), D); + for (i = 0; i < cs_nr; i++) { + cs = &cs_arr[i]; + switch (cs->type) { + case FFI_FUNC: + DumpCSymbolFunc(cs, D); + break; + case FFI_STRUCT: + DumpCSymbolStruct(cs, D); + break; + default: + DumpBlock(cs, sizeof(csymbol), D); + break; + } + } +} +#else +static void DumpCSymbols(DumpState *D) +{ + /* always dump zero when FFI is disabled */ + DumpInt(0, D); +} +#endif /* CONFIG_KTAP_FFI */ + /* * dump ktap function as precompiled chunk */ @@ -183,6 +245,7 @@ int ktapc_dump(const ktap_proto *f, ktap_writer w, void *data, int strip) D.strip = strip; D.status = 0; DumpHeader(&D); + DumpCSymbols(&D); DumpFunction(f, &D); return D.status; } diff --git a/userspace/ktapc.h b/userspace/ktapc.h index a7a9e32..e6acbf5 100644 --- a/userspace/ktapc.h +++ b/userspace/ktapc.h @@ -78,6 +78,7 @@ enum RESERVED { /* terminal symbols denoted by reserved words */ TK_TRACE = FIRST_RESERVED, TK_TRACE_END, TK_ARGEVENT, TK_ARGNAME, + TK_FFI_CDEF, TK_ARG1, TK_ARG2, TK_ARG3, TK_ARG4, TK_ARG5, TK_ARG6, TK_ARG7, TK_ARG8, TK_ARG9, TK_PROFILE, TK_TICK, TK_AGGR_ASSIGN, TK_AND, TK_BREAK, @@ -377,3 +378,16 @@ int kallsyms_parse(void *arg, unsigned long find_kernel_symbol(const char *symbol); void list_available_events(const char *match); + + +#ifdef CONFIG_KTAP_FFI +#include "../interpreter/kp_ffi.h" + +typedef struct cp_csymbol_state { + int cs_nr; /* number of c symbols */ + int cs_arr_size; /* size of current symbol arrays */ + csymbol *cs_arr; +} cp_csymbol_state; + +cp_csymbol_state *ctype_get_csym_state(void); +#endif diff --git a/userspace/lex.c b/userspace/lex.c index 5180eec..2cfcd92 100644 --- a/userspace/lex.c +++ b/userspace/lex.c @@ -39,7 +39,7 @@ /* ORDER RESERVED */ static const char *const ktap_tokens [] = { - "trace", "trace_end", "argevent", "argname", + "trace", "trace_end", "argevent", "argname", "cdef", "arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7", "arg9", "arg9", "profile", "tick", "<<<", "and", "break", "do", "else", "elseif", @@ -133,7 +133,7 @@ ktap_string *lex_newstring(ktap_lexstate *ls, const char *str, size_t l) ktap_value val; /* entry for `str' */ ktap_value tsv; ktap_string *ts = ktapc_ts_newlstr(str, l); /* create new string */ - set_string(&tsv, ts); + set_string(&tsv, ts); o = ktapc_table_get(ls->fs->h, &tsv); if (is_nil(o)) { /* not in use yet? (see 'addK') */ /* boolean value does not need GC barrier; @@ -553,7 +553,7 @@ static int llex(ktap_lexstate *ls, ktap_seminfo *seminfo) next(ls); return TK_AND; } - } + } case '|': { next(ls); if (ls->current != '|') @@ -562,7 +562,7 @@ static int llex(ktap_lexstate *ls, ktap_seminfo *seminfo) next(ls); return TK_OR; } - } + } default: { if (islalpha(ls->current)) { /* identifier or reserved word? */ diff --git a/userspace/main.c b/userspace/main.c index bdb6bb1..47df6df 100644 --- a/userspace/main.c +++ b/userspace/main.c @@ -40,6 +40,7 @@ #include "../interpreter/kp_str.h" #include "../interpreter/kp_tab.h" #include "symbol.h" +#include "cparser.h" /*******************************************************************/ @@ -618,6 +619,7 @@ static void compile(const char *input) if (oneline_src[0] != '\0') { init_dummy_global_state(); + ffi_cparser_init(); cl = ktapc_parser(oneline_src, input); goto dump; } @@ -636,6 +638,7 @@ static void compile(const char *input) handle_error("mmap failed"); init_dummy_global_state(); + ffi_cparser_init(); cl = ktapc_parser(buff, input); munmap(buff, sb.st_size); @@ -653,6 +656,7 @@ static void compile(const char *input) handle_error("malloc failed"); ktapc_dump(cl->p, ktapc_writer, NULL, 0); + ffi_cparser_free(); } int main(int argc, char **argv) diff --git a/userspace/parser.c b/userspace/parser.c index 5366004..00afa20 100644 --- a/userspace/parser.c +++ b/userspace/parser.c @@ -30,6 +30,7 @@ #include "../include/ktap_types.h" #include "../include/ktap_opcodes.h" #include "ktapc.h" +#include "cparser.h" /* maximum number of local variables per function (must be smaller than 250, due to the bytecode format) */ @@ -1490,7 +1491,7 @@ static void forstat(ktap_lexstate *ls, int line) case ',': case TK_IN: forlist(ls, varname); break; - default: + default: lex_syntaxerror(ls, KTAP_QL("=") " or " KTAP_QL("in") " expected"); } //check_match(ls, TK_END, TK_FOR, line); @@ -1797,6 +1798,49 @@ static void timerstat(ktap_lexstate *ls) SETARG_C(getcode(fs, v), 1); /* call statement uses no results */ } +#ifdef CONFIG_KTAP_FFI +static void __parsecdef(ktap_lexstate *ls) +{ + ktap_mbuffer cdef_buf; + int len; + + /* get rid of double qoutes */ + len = strlen(mbuff(ls->buff)); + mbuff_init(&cdef_buf); + mbuff_resize(&cdef_buf, len-1); + mbuff_reset(&cdef_buf); + strncpy(mbuff(&cdef_buf), mbuff(ls->buff)+1, len-2); + ffi_cdef(mbuff(&cdef_buf)); + mbuff_free(&cdef_buf); +} +#else +static void __parsecdef(ktap_lexstate *ls) +{ + printf("Please compile with FFI support to use cdef!\n"); + exit(EXIT_SUCCESS); +} +#endif + +/* we still keep cdef keyword even FFI feature is disabled, it just does + * nothing and prints out a warning */ +static void parsecdef(ktap_lexstate *ls) +{ + /* skip " */ + lex_next(ls); + /* read cdef string */ + lex_next(ls); + + if (ls->t.token != TK_STRING) + error_expected(ls, TK_STRING); + + __parsecdef(ls); + + /* consume ( */ + lex_next(ls); + /* consume newline */ + lex_next(ls); +} + static void statement(ktap_lexstate *ls) { int line = ls->linenumber; /* may be needed for error messages */ @@ -1865,6 +1909,9 @@ static void statement(ktap_lexstate *ls) case TK_TICK: timerstat(ls); break; + case TK_FFI_CDEF: + parsecdef(ls); + break; default: { /* stat -> func | assignment */ exprstat(ls); break; @@ -1925,4 +1972,3 @@ ktap_closure *ktapc_parser(char *ptr, const char *name) ktap_assert(dyd.actvar.n == 0 && dyd.gt.n == 0 && dyd.label.n == 0); return cl; } - -- 1.8.1.2