dftest: More code cleanups and enhancements

This commit is contained in:
João Valverde 2023-01-07 02:40:14 +00:00
parent 0c24b0ae72
commit 7641ba7416
4 changed files with 609 additions and 524 deletions

617
dftest.c
View File

@ -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] -- <EXPR>\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);
}

View File

@ -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);
}

View File

@ -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;
}
}

2
file.c
View File

@ -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");
}