summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--epan/dfilter/dfilter-int.h5
-rw-r--r--epan/dfilter/dfilter.c34
-rw-r--r--epan/dfilter/dfvm.c62
-rw-r--r--epan/dfilter/dfvm.h2
-rw-r--r--epan/dfilter/gencode.c48
5 files changed, 140 insertions, 11 deletions
diff --git a/epan/dfilter/dfilter-int.h b/epan/dfilter/dfilter-int.h
index 059a6b75af..f66e7c8a4c 100644
--- a/epan/dfilter/dfilter-int.h
+++ b/epan/dfilter/dfilter-int.h
@@ -32,7 +32,9 @@
/* Passed back to user */
struct _dfilter_t {
GPtrArray *insns;
+ GPtrArray *consts;
int num_registers;
+ int max_registers;
GList **registers;
gboolean *attempted_load;
int *interesting_fields;
@@ -44,10 +46,13 @@ typedef struct {
stnode_t *st_root;
gboolean syntax_error;
GPtrArray *insns;
+ GPtrArray *consts;
GHashTable *loaded_fields;
GHashTable *interesting_fields;
int next_insn_id;
+ int next_const_id;
int next_register;
+ int first_constant; /* first register used as a constant */
} dfwork_t;
/* Constructor/Destructor prototypes for Lemon Parser */
diff --git a/epan/dfilter/dfilter.c b/epan/dfilter/dfilter.c
index d6cf5679a0..c6d0a2b3d7 100644
--- a/epan/dfilter/dfilter.c
+++ b/epan/dfilter/dfilter.c
@@ -137,13 +137,28 @@ free_insns(GPtrArray *insns)
void
dfilter_free(dfilter_t *df)
{
+ int i;
+
+ if (!df)
+ return;
+
if (df->insns) {
free_insns(df->insns);
}
+ if (df->consts) {
+ free_insns(df->consts);
+ }
if (df->interesting_fields) {
g_free(df->interesting_fields);
}
+
+ /* clear registers */
+ for (i = 0; i < df->max_registers; i++) {
+ if (df->registers[i]) {
+ g_list_free(df->registers[i]);
+ }
+ }
g_free(df->registers);
g_free(df->attempted_load);
@@ -161,10 +176,12 @@ dfwork_new(void)
dfw->st_root = NULL;
dfw->syntax_error = FALSE;
dfw->insns = NULL;
+ dfw->consts = NULL;
dfw->loaded_fields = NULL;
dfw->interesting_fields = NULL;
dfw->next_insn_id = 0;
dfw->next_register = 0;
+ dfw->first_constant = -1;
return dfw;
}
@@ -187,11 +204,14 @@ dfwork_free(dfwork_t *dfw)
if (dfw->insns) {
free_insns(dfw->insns);
}
+
+ if (dfw->consts) {
+ free_insns(dfw->consts);
+ }
g_free(dfw);
}
-
gboolean
dfilter_compile(const gchar *text, dfilter_t **dfp)
{
@@ -279,14 +299,20 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
/* Tuck away the bytecode in the dfilter_t */
dfilter = dfilter_new();
dfilter->insns = dfw->insns;
+ dfilter->consts = dfw->consts;
dfw->insns = NULL;
+ dfw->consts = NULL;
dfilter->interesting_fields = dfw_interesting_fields(dfw,
&dfilter->num_interesting_fields);
/* Initialize run-time space */
- dfilter->num_registers = dfw->next_register;
- dfilter->registers = g_new0(GList*, dfilter->num_registers);
- dfilter->attempted_load = g_new0(gboolean, dfilter->num_registers);
+ dfilter->num_registers = dfw->first_constant;
+ dfilter->max_registers = dfw->next_register;
+ dfilter->registers = g_new0(GList*, dfilter->max_registers);
+ dfilter->attempted_load = g_new0(gboolean, dfilter->max_registers);
+
+ /* Initialize constants */
+ dfvm_init_const(dfilter);
/* And give it to the user. */
*dfp = dfilter;
diff --git a/epan/dfilter/dfvm.c b/epan/dfilter/dfvm.c
index 17d627e906..1d5899074a 100644
--- a/epan/dfilter/dfvm.c
+++ b/epan/dfilter/dfvm.c
@@ -36,6 +36,7 @@ dfvm_insn_new(dfvm_opcode_t op)
insn->arg1 = NULL;
insn->arg2 = NULL;
insn->arg3 = NULL;
+ insn->arg4 = NULL;
return insn;
}
@@ -68,6 +69,9 @@ dfvm_insn_free(dfvm_insn_t *insn)
if (insn->arg3) {
dfvm_value_free(insn->arg3);
}
+ if (insn->arg4) {
+ dfvm_value_free(insn->arg4);
+ }
g_free(insn);
}
@@ -439,11 +443,6 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
&df->registers[arg2->value.numeric]);
break;
- case PUT_FVALUE:
- accum = put_fvalue(df,
- arg1->value.fvalue, arg2->value.numeric);
- break;
-
case MK_RANGE:
arg3 = insn->arg3;
mk_range(df,
@@ -518,6 +517,12 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
}
break;
+ case PUT_FVALUE:
+#if 0
+ accum = put_fvalue(df,
+ arg1->value.fvalue, arg2->value.numeric);
+ break;
+#endif
default:
g_assert_not_reached();
@@ -528,3 +533,50 @@ dfvm_apply(dfilter_t *df, proto_tree *tree)
g_assert_not_reached();
return FALSE; /* to appease the compiler */
}
+
+void
+dfvm_init_const(dfilter_t *df)
+{
+ int id, length;
+ dfvm_insn_t *insn;
+ dfvm_value_t *arg1;
+ dfvm_value_t *arg2;
+
+ length = df->consts->len;
+
+ for (id = 0; id < length; id++) {
+
+ insn = g_ptr_array_index(df->consts, id);
+ arg1 = insn->arg1;
+ arg2 = insn->arg2;
+
+ switch (insn->op) {
+ case PUT_FVALUE:
+ put_fvalue(df,
+ arg1->value.fvalue, arg2->value.numeric);
+ break;
+ case CHECK_EXISTS:
+ case READ_TREE:
+ case CALL_FUNCTION:
+ case MK_RANGE:
+ case ANY_EQ:
+ case ANY_NE:
+ case ANY_GT:
+ case ANY_GE:
+ case ANY_LT:
+ case ANY_LE:
+ case ANY_BITWISE_AND:
+ case ANY_CONTAINS:
+ case ANY_MATCHES:
+ case NOT:
+ case RETURN:
+ case IF_TRUE_GOTO:
+ case IF_FALSE_GOTO:
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ }
+
+ return;
+}
diff --git a/epan/dfilter/dfvm.h b/epan/dfilter/dfvm.h
index cdc8f96453..ffe1b61de6 100644
--- a/epan/dfilter/dfvm.h
+++ b/epan/dfilter/dfvm.h
@@ -102,5 +102,7 @@ dfvm_dump(FILE *f, GPtrArray *insns);
gboolean
dfvm_apply(dfilter_t *df, proto_tree *tree);
+void
+dfvm_init_const(dfilter_t *df);
#endif
diff --git a/epan/dfilter/gencode.c b/epan/dfilter/gencode.c
index 78e57a7853..e6ff76ac70 100644
--- a/epan/dfilter/gencode.c
+++ b/epan/dfilter/gencode.c
@@ -47,6 +47,14 @@ dfw_append_insn(dfwork_t *dfw, dfvm_insn_t *insn)
g_ptr_array_add(dfw->insns, insn);
}
+static void
+dfw_append_const(dfwork_t *dfw, dfvm_insn_t *insn)
+{
+ insn->id = dfw->next_const_id;
+ dfw->next_const_id++;
+ g_ptr_array_add(dfw->consts, insn);
+}
+
/* returns register number */
static int
dfw_append_read_tree(dfwork_t *dfw, header_field_info *hfinfo)
@@ -116,11 +124,11 @@ dfw_append_put_fvalue(dfwork_t *dfw, fvalue_t *fv)
val1 = dfvm_value_new(FVALUE);
val1->value.fvalue = fv;
val2 = dfvm_value_new(REGISTER);
- reg = dfw->next_register++;
+ reg = dfw->first_constant--;
val2->value.numeric = reg;
insn->arg1 = val1;
insn->arg2 = val2;
- dfw_append_insn(dfw, insn);
+ dfw_append_const(dfw, insn);
return reg;
}
@@ -444,6 +452,7 @@ dfw_gencode(dfwork_t *dfw)
dfvm_value_t *arg1;
dfw->insns = g_ptr_array_new();
+ dfw->consts = g_ptr_array_new();
dfw->loaded_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
dfw->interesting_fields = g_hash_table_new(g_direct_hash, g_direct_equal);
gencode(dfw, dfw->st_root);
@@ -485,6 +494,41 @@ dfw_gencode(dfwork_t *dfw)
}
}
+ /* move constants after registers*/
+ if (dfw->first_constant == -1) {
+ /* NONE */
+ dfw->first_constant = 0;
+ return;
+ }
+
+ id = -dfw->first_constant -1;
+ dfw->first_constant = dfw->next_register;
+ dfw->next_register += id;
+
+ length = dfw->consts->len;
+ for (id = 0; id < length; id++) {
+ insn = g_ptr_array_index(dfw->consts, id);
+ if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
+ insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;
+ }
+
+ length = dfw->insns->len;
+ for (id = 0; id < length; id++) {
+ insn = g_ptr_array_index(dfw->insns, id);
+ if (insn->arg1 && insn->arg1->type == REGISTER && (int)insn->arg1->value.numeric < 0 )
+ insn->arg1->value.numeric = dfw->first_constant - insn->arg1->value.numeric -1;
+
+ if (insn->arg2 && insn->arg2->type == REGISTER && (int)insn->arg2->value.numeric < 0 )
+ insn->arg2->value.numeric = dfw->first_constant - insn->arg2->value.numeric -1;
+
+ if (insn->arg3 && insn->arg3->type == REGISTER && (int)insn->arg3->value.numeric < 0 )
+ insn->arg3->value.numeric = dfw->first_constant - insn->arg3->value.numeric -1;
+
+ if (insn->arg4 && insn->arg4->type == REGISTER && (int)insn->arg4->value.numeric < 0 )
+ insn->arg4->value.numeric = dfw->first_constant - insn->arg4->value.numeric -1;
+ }
+
+
}