diff --git a/basic_filters.c b/basic_filters.c index 54b52fed..da3bb80d 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 a7d93de7..9b996cf5 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 886da1b4..47ac5503 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 b403ca3a..fb8c3c1d 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 4c1ff466..73aaae3a 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 3e4f5f8e..d0788797 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); } /*