2 * trace_events_filter - generic event filtering
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
21 #include <linux/debugfs.h>
22 #include <linux/uaccess.h>
23 #include <linux/module.h>
24 #include <linux/ctype.h>
27 #include "trace_output.h"
29 static int filter_pred_64(struct filter_pred
*pred
, void *event
)
31 u64
*addr
= (u64
*)(event
+ pred
->offset
);
32 u64 val
= (u64
)pred
->val
;
35 match
= (val
== *addr
) ^ pred
->not;
40 static int filter_pred_32(struct filter_pred
*pred
, void *event
)
42 u32
*addr
= (u32
*)(event
+ pred
->offset
);
43 u32 val
= (u32
)pred
->val
;
46 match
= (val
== *addr
) ^ pred
->not;
51 static int filter_pred_16(struct filter_pred
*pred
, void *event
)
53 u16
*addr
= (u16
*)(event
+ pred
->offset
);
54 u16 val
= (u16
)pred
->val
;
57 match
= (val
== *addr
) ^ pred
->not;
62 static int filter_pred_8(struct filter_pred
*pred
, void *event
)
64 u8
*addr
= (u8
*)(event
+ pred
->offset
);
65 u8 val
= (u8
)pred
->val
;
68 match
= (val
== *addr
) ^ pred
->not;
73 static int filter_pred_string(struct filter_pred
*pred
, void *event
)
75 char *addr
= (char *)(event
+ pred
->offset
);
78 cmp
= strncmp(addr
, pred
->str_val
, pred
->str_len
);
80 match
= (!cmp
) ^ pred
->not;
85 /* return 1 if event matches, 0 otherwise (discard) */
86 int filter_match_preds(struct ftrace_event_call
*call
, void *rec
)
88 int i
, matched
, and_failed
= 0;
89 struct filter_pred
*pred
;
91 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
93 pred
= call
->preds
[i
];
94 if (and_failed
&& !pred
->or)
96 matched
= pred
->fn(pred
, rec
);
97 if (!matched
&& !pred
->or) {
100 } else if (matched
&& pred
->or)
112 void filter_print_preds(struct filter_pred
**preds
, struct trace_seq
*s
)
115 struct filter_pred
*pred
;
119 trace_seq_printf(s
, "none\n");
123 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
126 field_name
= pred
->field_name
;
128 trace_seq_printf(s
, pred
->or ? "|| " : "&& ");
129 trace_seq_printf(s
, "%s ", field_name
);
130 trace_seq_printf(s
, pred
->not ? "!= " : "== ");
132 trace_seq_printf(s
, "%s\n", pred
->str_val
);
134 trace_seq_printf(s
, "%llu\n", pred
->val
);
140 static struct ftrace_event_field
*
141 find_event_field(struct ftrace_event_call
*call
, char *name
)
143 struct ftrace_event_field
*field
;
145 list_for_each_entry(field
, &call
->fields
, link
) {
146 if (!strcmp(field
->name
, name
))
153 void filter_free_pred(struct filter_pred
*pred
)
158 kfree(pred
->field_name
);
159 kfree(pred
->str_val
);
163 void filter_free_preds(struct ftrace_event_call
*call
)
168 for (i
= 0; i
< MAX_FILTER_PRED
; i
++)
169 filter_free_pred(call
->preds
[i
]);
175 void filter_free_subsystem_preds(struct event_subsystem
*system
)
177 struct ftrace_event_call
*call
= __start_ftrace_events
;
181 for (i
= 0; i
< MAX_FILTER_PRED
; i
++)
182 filter_free_pred(system
->preds
[i
]);
183 kfree(system
->preds
);
184 system
->preds
= NULL
;
187 events_for_each(call
) {
188 if (!call
->name
|| !call
->regfunc
)
191 if (!strcmp(call
->system
, system
->name
))
192 filter_free_preds(call
);
196 static int __filter_add_pred(struct ftrace_event_call
*call
,
197 struct filter_pred
*pred
)
201 if (call
->preds
&& !pred
->compound
)
202 filter_free_preds(call
);
205 call
->preds
= kzalloc(MAX_FILTER_PRED
* sizeof(pred
),
211 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
212 if (!call
->preds
[i
]) {
213 call
->preds
[i
] = pred
;
221 static int is_string_field(const char *type
)
223 if (strchr(type
, '[') && strstr(type
, "char"))
229 int filter_add_pred(struct ftrace_event_call
*call
, struct filter_pred
*pred
)
231 struct ftrace_event_field
*field
;
233 field
= find_event_field(call
, pred
->field_name
);
237 pred
->offset
= field
->offset
;
239 if (is_string_field(field
->type
)) {
242 pred
->fn
= filter_pred_string
;
243 pred
->str_len
= field
->size
;
244 return __filter_add_pred(call
, pred
);
250 switch (field
->size
) {
252 pred
->fn
= filter_pred_64
;
255 pred
->fn
= filter_pred_32
;
258 pred
->fn
= filter_pred_16
;
261 pred
->fn
= filter_pred_8
;
267 return __filter_add_pred(call
, pred
);
270 static struct filter_pred
*copy_pred(struct filter_pred
*pred
)
272 struct filter_pred
*new_pred
= kmalloc(sizeof(*pred
), GFP_KERNEL
);
276 memcpy(new_pred
, pred
, sizeof(*pred
));
278 if (pred
->field_name
) {
279 new_pred
->field_name
= kstrdup(pred
->field_name
, GFP_KERNEL
);
280 if (!new_pred
->field_name
) {
287 new_pred
->str_val
= kstrdup(pred
->str_val
, GFP_KERNEL
);
288 if (!new_pred
->str_val
) {
289 filter_free_pred(new_pred
);
297 int filter_add_subsystem_pred(struct event_subsystem
*system
,
298 struct filter_pred
*pred
)
300 struct ftrace_event_call
*call
= __start_ftrace_events
;
301 struct filter_pred
*event_pred
;
304 if (system
->preds
&& !pred
->compound
)
305 filter_free_subsystem_preds(system
);
307 if (!system
->preds
) {
308 system
->preds
= kzalloc(MAX_FILTER_PRED
* sizeof(pred
),
314 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
315 if (!system
->preds
[i
]) {
316 system
->preds
[i
] = pred
;
321 if (i
== MAX_FILTER_PRED
)
324 events_for_each(call
) {
327 if (!call
->name
|| !call
->regfunc
)
330 if (strcmp(call
->system
, system
->name
))
333 if (!find_event_field(call
, pred
->field_name
))
336 event_pred
= copy_pred(pred
);
340 err
= filter_add_pred(call
, event_pred
);
342 filter_free_pred(event_pred
);
350 system
->preds
[i
] = NULL
;
354 int filter_parse(char **pbuf
, struct filter_pred
*pred
)
356 char *tmp
, *tok
, *val_str
= NULL
;
359 /* field ==/!= number, or/and field ==/!= number, number */
360 while ((tok
= strsep(pbuf
, " \n"))) {
362 if (!strcmp(tok
, "0")) {
365 } else if (!strcmp(tok
, "&&")) {
368 } else if (!strcmp(tok
, "||")) {
372 pred
->field_name
= tok
;
377 if (!pred
->field_name
)
378 pred
->field_name
= tok
;
379 else if (!strcmp(tok
, "!="))
381 else if (!strcmp(tok
, "=="))
384 pred
->field_name
= NULL
;
391 if (pred
->compound
) {
392 if (!strcmp(tok
, "!="))
394 else if (!strcmp(tok
, "=="))
397 pred
->field_name
= NULL
;
414 pred
->field_name
= NULL
;
418 pred
->field_name
= kstrdup(pred
->field_name
, GFP_KERNEL
);
419 if (!pred
->field_name
)
422 pred
->val
= simple_strtoull(val_str
, &tmp
, 0);
423 if (tmp
== val_str
) {
424 pred
->str_val
= kstrdup(val_str
, GFP_KERNEL
);
427 } else if (*tmp
!= '\0')