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 | |
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>
-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]) { |