diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2009-10-14 15:43:35 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-10-15 04:42:36 -0400 |
| commit | 0959b8d65ce26131c2d5ccfa518a7b76529280fa (patch) | |
| tree | eae5c5c426623156142dc406f92b42d358dd53c2 /tools/perf/util/trace-event-parse.c | |
| parent | 298ebc3ef2a6c569b3eb51651f04e26aecbf8a1d (diff) | |
perf tools: Handle arrays in print fields for trace parsing
The array used by the ftrace stack events (caller[x]) causes
issues with the parser. This adds code to handle the case, but
it also assumes that the array is of type long.
Note, this is a special case used (currently) only by the ftrace
user and kernel stack records.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <20091014194358.124833639@goodmis.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/trace-event-parse.c')
| -rw-r--r-- | tools/perf/util/trace-event-parse.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 3e643f5da202..7aeedb09ea7d 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
| @@ -1046,6 +1046,35 @@ out_free: | |||
| 1046 | return EVENT_ERROR; | 1046 | return EVENT_ERROR; |
| 1047 | } | 1047 | } |
| 1048 | 1048 | ||
| 1049 | static enum event_type | ||
| 1050 | process_array(struct event *event, struct print_arg *top, char **tok) | ||
| 1051 | { | ||
| 1052 | struct print_arg *arg; | ||
| 1053 | enum event_type type; | ||
| 1054 | char *token = NULL; | ||
| 1055 | |||
| 1056 | arg = malloc_or_die(sizeof(*arg)); | ||
| 1057 | memset(arg, 0, sizeof(*arg)); | ||
| 1058 | |||
| 1059 | *tok = NULL; | ||
| 1060 | type = process_arg(event, arg, &token); | ||
| 1061 | if (test_type_token(type, token, EVENT_OP, (char *)"]")) | ||
| 1062 | goto out_free; | ||
| 1063 | |||
| 1064 | top->op.right = arg; | ||
| 1065 | |||
| 1066 | free_token(token); | ||
| 1067 | type = read_token_item(&token); | ||
| 1068 | *tok = token; | ||
| 1069 | |||
| 1070 | return type; | ||
| 1071 | |||
| 1072 | out_free: | ||
| 1073 | free_token(*tok); | ||
| 1074 | free_arg(arg); | ||
| 1075 | return EVENT_ERROR; | ||
| 1076 | } | ||
| 1077 | |||
| 1049 | static int get_op_prio(char *op) | 1078 | static int get_op_prio(char *op) |
| 1050 | { | 1079 | { |
| 1051 | if (!op[1]) { | 1080 | if (!op[1]) { |
| @@ -1192,6 +1221,18 @@ process_op(struct event *event, struct print_arg *arg, char **tok) | |||
| 1192 | 1221 | ||
| 1193 | arg->op.right = right; | 1222 | arg->op.right = right; |
| 1194 | 1223 | ||
| 1224 | } else if (strcmp(token, "[") == 0) { | ||
| 1225 | |||
| 1226 | left = malloc_or_die(sizeof(*left)); | ||
| 1227 | *left = *arg; | ||
| 1228 | |||
| 1229 | arg->type = PRINT_OP; | ||
| 1230 | arg->op.op = token; | ||
| 1231 | arg->op.left = left; | ||
| 1232 | |||
| 1233 | arg->op.prio = 0; | ||
| 1234 | type = process_array(event, arg, tok); | ||
| 1235 | |||
| 1195 | } else { | 1236 | } else { |
| 1196 | die("unknown op '%s'", token); | 1237 | die("unknown op '%s'", token); |
| 1197 | /* the arg is now the left side */ | 1238 | /* the arg is now the left side */ |
| @@ -1931,6 +1972,7 @@ static unsigned long long eval_num_arg(void *data, int size, | |||
| 1931 | { | 1972 | { |
| 1932 | unsigned long long val = 0; | 1973 | unsigned long long val = 0; |
| 1933 | unsigned long long left, right; | 1974 | unsigned long long left, right; |
| 1975 | struct print_arg *larg; | ||
| 1934 | 1976 | ||
| 1935 | switch (arg->type) { | 1977 | switch (arg->type) { |
| 1936 | case PRINT_NULL: | 1978 | case PRINT_NULL: |
| @@ -1957,6 +1999,26 @@ static unsigned long long eval_num_arg(void *data, int size, | |||
| 1957 | return 0; | 1999 | return 0; |
| 1958 | break; | 2000 | break; |
| 1959 | case PRINT_OP: | 2001 | case PRINT_OP: |
| 2002 | if (strcmp(arg->op.op, "[") == 0) { | ||
| 2003 | /* | ||
| 2004 | * Arrays are special, since we don't want | ||
| 2005 | * to read the arg as is. | ||
| 2006 | */ | ||
| 2007 | if (arg->op.left->type != PRINT_FIELD) | ||
| 2008 | goto default_op; /* oops, all bets off */ | ||
| 2009 | larg = arg->op.left; | ||
| 2010 | if (!larg->field.field) { | ||
| 2011 | larg->field.field = | ||
| 2012 | find_any_field(event, larg->field.name); | ||
| 2013 | if (!larg->field.field) | ||
| 2014 | die("field %s not found", larg->field.name); | ||
| 2015 | } | ||
| 2016 | right = eval_num_arg(data, size, event, arg->op.right); | ||
| 2017 | val = read_size(data + larg->field.field->offset + | ||
| 2018 | right * long_size, long_size); | ||
| 2019 | break; | ||
| 2020 | } | ||
| 2021 | default_op: | ||
| 1960 | left = eval_num_arg(data, size, event, arg->op.left); | 2022 | left = eval_num_arg(data, size, event, arg->op.left); |
| 1961 | right = eval_num_arg(data, size, event, arg->op.right); | 2023 | right = eval_num_arg(data, size, event, arg->op.right); |
| 1962 | switch (arg->op.op[0]) { | 2024 | switch (arg->op.op[0]) { |
