forked from osmocom/wireshark
dfilter: Print syntax tree using dftest + format enhancements
Add argument to dfilter_compile_real() to save syntax tree text representation. Use it with dftest to print syntax tree. Misc debug output format improvements.
This commit is contained in:
parent
d91734ab6a
commit
c98df5eef5
10
dftest.c
10
dftest.c
|
@ -131,7 +131,7 @@ main(int argc, char **argv)
|
||||||
text = get_args_as_string(argc, argv, 1);
|
text = get_args_as_string(argc, argv, 1);
|
||||||
|
|
||||||
/* Compile it */
|
/* Compile it */
|
||||||
if (!dfilter_compile(text, &df, &err_msg)) {
|
if (!dfilter_compile2(text, &df, &err_msg, TRUE)) {
|
||||||
fprintf(stderr, "dftest: %s\n", err_msg);
|
fprintf(stderr, "dftest: %s\n", err_msg);
|
||||||
g_free(err_msg);
|
g_free(err_msg);
|
||||||
epan_cleanup();
|
epan_cleanup();
|
||||||
|
@ -139,10 +139,14 @@ main(int argc, char **argv)
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (df == NULL)
|
if (df == NULL) {
|
||||||
printf("Filter is empty\n");
|
printf("Filter is empty\n");
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
|
printf("Filter text:\n%s\n\n", dfilter_text(df));
|
||||||
|
printf("Syntax tree:\n%s\n\n", dfilter_syntax_tree(df));
|
||||||
dfilter_dump(df);
|
dfilter_dump(df);
|
||||||
|
}
|
||||||
|
|
||||||
dfilter_free(df);
|
dfilter_free(df);
|
||||||
epan_cleanup();
|
epan_cleanup();
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct epan_dfilter {
|
||||||
GPtrArray *deprecated;
|
GPtrArray *deprecated;
|
||||||
char *expanded_text;
|
char *expanded_text;
|
||||||
GHashTable *references;
|
GHashTable *references;
|
||||||
|
char *syntax_tree_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -208,6 +208,7 @@ dfilter_free(dfilter_t *df)
|
||||||
g_free(df->attempted_load);
|
g_free(df->attempted_load);
|
||||||
g_free(df->free_registers);
|
g_free(df->free_registers);
|
||||||
g_free(df->expanded_text);
|
g_free(df->expanded_text);
|
||||||
|
g_free(df->syntax_tree_str);
|
||||||
g_free(df);
|
g_free(df);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +339,8 @@ add_deprecated_token(dfwork_t *dfw, const char *token)
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||||
gchar **error_ret, const char *caller)
|
gchar **error_ret, const char *caller,
|
||||||
|
gboolean save_tree)
|
||||||
{
|
{
|
||||||
gchar *expanded_text;
|
gchar *expanded_text;
|
||||||
int token;
|
int token;
|
||||||
|
@ -349,6 +351,7 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||||
YY_BUFFER_STATE in_buffer;
|
YY_BUFFER_STATE in_buffer;
|
||||||
gboolean failure = FALSE;
|
gboolean failure = FALSE;
|
||||||
unsigned token_count = 0;
|
unsigned token_count = 0;
|
||||||
|
char *tree_str;
|
||||||
|
|
||||||
ws_assert(dfp);
|
ws_assert(dfp);
|
||||||
*dfp = NULL;
|
*dfp = NULL;
|
||||||
|
@ -462,14 +465,20 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||||
*dfp = NULL;
|
*dfp = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
log_syntax_tree(LOG_LEVEL_NOISY, dfw->st_root, "Syntax tree before semantic check");
|
log_syntax_tree(LOG_LEVEL_NOISY, dfw->st_root, "Syntax tree before semantic check", NULL);
|
||||||
|
|
||||||
/* Check semantics and do necessary type conversion*/
|
/* Check semantics and do necessary type conversion*/
|
||||||
if (!dfw_semcheck(dfw)) {
|
if (!dfw_semcheck(dfw)) {
|
||||||
goto FAILURE;
|
goto FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_syntax_tree(LOG_LEVEL_NOISY, dfw->st_root, "Syntax tree after successful semantic check");
|
/* Cache tree representation in tree_str. */
|
||||||
|
tree_str = NULL;
|
||||||
|
log_syntax_tree(LOG_LEVEL_NOISY, dfw->st_root, "Syntax tree after successful semantic check", &tree_str);
|
||||||
|
|
||||||
|
if (save_tree && tree_str == NULL) {
|
||||||
|
tree_str = dump_syntax_tree_str(dfw->st_root);
|
||||||
|
}
|
||||||
|
|
||||||
/* Create bytecode */
|
/* Create bytecode */
|
||||||
dfw_gencode(dfw);
|
dfw_gencode(dfw);
|
||||||
|
@ -484,6 +493,17 @@ dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||||
dfilter->references = dfw->references;
|
dfilter->references = dfw->references;
|
||||||
dfw->references = NULL;
|
dfw->references = NULL;
|
||||||
|
|
||||||
|
if (save_tree) {
|
||||||
|
ws_assert(tree_str);
|
||||||
|
dfilter->syntax_tree_str = tree_str;
|
||||||
|
tree_str = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dfilter->syntax_tree_str = NULL;
|
||||||
|
g_free(tree_str);
|
||||||
|
tree_str = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize run-time space */
|
/* Initialize run-time space */
|
||||||
dfilter->num_registers = dfw->next_register;
|
dfilter->num_registers = dfw->next_register;
|
||||||
dfilter->registers = g_new0(GSList *, dfilter->num_registers);
|
dfilter->registers = g_new0(GSList *, dfilter->num_registers);
|
||||||
|
@ -582,6 +602,18 @@ dfilter_dump(dfilter_t *df)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
dfilter_text(dfilter_t *df)
|
||||||
|
{
|
||||||
|
return df->expanded_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
dfilter_syntax_tree(dfilter_t *df)
|
||||||
|
{
|
||||||
|
return df->syntax_tree_str;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dfilter_log_full(const char *domain, enum ws_log_level level,
|
dfilter_log_full(const char *domain, enum ws_log_level level,
|
||||||
const char *file, long line, const char *func,
|
const char *file, long line, const char *func,
|
||||||
|
@ -598,9 +630,9 @@ dfilter_log_full(const char *domain, enum ws_log_level level,
|
||||||
|
|
||||||
char *str = dfvm_dump_str(NULL, df, TRUE);
|
char *str = dfvm_dump_str(NULL, df, TRUE);
|
||||||
if (G_UNLIKELY(msg == NULL))
|
if (G_UNLIKELY(msg == NULL))
|
||||||
ws_log_write_always_full(domain, level, file, line, func, "\n%s", str);
|
ws_log_write_always_full(domain, level, file, line, func, "Filter:%s\n%s", dfilter_text(df), str);
|
||||||
else
|
else
|
||||||
ws_log_write_always_full(domain, level, file, line, func, "%s\n%s", msg, str);
|
ws_log_write_always_full(domain, level, file, line, func, "%s:\nFilter: %s\nInstructions:\n%s", msg, dfilter_text(df), str);
|
||||||
g_free(str);
|
g_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,10 +49,14 @@ dfilter_cleanup(void);
|
||||||
WS_DLL_PUBLIC
|
WS_DLL_PUBLIC
|
||||||
gboolean
|
gboolean
|
||||||
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
dfilter_compile_real(const gchar *text, dfilter_t **dfp,
|
||||||
gchar **err_msg, const char *caller);
|
gchar **err_msg, const char *caller,
|
||||||
|
gboolean save_tree);
|
||||||
|
|
||||||
#define dfilter_compile(text, dfp, err_msg) \
|
#define dfilter_compile(text, dfp, err_msg) \
|
||||||
dfilter_compile_real(text, dfp, err_msg, __func__)
|
dfilter_compile_real(text, dfp, err_msg, __func__, FALSE)
|
||||||
|
|
||||||
|
#define dfilter_compile2(text, dfp, err_msg, save_tree) \
|
||||||
|
dfilter_compile_real(text, dfp, err_msg, __func__, save_tree)
|
||||||
|
|
||||||
/* Frees all memory used by dfilter, and frees
|
/* Frees all memory used by dfilter, and frees
|
||||||
* the dfilter itself. */
|
* the dfilter itself. */
|
||||||
|
@ -91,6 +95,16 @@ WS_DLL_PUBLIC
|
||||||
void
|
void
|
||||||
dfilter_dump(dfilter_t *df);
|
dfilter_dump(dfilter_t *df);
|
||||||
|
|
||||||
|
/* Text after macro expansion. */
|
||||||
|
WS_DLL_PUBLIC
|
||||||
|
const char *
|
||||||
|
dfilter_text(dfilter_t *df);
|
||||||
|
|
||||||
|
/* Text representation of syntax tree (if it was saved, NULL oterwise). */
|
||||||
|
WS_DLL_PUBLIC
|
||||||
|
const char *
|
||||||
|
dfilter_syntax_tree(dfilter_t *df);
|
||||||
|
|
||||||
/* Print bytecode of dfilter to log */
|
/* Print bytecode of dfilter to log */
|
||||||
WS_DLL_PUBLIC
|
WS_DLL_PUBLIC
|
||||||
void
|
void
|
||||||
|
|
|
@ -195,9 +195,7 @@ dfvm_dump_str(wmem_allocator_t *alloc, dfilter_t *df, gboolean print_references)
|
||||||
|
|
||||||
buf = wmem_strbuf_new(alloc, NULL);
|
buf = wmem_strbuf_new(alloc, NULL);
|
||||||
|
|
||||||
wmem_strbuf_append_printf(buf, "Filter: %s\n", df->expanded_text);
|
wmem_strbuf_append(buf, "Instructions:\n");
|
||||||
|
|
||||||
wmem_strbuf_append(buf, "\nInstructions:\n");
|
|
||||||
|
|
||||||
length = df->insns->len;
|
length = df->insns->len;
|
||||||
for (id = 0; id < length; id++) {
|
for (id = 0; id < length; id++) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ function_tostr(const void *data, gboolean pretty)
|
||||||
|
|
||||||
ws_assert(def);
|
ws_assert(def);
|
||||||
|
|
||||||
g_string_printf(repr, "%s(", def->name);
|
g_string_printf(repr, "%s: ", def->name);
|
||||||
while (params != NULL) {
|
while (params != NULL) {
|
||||||
ws_assert(params->data);
|
ws_assert(params->data);
|
||||||
g_string_append(repr, stnode_tostr(params->data, pretty));
|
g_string_append(repr, stnode_tostr(params->data, pretty));
|
||||||
|
@ -69,7 +69,6 @@ function_tostr(const void *data, gboolean pretty)
|
||||||
g_string_append(repr, ", ");
|
g_string_append(repr, ", ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_string_append_c(repr, ')');
|
|
||||||
|
|
||||||
return g_string_free(repr, FALSE);
|
return g_string_free(repr, FALSE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ sttype_fvalue_tostr(const void *data, gboolean pretty)
|
||||||
if (pretty)
|
if (pretty)
|
||||||
repr = g_strdup(s);
|
repr = g_strdup(s);
|
||||||
else
|
else
|
||||||
repr = ws_strdup_printf("%s[%s]", fvalue_type_name(fvalue), s);
|
repr = ws_strdup_printf("%s <%s>", s, fvalue_type_name(fvalue));
|
||||||
g_free(s);
|
g_free(s);
|
||||||
return repr;
|
return repr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,25 +187,25 @@ test_todebug(test_op_t op)
|
||||||
s = "TEST_LE";
|
s = "TEST_LE";
|
||||||
break;
|
break;
|
||||||
case OP_BITWISE_AND:
|
case OP_BITWISE_AND:
|
||||||
s = "BITWISE_AND";
|
s = "OP_BITWISE_AND";
|
||||||
break;
|
break;
|
||||||
case OP_UNARY_MINUS:
|
case OP_UNARY_MINUS:
|
||||||
s = "UNARY_MINUS";
|
s = "OP_UNARY_MINUS";
|
||||||
break;
|
break;
|
||||||
case OP_ADD:
|
case OP_ADD:
|
||||||
s = "ADD";
|
s = "OP_ADD";
|
||||||
break;
|
break;
|
||||||
case OP_SUBTRACT:
|
case OP_SUBTRACT:
|
||||||
s = "SUBTRACT";
|
s = "OP_SUBTRACT";
|
||||||
break;
|
break;
|
||||||
case OP_MULTIPLY:
|
case OP_MULTIPLY:
|
||||||
s = "MULTIPLY";
|
s = "OP_MULTIPLY";
|
||||||
break;
|
break;
|
||||||
case OP_DIVIDE:
|
case OP_DIVIDE:
|
||||||
s = "DIVIDE";
|
s = "OP_DIVIDE";
|
||||||
break;
|
break;
|
||||||
case OP_MODULO:
|
case OP_MODULO:
|
||||||
s = "MODULO";
|
s = "OP_MODULO";
|
||||||
break;
|
break;
|
||||||
case TEST_OP_NOTZERO:
|
case TEST_OP_NOTZERO:
|
||||||
s = "TEST_NOTZERO";
|
s = "TEST_NOTZERO";
|
||||||
|
@ -286,6 +286,7 @@ sttype_test_set1(stnode_t *node, test_op_t op, stnode_t *val1)
|
||||||
ws_assert(num_operands(op) == 1);
|
ws_assert(num_operands(op) == 1);
|
||||||
test->op = op;
|
test->op = op;
|
||||||
test->val1 = val1;
|
test->val1 = val1;
|
||||||
|
test->val2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -310,6 +311,7 @@ sttype_test_set1_args(stnode_t *node, stnode_t *val1)
|
||||||
|
|
||||||
ws_assert(num_operands(test->op) == 1);
|
ws_assert(num_operands(test->op) == 1);
|
||||||
test->val1 = val1;
|
test->val1 = val1;
|
||||||
|
test->val2 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -266,11 +266,12 @@ _node_tostr(stnode_t *node, gboolean pretty)
|
||||||
if (pretty)
|
if (pretty)
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
if (stnode_type_id(node) == STTYPE_TEST) {
|
if (stnode_type_id(node) == STTYPE_TEST ||
|
||||||
|
stnode_type_id(node) == STTYPE_ARITHMETIC) {
|
||||||
repr = s;
|
repr = s;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
repr = ws_strdup_printf("%s<%s>", stnode_type_name(node), s);
|
repr = ws_strdup_printf("%s(%s)", stnode_type_name(node), s);
|
||||||
g_free(s);
|
g_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +383,7 @@ indent(wmem_strbuf_t *buf, int level)
|
||||||
for (int i = 0; i < level * 2; i++) {
|
for (int i = 0; i < level * 2; i++) {
|
||||||
wmem_strbuf_append_c(buf, ' ');
|
wmem_strbuf_append_c(buf, ' ');
|
||||||
}
|
}
|
||||||
|
wmem_strbuf_append_printf(buf, "% 2d ", level);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -392,45 +394,54 @@ visit_tree(wmem_strbuf_t *buf, stnode_t *node, int level)
|
||||||
if (stnode_type_id(node) == STTYPE_TEST ||
|
if (stnode_type_id(node) == STTYPE_TEST ||
|
||||||
stnode_type_id(node) == STTYPE_BITWISE ||
|
stnode_type_id(node) == STTYPE_BITWISE ||
|
||||||
stnode_type_id(node) == STTYPE_ARITHMETIC) {
|
stnode_type_id(node) == STTYPE_ARITHMETIC) {
|
||||||
wmem_strbuf_append_printf(buf, "%s(", stnode_todebug(node));
|
wmem_strbuf_append_printf(buf, "%s:\n", stnode_todebug(node));
|
||||||
sttype_test_get(node, NULL, &left, &right);
|
sttype_test_get(node, NULL, &left, &right);
|
||||||
if (left && right) {
|
if (left && right) {
|
||||||
wmem_strbuf_append_c(buf, '\n');
|
|
||||||
indent(buf, level + 1);
|
indent(buf, level + 1);
|
||||||
wmem_strbuf_append(buf, "LHS = ");
|
|
||||||
visit_tree(buf, left, level + 1);
|
visit_tree(buf, left, level + 1);
|
||||||
wmem_strbuf_append_c(buf, '\n');
|
wmem_strbuf_append_c(buf, '\n');
|
||||||
indent(buf, level + 1);
|
indent(buf, level + 1);
|
||||||
wmem_strbuf_append(buf, "RHS = ");
|
|
||||||
visit_tree(buf, right, level + 1);
|
visit_tree(buf, right, level + 1);
|
||||||
wmem_strbuf_append(buf, "\n");
|
|
||||||
indent(buf, level);
|
|
||||||
}
|
}
|
||||||
else if (left) {
|
else if (left) {
|
||||||
visit_tree(buf, left, level);
|
indent(buf, level + 1);
|
||||||
|
visit_tree(buf, left, level + 1);
|
||||||
}
|
}
|
||||||
else if (right) {
|
else if (right) {
|
||||||
visit_tree(buf, right, level);
|
ws_assert_not_reached();
|
||||||
}
|
}
|
||||||
wmem_strbuf_append(buf, ")");
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wmem_strbuf_append(buf, stnode_todebug(node));
|
wmem_strbuf_append(buf, stnode_todebug(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
dump_syntax_tree_str(stnode_t *root)
|
||||||
|
{
|
||||||
|
wmem_strbuf_t *buf = wmem_strbuf_new(NULL, NULL);
|
||||||
|
indent(buf, 0);
|
||||||
|
visit_tree(buf, root, 0);
|
||||||
|
return wmem_strbuf_finalize(buf);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
log_syntax_tree(enum ws_log_level level, stnode_t *root, const char *msg)
|
log_syntax_tree(enum ws_log_level level, stnode_t *root, const char *msg, char **cache_ptr)
|
||||||
{
|
{
|
||||||
if (!ws_log_msg_is_active(LOG_DOMAIN_DFILTER, level))
|
if (!ws_log_msg_is_active(LOG_DOMAIN_DFILTER, level))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
wmem_strbuf_t *buf = wmem_strbuf_new(NULL, NULL);
|
char *str = dump_syntax_tree_str(root);
|
||||||
|
|
||||||
visit_tree(buf, root, 0);
|
|
||||||
ws_log_write_always_full(LOG_DOMAIN_DFILTER, level, NULL, -1, NULL,
|
ws_log_write_always_full(LOG_DOMAIN_DFILTER, level, NULL, -1, NULL,
|
||||||
"%s:\n%s", msg, wmem_strbuf_get_str(buf));
|
"%s:\n%s", msg, str);
|
||||||
wmem_strbuf_destroy(buf);
|
|
||||||
|
if (cache_ptr) {
|
||||||
|
*cache_ptr = str;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_free(str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -189,8 +189,11 @@ log_test_full(enum ws_log_level level,
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
char *
|
||||||
|
dump_syntax_tree_str(stnode_t *root);
|
||||||
|
|
||||||
void
|
void
|
||||||
log_syntax_tree(enum ws_log_level, stnode_t *root, const char *msg);
|
log_syntax_tree(enum ws_log_level, stnode_t *root, const char *msg, char **cache_ptr);
|
||||||
|
|
||||||
#ifdef WS_DISABLE_DEBUG
|
#ifdef WS_DISABLE_DEBUG
|
||||||
#define ws_assert_magic(obj, mnum) (void)0
|
#define ws_assert_magic(obj, mnum) (void)0
|
||||||
|
|
|
@ -280,6 +280,8 @@ libwireshark.so.0 libwireshark0 #MINVER#
|
||||||
dfilter_load_field_references@Base 3.7.0
|
dfilter_load_field_references@Base 3.7.0
|
||||||
dfilter_log_full@Base 3.7.0
|
dfilter_log_full@Base 3.7.0
|
||||||
dfilter_macro_get_uat@Base 1.9.1
|
dfilter_macro_get_uat@Base 1.9.1
|
||||||
|
dfilter_syntax_tree@Base 3.7.0
|
||||||
|
dfilter_text@Base 3.7.0
|
||||||
disable_name_resolution@Base 1.99.9
|
disable_name_resolution@Base 1.99.9
|
||||||
display_epoch_time@Base 1.9.1
|
display_epoch_time@Base 1.9.1
|
||||||
display_signed_time@Base 1.9.1
|
display_signed_time@Base 1.9.1
|
||||||
|
|
Loading…
Reference in New Issue