From 7641ba7416cdb0232ecef7c5aa3d39a711d1766c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Valverde?= Date: Sat, 7 Jan 2023 02:40:14 +0000 Subject: [PATCH] dftest: More code cleanups and enhancements --- dftest.c | 617 ++++++++++++++++++++++------------------- epan/dfilter/dfilter.c | 4 +- epan/dfilter/dfvm.c | 510 ++++++++++++++++++---------------- file.c | 2 +- 4 files changed, 609 insertions(+), 524 deletions(-) diff --git a/dftest.c b/dftest.c index 82ea33aa0d..53e39614be 100644 --- a/dftest.c +++ b/dftest.c @@ -40,290 +40,15 @@ #include "ui/failure_message.h" #include "ui/version_info.h" -static void dftest_cmdarg_err(const char *fmt, va_list ap); -static void dftest_cmdarg_err_cont(const char *fmt, va_list ap); - static int opt_verbose = 0; static int opt_noisy = 0; static int opt_flex = 0; static int opt_lemon = 0; static int opt_syntax_tree = 0; +static int opt_timer = 0; -static void -putloc(FILE *fp, df_loc_t loc) -{ - for (long i = 0; i < loc.col_start; i++) { - fputc(' ', fp); - } - fputc('^', fp); - - for (size_t l = loc.col_len; l > 1; l--) { - fputc('~', fp); - } - fputc('\n', fp); -} - -static void -print_usage(void) -{ - fprintf(stderr, "Usage: dftest [OPTIONS] -- \n"); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -v verbose mode\n"); - fprintf(stderr, " -d enable noisy display filter logs\n"); - fprintf(stderr, " -f enable Flex debug trace\n"); - fprintf(stderr, " -l enable Lemon debug trace\n"); - fprintf(stderr, " -s print syntax tree\n"); - fprintf(stderr, " -h display this help and exit\n"); -} - -static void -print_syntax_tree(dfilter_t *df) -{ - printf("Syntax tree:\n%s\n\n", dfilter_syntax_tree(df)); -} - -static void -print_warnings(dfilter_t *df) -{ - guint i; - GSList *warnings; - GPtrArray *deprecated; - - warnings = dfilter_get_warnings(df); - for (GSList *l = warnings; l != NULL; l = l->next) { - printf("Warning: %s.\n", (char *)l->data); - } - - deprecated = dfilter_deprecated_tokens(df); - if (deprecated && deprecated->len) { - for (i = 0; i < deprecated->len; i++) { - printf("Warning: Deprecated token \"%s\".\n", (char *) g_ptr_array_index(deprecated, i)); - } - } - - if (warnings || (deprecated && deprecated->len > 0)) { - printf("\n"); - } -} - -static void -print_elapsed(gdouble expand_secs, gdouble compile_secs) -{ - printf("Elapsed time: %.f µs (%.f µs + %.f µs)\n", - (expand_secs + compile_secs) * 1000 * 1000, - expand_secs * 1000 * 1000, - compile_secs * 1000 * 1000); -} - -int -main(int argc, char **argv) -{ - char *configuration_init_error; - static const struct report_message_routines dftest_report_routines = { - failure_message, - failure_message, - open_failure_message, - read_failure_message, - write_failure_message, - cfile_open_failure_message, - cfile_dump_open_failure_message, - cfile_read_failure_message, - cfile_write_failure_message, - cfile_close_failure_message - }; - char *text = NULL; - char *expanded_text = NULL; - dfilter_t *df = NULL; - gchar *err_msg = NULL; - df_error_t *df_err = NULL; - unsigned df_flags = 0; - GTimer *timer = NULL; - gdouble elapsed_expand, elapsed_compile; - gboolean ok; - int exit_status = 0; - int opt; - - cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont); - - /* Initialize log handler early so we can have proper logging during startup. */ - ws_log_init("dftest", vcmdarg_err); - - /* Early logging command-line initialization. */ - ws_log_parse_args(&argc, argv, vcmdarg_err, 1); - - ws_noisy("Finished log init and parsing command line log arguments"); - - /* - * Set the C-language locale to the native environment and set the - * code page to UTF-8 on Windows. - */ -#ifdef _WIN32 - setlocale(LC_ALL, ".UTF-8"); -#else - setlocale(LC_ALL, ""); -#endif - - ws_init_version_info("DFTest", NULL, NULL); - - while ((opt = ws_getopt(argc, argv, "vdflsh")) != -1) { - switch (opt) { - case 'v': - opt_verbose = 1; - break; - case 'd': - opt_noisy = 1; - break; - case 'f': - opt_flex = 1; - break; - case 'l': - opt_lemon = 1; - break; - case 's': - opt_syntax_tree = 1; - break; - case 'h': - /* fall-through */ - default: /* '?' */ - show_help_header(NULL); - printf("\n"); - print_usage(); - exit(EXIT_FAILURE); - } - } - - if (opt_noisy) - ws_log_set_noisy_filter(LOG_DOMAIN_DFILTER); - - /* - * Get credential information for later use. - */ - init_process_policies(); - - /* - * Attempt to get the pathname of the directory containing the - * executable file. - */ - configuration_init_error = configuration_init(argv[0], NULL); - if (configuration_init_error != NULL) { - fprintf(stderr, "dftest: Can't get pathname of directory containing the dftest program: %s.\n", - configuration_init_error); - g_free(configuration_init_error); - } - - init_report_message("dftest", &dftest_report_routines); - - timestamp_set_type(TS_RELATIVE); - timestamp_set_seconds_type(TS_SECONDS_DEFAULT); - - /* - * Libwiretap must be initialized before libwireshark is, so that - * dissection-time handlers for file-type-dependent blocks can - * register using the file type/subtype value for the file type. - */ - wtap_init(TRUE); - - /* Register all dissectors; we must do this before checking for the - "-g" flag, as the "-g" flag dumps a list of fields registered - by the dissectors, and we must do it before we read the preferences, - in case any dissectors register preferences. */ - if (!epan_init(NULL, NULL, FALSE)) - return 2; - - /* Load libwireshark settings from the current profile. */ - epan_load_settings(); - - /* notify all registered modules that have had any of their preferences - changed either from one of the preferences file or from the command - line that its preferences have changed. */ - prefs_apply_all(); - - /* Check for filter on command line */ - if (argv[ws_optind] == NULL) { - print_usage(); - exit(1); - } - - /* This is useful to prevent confusion with option parsing. - * Skips printing options and argv[0]. */ - if (opt_verbose) { - for (int i = ws_optind; i < argc; i++) { - printf("argv[%d]: %s\n", i, argv[i]); - } - printf("\n"); - } - - /* Get filter text */ - text = get_args_as_string(argc, argv, ws_optind); - - printf("Filter:\n %s\n\n", text); - - timer = g_timer_new(); - - /* Expand macros. */ - g_timer_start(timer); - expanded_text = dfilter_expand(text, &err_msg); - g_timer_stop(timer); - elapsed_expand = g_timer_elapsed(timer, NULL); - if (expanded_text == NULL) { - fprintf(stderr, "Error: %s\n", err_msg); - g_free(err_msg); - exit_status = 2; - goto out; - } - - if (strcmp(text, expanded_text) != 0) - printf("Filter (after expansion):\n %s\n\n", expanded_text); - - /* Compile it */ - if (opt_syntax_tree) - df_flags |= DF_SAVE_TREE; - if (opt_flex) - df_flags |= DF_DEBUG_FLEX; - if (opt_lemon) - df_flags |= DF_DEBUG_LEMON; - g_timer_start(timer); - ok = dfilter_compile_real(expanded_text, &df, &df_err, df_flags, "dftest"); - g_timer_stop(timer); - elapsed_compile = g_timer_elapsed(timer, NULL); - if (!ok) { - fprintf(stderr, "Error: %s\n", df_err->msg); - if (df_err->loc.col_start >= 0) { - fprintf(stderr, " %s\n ", expanded_text); - putloc(stderr, df_err->loc); - } - dfilter_error_free(df_err); - exit_status = 2; - goto out; - } - - if (df == NULL) { - printf("Filter is empty.\n"); - goto out; - } - - if (opt_syntax_tree) - print_syntax_tree(df); - - dfilter_dump(stdout, df); - printf("\n"); - - print_warnings(df); - - print_elapsed(elapsed_expand, elapsed_compile); - -out: - epan_cleanup(); - if (df != NULL) - dfilter_free(df); - if (text != NULL) - g_free(text); - if (expanded_text != NULL) - g_free(expanded_text); - if (timer != NULL) - g_timer_destroy(timer); - exit(exit_status); -} +static gdouble elapsed_expand = 0; +static gdouble elapsed_compile = 0; /* * Report an error in command-line arguments. @@ -345,3 +70,339 @@ dftest_cmdarg_err_cont(const char *fmt, va_list ap) vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } + +static void +putloc(FILE *fp, df_loc_t loc) +{ + for (long i = 0; i < loc.col_start; i++) { + fputc(' ', fp); + } + fputc('^', fp); + + for (size_t l = loc.col_len; l > 1; l--) { + fputc('~', fp); + } + fputc('\n', fp); +} + +static void +print_usage(void) +{ + FILE *fp = stdout; + fprintf(fp, "Usage: dftest [OPTIONS] -- EXPRESSION\n"); + fprintf(fp, "Options:\n"); + fprintf(fp, " -V, --verbose enable verbose mode\n"); + fprintf(fp, " -d, --debug enable compiler debug logs\n"); + fprintf(fp, " -f, --flex enable Flex debug trace\n"); + fprintf(fp, " -l, --lemon enable Lemon debug trace\n"); + fprintf(fp, " -s, --syntax print syntax tree\n"); + fprintf(fp, " -t, --timer print elapsed compilation time\n"); + fprintf(fp, " -h, --help display this help and exit\n"); + fprintf(fp, " -v, --version print version\n"); +} + +static void +print_syntax_tree(dfilter_t *df) +{ + printf("Syntax tree:\n%s\n\n", dfilter_syntax_tree(df)); +} + +static void +print_warnings(dfilter_t *df) +{ + guint i; + GPtrArray *deprecated; + int count = 0; + + for (GSList *l = dfilter_get_warnings(df); l != NULL; l = l->next) { + printf("\nWarning: %s.", (char *)l->data); + count++; + } + + deprecated = dfilter_deprecated_tokens(df); + if (deprecated && deprecated->len) { + for (i = 0; i < deprecated->len; i++) { + const char *token = g_ptr_array_index(deprecated, i); + printf("\nWarning: Deprecated token \"%s\".", token); + count++; + } + } + + if (count) { + printf("\n"); + } +} + +static void +print_elapsed(void) +{ + printf("\nElapsed: %.f µs (%.f µs + %.f µs)\n", + (elapsed_expand + elapsed_compile) * 1000 * 1000, + elapsed_expand * 1000 * 1000, + elapsed_compile * 1000 * 1000); +} + +static char * +expand_filter(const char *text, GTimer *timer) +{ + char *expanded = NULL; + char *err_msg = NULL; + + g_timer_start(timer); + expanded = dfilter_expand(text, &err_msg); + g_timer_stop(timer); + elapsed_expand = g_timer_elapsed(timer, NULL); + if (expanded == NULL) { + fprintf(stderr, "Error: %s\n", err_msg); + g_free(err_msg); + } + return expanded; +} + +static gboolean +compile_filter(const char *text, dfilter_t **dfp, GTimer *timer) +{ + unsigned df_flags = 0; + gboolean ok; + df_error_t *df_err = NULL; + + df_flags |= DF_OPTIMIZE; + if (opt_syntax_tree) + df_flags |= DF_SAVE_TREE; + if (opt_flex) + df_flags |= DF_DEBUG_FLEX; + if (opt_lemon) + df_flags |= DF_DEBUG_LEMON; + + g_timer_start(timer); + ok = dfilter_compile_real(text, dfp, &df_err, df_flags, "dftest"); + g_timer_stop(timer); + elapsed_compile = g_timer_elapsed(timer, NULL); + + if (!ok) { + fprintf(stderr, "Error: %s\n", df_err->msg); + if (df_err->loc.col_start >= 0) { + fprintf(stderr, " %s\n ", text); + putloc(stderr, df_err->loc); + } + dfilter_error_free(df_err); + } + return ok; +} + +int +main(int argc, char **argv) +{ + char *configuration_init_error; + char *text = NULL; + char *expanded_text = NULL; + dfilter_t *df = NULL; + GTimer *timer = NULL; + int exit_status = EXIT_FAILURE; + + /* + * Set the C-language locale to the native environment and set the + * code page to UTF-8 on Windows. + */ +#ifdef _WIN32 + setlocale(LC_ALL, ".UTF-8"); +#else + setlocale(LC_ALL, ""); +#endif + + cmdarg_err_init(dftest_cmdarg_err, dftest_cmdarg_err_cont); + + /* Initialize log handler early for startup. */ + ws_log_init("dftest", vcmdarg_err); + + /* Early logging command-line initialization. */ + ws_log_parse_args(&argc, argv, vcmdarg_err, 1); + + ws_noisy("Finished log init and parsing command line log arguments"); + + ws_init_version_info("DFTest", NULL, NULL); + + const char *optstring = "hvdflsVt"; + static struct ws_option long_options[] = { + { "help", ws_no_argument, 0, 'h' }, + { "version", ws_no_argument, 0, 'v' }, + { "debug", ws_no_argument, 0, 'd' }, + { "flex", ws_no_argument, 0, 'f' }, + { "lemon", ws_no_argument, 0, 'l' }, + { "syntax", ws_no_argument, 0, 's' }, + { "timer", ws_no_argument, 0, 't' }, + { "verbose", ws_no_argument, 0, 'V' }, + { NULL, 0, 0, 0 } + }; + int opt; + + for (;;) { + opt = ws_getopt_long(argc, argv, optstring, long_options, NULL); + if (opt == -1) + break; + + switch (opt) { + case 'V': + opt_verbose = 1; + break; + case 'd': + opt_noisy = 1; + break; + case 'f': + opt_flex = 1; + break; + case 'l': + opt_lemon = 1; + break; + case 's': + opt_syntax_tree = 1; + break; + case 't': + opt_timer = 1; + break; + case 'v': + show_help_header(NULL); + exit(EXIT_SUCCESS); + break; + case 'h': + show_help_header(NULL); + printf("\n"); + print_usage(); + exit(EXIT_SUCCESS); + break; + case '?': + printf("\n"); + print_usage(); + exit(EXIT_FAILURE); + default: + ws_assert_not_reached(); + } + } + + /* Check for filter on command line */ + if (argv[ws_optind] == NULL) { + printf("Error: Missing argument.\n\n"); + print_usage(); + exit(EXIT_FAILURE); + } + + if (opt_noisy) + ws_log_set_noisy_filter(LOG_DOMAIN_DFILTER); + + /* + * Get credential information for later use. + */ + init_process_policies(); + + /* + * Attempt to get the pathname of the directory containing the + * executable file. + */ + configuration_init_error = configuration_init(argv[0], NULL); + if (configuration_init_error != NULL) { + fprintf(stderr, "Error: Can't get pathname of directory containing " + "the dftest program: %s.\n", + configuration_init_error); + g_free(configuration_init_error); + } + + static const struct report_message_routines dftest_report_routines = { + failure_message, + failure_message, + open_failure_message, + read_failure_message, + write_failure_message, + cfile_open_failure_message, + cfile_dump_open_failure_message, + cfile_read_failure_message, + cfile_write_failure_message, + cfile_close_failure_message + }; + + init_report_message("dftest", &dftest_report_routines); + + timestamp_set_type(TS_RELATIVE); + timestamp_set_seconds_type(TS_SECONDS_DEFAULT); + + /* + * Libwiretap must be initialized before libwireshark is, so that + * dissection-time handlers for file-type-dependent blocks can + * register using the file type/subtype value for the file type. + */ + wtap_init(TRUE); + + /* Register all dissectors; we must do this before checking for the + "-g" flag, as the "-g" flag dumps a list of fields registered + by the dissectors, and we must do it before we read the preferences, + in case any dissectors register preferences. */ + if (!epan_init(NULL, NULL, FALSE)) + goto out; + + /* Load libwireshark settings from the current profile. */ + epan_load_settings(); + + /* notify all registered modules that have had any of their preferences + changed either from one of the preferences file or from the command + line that its preferences have changed. */ + prefs_apply_all(); + + /* This is useful to prevent confusion with option parsing. + * Skips printing options and argv[0]. */ + if (opt_verbose) { + for (int i = ws_optind; i < argc; i++) { + fprintf(stderr, "argv[%d]: %s\n", i, argv[i]); + } + fprintf(stderr, "\n"); + } + + /* Get filter text */ + text = get_args_as_string(argc, argv, ws_optind); + + printf("Filter:\n %s\n\n", text); + + timer = g_timer_new(); + + /* Expand macros. */ + expanded_text = expand_filter(text, timer); + if (expanded_text == NULL) { + exit_status = 2; + goto out; + } + + if (strcmp(text, expanded_text) != 0) + printf("Filter (after expansion):\n %s\n\n", expanded_text); + + /* Compile it */ + if (!compile_filter(expanded_text, &df, timer)) { + exit_status = 2; + goto out; + } + + if (df == NULL) { + printf("Filter is empty.\n"); + exit_status = 1; + goto out; + } + + if (opt_syntax_tree) + print_syntax_tree(df); + + dfilter_dump(stdout, df); + printf("\n"); + + print_warnings(df); + + if (opt_timer) + print_elapsed(); + + exit_status = 0; + +out: + epan_cleanup(); + dfilter_free(df); + g_free(text); + g_free(expanded_text); + if (timer != NULL) + g_timer_destroy(timer); + exit(exit_status); +} diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c index 64ea165b11..934a8f95f2 100644 --- a/epan/dfilter/dfilter.c +++ b/epan/dfilter/dfilter.c @@ -661,9 +661,9 @@ dfilter_log_full(const char *domain, enum ws_log_level level, char *str = dfvm_dump_str(NULL, df, TRUE); if (G_UNLIKELY(msg == NULL)) - ws_log_write_always_full(domain, level, file, line, func, "\nFilter:\n%s\n%s", dfilter_text(df), str); + ws_log_write_always_full(domain, level, file, line, func, "\nFilter:\n %s\n\n%s", dfilter_text(df), str); else - ws_log_write_always_full(domain, level, file, line, func, "%s:\nFilter:\n%s\n%s", msg, dfilter_text(df), str); + ws_log_write_always_full(domain, level, file, line, func, "%s:\nFilter:\n %s\n\n%s", msg, dfilter_text(df), str); g_free(str); } diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c index 0e28715423..ac8e80d90b 100644 --- a/epan/dfilter/dfvm.c +++ b/epan/dfilter/dfvm.c @@ -263,29 +263,256 @@ dump_str_stack_pop(GSList *stack, guint32 count) } static void -append_op(wmem_strbuf_t *buf, int id, dfvm_opcode_t opcode) +append_call_function(wmem_strbuf_t *buf, const char *func, uint32_t nargs, + GSList *stack_print) { - char *str; - size_t len; -#define INDENT_COLUMN 24 + uint32_t idx; + GString *gs; + GSList *l; + const char *sep = ""; - str = ws_strdup_printf(" %04d %s ", id, dfvm_opcode_tostr(opcode)); - wmem_strbuf_append(buf, str); - len = strlen(str); - g_free(str); - if (len < INDENT_COLUMN) { - wmem_strbuf_append_c_count(buf, ' ', INDENT_COLUMN - len); + wmem_strbuf_append_printf(buf, "%s(", func); + if (nargs > 0) { + gs = g_string_new(NULL); + for (l = stack_print, idx = 0; l != NULL && idx < nargs; idx++, l = l->next) { + g_string_prepend(gs, sep); + g_string_prepend(gs, l->data); + sep = ", "; + } + wmem_strbuf_append(buf, gs->str); + g_string_free(gs, TRUE); } + wmem_strbuf_append(buf, ")"); } +static void +indent(wmem_strbuf_t *buf, size_t offset, size_t start) +{ + size_t pos = buf->len - start; + if (pos >= offset) + return; + wmem_strbuf_append_c_count(buf, ' ', offset - pos); +} +#define indent1(buf, start) indent(buf, 24, start) +#define indent2(buf, start) indent(buf, 16, start) + static void append_to_register(wmem_strbuf_t *buf, const char *reg) { - if (reg != NULL) { - wmem_strbuf_append(buf, " -> "); - wmem_strbuf_append(buf, reg); + wmem_strbuf_append_printf(buf, " >> %s", reg); +} + +static void +append_op_args(wmem_strbuf_t *buf, dfvm_insn_t *insn, GSList **stack_print) +{ + dfvm_value_t *arg1, *arg2, *arg3; + char *arg1_str, *arg2_str, *arg3_str; + size_t col_start; + + arg1 = insn->arg1; + arg2 = insn->arg2; + arg3 = insn->arg3; + arg1_str = dfvm_value_tostr(arg1); + arg2_str = dfvm_value_tostr(arg2); + arg3_str = dfvm_value_tostr(arg3); + + col_start = buf->len; + + switch (insn->op) { + case DFVM_CHECK_EXISTS: + case DFVM_CHECK_EXISTS_R: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + break; + + case DFVM_READ_TREE: + case DFVM_READ_TREE_R: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_READ_REFERENCE: + case DFVM_READ_REFERENCE_R: + wmem_strbuf_append_printf(buf, "${%s}", arg1_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_PUT_FVALUE: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_CALL_FUNCTION: + append_call_function(buf, arg1_str, arg3->value.numeric, *stack_print); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_STACK_PUSH: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + *stack_print = dump_str_stack_push(*stack_print, arg1_str); + break; + + case DFVM_STACK_POP: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + *stack_print = dump_str_stack_pop(*stack_print, arg1->value.numeric); + break; + + case DFVM_SLICE: + wmem_strbuf_append_printf(buf, "%s[%s]", arg1_str, arg3_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_LENGTH: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_ALL_EQ: + wmem_strbuf_append_printf(buf, "%s === %s", arg1_str, arg2_str); + break; + + case DFVM_ANY_EQ: + wmem_strbuf_append_printf(buf, "%s == %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_NE: + wmem_strbuf_append_printf(buf, "%s != %s", arg1_str, arg2_str); + break; + + case DFVM_ANY_NE: + wmem_strbuf_append_printf(buf, "%s !== %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_GT: + case DFVM_ANY_GT: + wmem_strbuf_append_printf(buf, "%s > %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_GE: + case DFVM_ANY_GE: + wmem_strbuf_append_printf(buf, "%s >= %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_LT: + case DFVM_ANY_LT: + wmem_strbuf_append_printf(buf, "%s < %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_LE: + case DFVM_ANY_LE: + wmem_strbuf_append_printf(buf, "%s <= %s", arg1_str, arg2_str); + break; + + case DFVM_NOT_ALL_ZERO: + wmem_strbuf_append_printf(buf, "%s", arg1_str); + break; + + case DFVM_ALL_CONTAINS: + case DFVM_ANY_CONTAINS: + wmem_strbuf_append_printf(buf, "%s contains %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_MATCHES: + case DFVM_ANY_MATCHES: + wmem_strbuf_append_printf(buf, "%s matches %s", arg1_str, arg2_str); + break; + + case DFVM_ALL_IN_RANGE: + case DFVM_ANY_IN_RANGE: + wmem_strbuf_append_printf(buf, "%s in { %s .. %s }", arg1_str, arg2_str, arg3_str); + break; + + case DFVM_BITWISE_AND: + wmem_strbuf_append_printf(buf, "%s & %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_UNARY_MINUS: + wmem_strbuf_append_printf(buf, "-%s", arg1_str); + indent2(buf, col_start); + append_to_register(buf, arg2_str); + break; + + case DFVM_ADD: + wmem_strbuf_append_printf(buf, "%s + %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_SUBTRACT: + wmem_strbuf_append_printf(buf, "%s - %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_MULTIPLY: + wmem_strbuf_append_printf(buf, "%s * %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_DIVIDE: + wmem_strbuf_append_printf(buf, "%s / %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_MODULO: + wmem_strbuf_append_printf(buf, "%s %% %s", arg1_str, arg2_str); + indent2(buf, col_start); + append_to_register(buf, arg3_str); + break; + + case DFVM_IF_TRUE_GOTO: + case DFVM_IF_FALSE_GOTO: + wmem_strbuf_append_printf(buf, "%u", arg1->value.numeric); + break; + + case DFVM_NOT: + case DFVM_RETURN: + ws_assert_not_reached(); + } + + g_free(arg1_str); + g_free(arg2_str); + g_free(arg3_str); +} + +static void +append_references(wmem_strbuf_t *buf, GHashTable *references, gboolean raw) +{ + GHashTableIter ref_iter; + gpointer key, value; + char *str; + guint i; + + g_hash_table_iter_init(&ref_iter, references); + while (g_hash_table_iter_next(&ref_iter, &key, &value)) { + const char *abbrev = ((header_field_info *)key)->abbrev; + GPtrArray *refs_array = value; + df_reference_t *ref; + + if (raw) + wmem_strbuf_append_printf(buf, " ${@%s} = {", abbrev); + else + wmem_strbuf_append_printf(buf, " ${%s} = {", abbrev); + for (i = 0; i < refs_array->len; i++) { + if (i != 0) { + wmem_strbuf_append(buf, ", "); + } + ref = refs_array->pdata[i]; + str = fvalue_to_debug_repr(NULL, ref->value); + wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(ref->value)); + g_free(str); + } + wmem_strbuf_append(buf, "}\n"); } - wmem_strbuf_append_c(buf, '\n'); } char * @@ -293,244 +520,41 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references) { int id, length; dfvm_insn_t *insn; - dfvm_value_t *arg1, *arg2, *arg3; - char *arg1_str, *arg2_str, *arg3_str; wmem_strbuf_t *buf; - GHashTableIter ref_iter; - gpointer key, value; - char *str; - GSList *stack_print = NULL, *l; - guint i; + GSList *stack_print = NULL; + size_t col_start; buf = wmem_strbuf_new(alloc, NULL); - wmem_strbuf_append(buf, "Instructions:\n"); - - length = df->insns->len; - for (id = 0; id < length; id++) { - - insn = g_ptr_array_index(df->insns, id); - arg1 = insn->arg1; - arg2 = insn->arg2; - arg3 = insn->arg3; - arg1_str = dfvm_value_tostr(arg1); - arg2_str = dfvm_value_tostr(arg2); - arg3_str = dfvm_value_tostr(arg3); - - append_op(buf, id, insn->op); - - switch (insn->op) { - case DFVM_CHECK_EXISTS: - case DFVM_CHECK_EXISTS_R: - wmem_strbuf_append_printf(buf, "%s\n", arg1_str); - break; - - case DFVM_READ_TREE: - case DFVM_READ_TREE_R: - wmem_strbuf_append_printf(buf, "%s", arg1_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_READ_REFERENCE: - case DFVM_READ_REFERENCE_R: - wmem_strbuf_append_printf(buf, "${%s}", arg1_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_PUT_FVALUE: - wmem_strbuf_append_printf(buf, "%s", arg1_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_CALL_FUNCTION: - { - uint32_t nargs = arg3->value.numeric; - uint32_t idx; - GString *gs; - const char *sep = ""; - - wmem_strbuf_append_printf(buf, "%s(", arg1_str); - if (nargs > 0) { - gs = g_string_new(NULL); - for (l = stack_print, idx = 0; l != NULL && idx < nargs; idx++, l = l->next) { - g_string_prepend(gs, sep); - g_string_prepend(gs, l->data); - sep = ", "; - } - wmem_strbuf_append(buf, gs->str); - g_string_free(gs, TRUE); - } - wmem_strbuf_append(buf, ")"); - append_to_register(buf, arg2_str); - break; - } - case DFVM_STACK_PUSH: - wmem_strbuf_append_printf(buf, "%s\n", arg1_str); - stack_print = dump_str_stack_push(stack_print, arg1_str); - break; - - case DFVM_STACK_POP: - wmem_strbuf_append_printf(buf, "%s\n", arg1_str); - stack_print = dump_str_stack_pop(stack_print, arg1->value.numeric); - break; - - case DFVM_SLICE: - wmem_strbuf_append_printf(buf, "%s[%s]", arg1_str, arg3_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_LENGTH: - wmem_strbuf_append_printf(buf, "%s", arg1_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_ALL_EQ: - wmem_strbuf_append_printf(buf, "%s === %s\n", arg1_str, arg2_str); - break; - - case DFVM_ANY_EQ: - wmem_strbuf_append_printf(buf, "%s == %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_NE: - wmem_strbuf_append_printf(buf, "%s != %s\n", arg1_str, arg2_str); - break; - - case DFVM_ANY_NE: - wmem_strbuf_append_printf(buf, "%s !== %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_GT: - case DFVM_ANY_GT: - wmem_strbuf_append_printf(buf, "%s > %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_GE: - case DFVM_ANY_GE: - wmem_strbuf_append_printf(buf, "%s >= %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_LT: - case DFVM_ANY_LT: - wmem_strbuf_append_printf(buf, "%s < %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_LE: - case DFVM_ANY_LE: - wmem_strbuf_append_printf(buf, "%s <= %s\n", arg1_str, arg2_str); - break; - - case DFVM_NOT_ALL_ZERO: - wmem_strbuf_append_printf(buf, "%s\n", arg1_str); - break; - - case DFVM_ALL_CONTAINS: - case DFVM_ANY_CONTAINS: - wmem_strbuf_append_printf(buf, "%s contains %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_MATCHES: - case DFVM_ANY_MATCHES: - wmem_strbuf_append_printf(buf, "%s matches %s\n", arg1_str, arg2_str); - break; - - case DFVM_ALL_IN_RANGE: - case DFVM_ANY_IN_RANGE: - wmem_strbuf_append_printf(buf, "%s in { %s .. %s }\n", arg1_str, arg2_str, arg3_str); - break; - - case DFVM_BITWISE_AND: - wmem_strbuf_append_printf(buf, "%s & %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_UNARY_MINUS: - wmem_strbuf_append_printf(buf, "-%s", arg1_str); - append_to_register(buf, arg2_str); - break; - - case DFVM_ADD: - wmem_strbuf_append_printf(buf, "%s + %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_SUBTRACT: - wmem_strbuf_append_printf(buf, "%s - %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_MULTIPLY: - wmem_strbuf_append_printf(buf, "%s * %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_DIVIDE: - wmem_strbuf_append_printf(buf, "%s / %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_MODULO: - wmem_strbuf_append_printf(buf, "%s %% %s", arg1_str, arg2_str); - append_to_register(buf, arg3_str); - break; - - case DFVM_NOT: - case DFVM_RETURN: - wmem_strbuf_append_c(buf, '\n'); - break; - - case DFVM_IF_TRUE_GOTO: - case DFVM_IF_FALSE_GOTO: - wmem_strbuf_append_printf(buf, "%u\n", arg1->value.numeric); - break; - } - - g_free(arg1_str); - g_free(arg2_str); - g_free(arg3_str); - } - if (print_references && g_hash_table_size(df->references) > 0) { - wmem_strbuf_append(buf, "\nReferences:\n"); - g_hash_table_iter_init(&ref_iter, df->references); - while (g_hash_table_iter_next(&ref_iter, &key, &value)) { - const char *abbrev = ((header_field_info *)key)->abbrev; - GPtrArray *refs_array = value; - df_reference_t *ref; - - wmem_strbuf_append_printf(buf, "${%s} = {", abbrev); - for (i = 0; i < refs_array->len; i++) { - if (i != 0) { - wmem_strbuf_append(buf, ", "); - } - ref = refs_array->pdata[i]; - str = fvalue_to_debug_repr(NULL, ref->value); - wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(ref->value)); - g_free(str); - } - wmem_strbuf_append(buf, "}\n"); - } + wmem_strbuf_append(buf, "References:\n"); + append_references(buf, df->references, FALSE); + wmem_strbuf_append_c(buf, '\n'); } if (print_references && g_hash_table_size(df->raw_references) > 0) { - wmem_strbuf_append(buf, "\nRaw references:\n"); - g_hash_table_iter_init(&ref_iter, df->raw_references); - while (g_hash_table_iter_next(&ref_iter, &key, &value)) { - const char *abbrev = ((header_field_info *)key)->abbrev; - GPtrArray *refs_array = value; - df_reference_t *ref; + wmem_strbuf_append(buf, "Raw references:\n"); + append_references(buf, df->raw_references, TRUE); + wmem_strbuf_append_c(buf, '\n'); + } - wmem_strbuf_append_printf(buf, "${@%s} = {", abbrev); - for (i = 0; i < refs_array->len; i++) { - if (i != 0) { - wmem_strbuf_append(buf, ", "); - } - ref = refs_array->pdata[i]; - str = fvalue_to_debug_repr(NULL, ref->value); - wmem_strbuf_append_printf(buf, "%s <%s>", str, fvalue_type_name(ref->value)); - g_free(str); - } - wmem_strbuf_append(buf, "}\n"); + wmem_strbuf_append(buf, "Instructions:"); + + length = df->insns->len; + for (id = 0; id < length; id++) { + insn = g_ptr_array_index(df->insns, id); + col_start = buf->len; + wmem_strbuf_append_printf(buf, "\n %04d %s", id, dfvm_opcode_tostr(insn->op)); + + switch (insn->op) { + case DFVM_NOT: + case DFVM_RETURN: + /* Nothing here */ + break; + default: + indent1(buf, col_start); + append_op_args(buf, insn, &stack_print); + break; } } diff --git a/file.c b/file.c index 19f8ca8513..a0c941eacc 100644 --- a/file.c +++ b/file.c @@ -1656,7 +1656,7 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, gb dfilter_load_field_references(dfcode, cf->edt->tree); if (dfcode != NULL) { - dfilter_log_full(LOG_DOMAIN_DFILTER, LOG_LEVEL_DEBUG, NULL, -1, NULL, + dfilter_log_full(LOG_DOMAIN_DFILTER, LOG_LEVEL_NOISY, NULL, -1, NULL, dfcode, "Rescanning packets with display filter"); }