summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Marchuk <marchuk.nikolay.a@gmail.com>2017-08-28 09:34:03 +0700
committerDmitry V. Levin <ldv@altlinux.org>2017-12-21 13:12:36 +0000
commit59b2dbbdbd448400aef53985ab1d5f7844f5d4ea (patch)
tree1f3c3855b8b68c4fc015da5f6ee207ff3dea783e
parentdfc18a8a983182edb5dd7c7cf2e364ffb8b997df (diff)
downloadstrace-59b2dbbdbd448400aef53985ab1d5f7844f5d4ea.tar.gz
Implement path filter
* basic_filters.c (parse_path_filter, run_path_filter, free_path_filter): New functions. * filter.c (filter_types): Add path filter type. (set_filter_priv_data): New function. * filter.h (set_filter_priv_data, expression_add_filter_and): Add declarations. (DECL_FILTER): Add path filter declaration. * filter_action.c (inject_path_tracing): New function. (filtering_parse_finish): Use it. * filter_expression.c (add_variable_token, add_operator_token, expression_add_filter_and): New functions. * pathtrace.c (storepath): Duplicate path.
-rw-r--r--basic_filters.c30
-rw-r--r--filter.c8
-rw-r--r--filter.h3
-rw-r--r--filter_action.c18
-rw-r--r--filter_expression.c26
-rw-r--r--pathtrace.c2
6 files changed, 86 insertions, 1 deletions
diff --git a/basic_filters.c b/basic_filters.c
index 54b52feda..da3bb80d5 100644
--- a/basic_filters.c
+++ b/basic_filters.c
@@ -375,3 +375,33 @@ free_fd_filter(void *priv_data)
free_number_set_array(set, 1);
return;
}
+
+void *
+parse_path_filter(const char *path)
+{
+ struct path_set *set = xcalloc(1, sizeof(struct path_set));
+
+ pathtrace_select_set(path, set);
+ return set;
+}
+
+bool
+run_path_filter(struct tcb *tcp, void *priv_data)
+{
+ struct path_set *set = priv_data;
+
+ return pathtrace_match_set(tcp, set);
+}
+
+void
+free_path_filter(void *priv_data)
+{
+ struct path_set *set = priv_data;
+ unsigned int i;
+
+ for (i = 0; i < set->num_selected; ++i)
+ free((char *) set->paths_selected[i]);
+ free(set->paths_selected);
+ free(set);
+ return;
+}
diff --git a/filter.c b/filter.c
index a7d93de72..9b996cf57 100644
--- a/filter.c
+++ b/filter.c
@@ -41,6 +41,7 @@ static const struct filter_type {
} filter_types[] = {
FILTER_TYPE(syscall),
FILTER_TYPE(fd),
+ FILTER_TYPE(path),
};
#undef FILTER_TYPE
@@ -120,3 +121,10 @@ set_filters_qualify_mode(struct filter **filters, unsigned int *nfilters,
*filters = xreallocarray(*filters, filters_left, sizeof(struct filter));
*nfilters = filters_left;
}
+
+void
+set_filter_priv_data(struct filter *filter, void *priv_data)
+{
+ if (filter)
+ filter->priv_data = priv_data;
+}
diff --git a/filter.h b/filter.h
index 886da1b40..47ac5503e 100644
--- a/filter.h
+++ b/filter.h
@@ -56,6 +56,7 @@ void run_filters(struct tcb *, struct filter *, unsigned int, bool *);
void free_filter(struct filter *);
void set_filters_qualify_mode(struct filter **, unsigned int *nfilters,
unsigned int filters_left);
+void set_filter_priv_data(struct filter *, void *);
/* filter action api */
struct filter *create_filter(struct filter_action *, const char *name);
@@ -67,6 +68,7 @@ void set_filter_action_priv_data(struct filter_action *, void *);
struct bool_expression *create_expression();
bool run_expression(struct bool_expression *, bool *, unsigned int);
void set_expression_qualify_mode(struct bool_expression *, unsigned int);
+void expression_add_filter_and(struct bool_expression *, unsigned int);
#define DECL_FILTER(name) \
extern void * \
@@ -79,6 +81,7 @@ free_ ## name ## _filter(void *) \
DECL_FILTER(syscall);
DECL_FILTER(fd);
+DECL_FILTER(path);
#undef DECL_FILTER
#define DECL_FILTER_ACTION(name) \
diff --git a/filter_action.c b/filter_action.c
index b403ca3ae..fb8c3c1d6 100644
--- a/filter_action.c
+++ b/filter_action.c
@@ -86,12 +86,30 @@ compare_action_priority(const void *a, const void *b)
}
}
+static void
+inject_path_tracing(void)
+{
+ struct filter_action *action = find_or_add_action("trace");
+ struct filter *path_filter;
+
+ if (!action->nfilters)
+ qualify("trace=all");
+ path_filter = add_filter_to_array(&action->filters, &action->nfilters,
+ "path");
+ set_filter_priv_data(path_filter, &global_path_set);
+ expression_add_filter_and(action->expr, action->nfilters - 1);
+}
+
void
filtering_parsing_finish(void)
{
unsigned int maxfilters = 0;
unsigned int i;
+ /* Inject path filter into trace action. */
+ if (tracing_paths)
+ inject_path_tracing();
+
/* Sort actions by priority */
if (nfilter_actions == 0)
return;
diff --git a/filter_expression.c b/filter_expression.c
index 4c1ff466e..73aaae3a0 100644
--- a/filter_expression.c
+++ b/filter_expression.c
@@ -69,6 +69,32 @@ reallocate_expression(struct bool_expression *const expr,
expr->ntokens = new_ntokens;
}
+static void
+add_variable_token(struct bool_expression *expr, unsigned int id)
+{
+ struct expression_token token;
+ token.type = TOK_VARIABLE;
+ token.data.variable_id = id;
+ reallocate_expression(expr, expr->ntokens + 1);
+ expr->tokens[expr->ntokens - 1] = token;
+}
+
+static void
+add_operator_token(struct bool_expression *expr, int op) {
+ struct expression_token token;
+ token.type = TOK_OPERATOR;
+ token.data.operator_id = op;
+ reallocate_expression(expr, expr->ntokens + 1);
+ expr->tokens[expr->ntokens - 1] = token;
+}
+
+void
+expression_add_filter_and(struct bool_expression *expr, unsigned int filter_id)
+{
+ add_variable_token(expr, filter_id);
+ add_operator_token(expr, OP_AND);
+}
+
void
set_expression_qualify_mode(struct bool_expression *expr,
unsigned int filters_left)
diff --git a/pathtrace.c b/pathtrace.c
index 3e4f5f8e1..d07887978 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -90,7 +90,7 @@ storepath(const char *path, struct path_set *set)
xgrowarray(set->paths_selected, &set->size,
sizeof(set->paths_selected[0]));
- set->paths_selected[set->num_selected++] = path;
+ set->paths_selected[set->num_selected++] = xstrdup(path);
}
/*