mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 13:11:45 +00:00
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>
This commit is contained in:
parent
298ebc3ef2
commit
0959b8d65c
@ -1046,6 +1046,35 @@ out_free:
|
||||
return EVENT_ERROR;
|
||||
}
|
||||
|
||||
static enum event_type
|
||||
process_array(struct event *event, struct print_arg *top, char **tok)
|
||||
{
|
||||
struct print_arg *arg;
|
||||
enum event_type type;
|
||||
char *token = NULL;
|
||||
|
||||
arg = malloc_or_die(sizeof(*arg));
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
*tok = NULL;
|
||||
type = process_arg(event, arg, &token);
|
||||
if (test_type_token(type, token, EVENT_OP, (char *)"]"))
|
||||
goto out_free;
|
||||
|
||||
top->op.right = arg;
|
||||
|
||||
free_token(token);
|
||||
type = read_token_item(&token);
|
||||
*tok = token;
|
||||
|
||||
return type;
|
||||
|
||||
out_free:
|
||||
free_token(*tok);
|
||||
free_arg(arg);
|
||||
return EVENT_ERROR;
|
||||
}
|
||||
|
||||
static int get_op_prio(char *op)
|
||||
{
|
||||
if (!op[1]) {
|
||||
@ -1192,6 +1221,18 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
|
||||
|
||||
arg->op.right = right;
|
||||
|
||||
} else if (strcmp(token, "[") == 0) {
|
||||
|
||||
left = malloc_or_die(sizeof(*left));
|
||||
*left = *arg;
|
||||
|
||||
arg->type = PRINT_OP;
|
||||
arg->op.op = token;
|
||||
arg->op.left = left;
|
||||
|
||||
arg->op.prio = 0;
|
||||
type = process_array(event, arg, tok);
|
||||
|
||||
} else {
|
||||
die("unknown op '%s'", token);
|
||||
/* the arg is now the left side */
|
||||
@ -1931,6 +1972,7 @@ static unsigned long long eval_num_arg(void *data, int size,
|
||||
{
|
||||
unsigned long long val = 0;
|
||||
unsigned long long left, right;
|
||||
struct print_arg *larg;
|
||||
|
||||
switch (arg->type) {
|
||||
case PRINT_NULL:
|
||||
@ -1957,6 +1999,26 @@ static unsigned long long eval_num_arg(void *data, int size,
|
||||
return 0;
|
||||
break;
|
||||
case PRINT_OP:
|
||||
if (strcmp(arg->op.op, "[") == 0) {
|
||||
/*
|
||||
* Arrays are special, since we don't want
|
||||
* to read the arg as is.
|
||||
*/
|
||||
if (arg->op.left->type != PRINT_FIELD)
|
||||
goto default_op; /* oops, all bets off */
|
||||
larg = arg->op.left;
|
||||
if (!larg->field.field) {
|
||||
larg->field.field =
|
||||
find_any_field(event, larg->field.name);
|
||||
if (!larg->field.field)
|
||||
die("field %s not found", larg->field.name);
|
||||
}
|
||||
right = eval_num_arg(data, size, event, arg->op.right);
|
||||
val = read_size(data + larg->field.field->offset +
|
||||
right * long_size, long_size);
|
||||
break;
|
||||
}
|
||||
default_op:
|
||||
left = eval_num_arg(data, size, event, arg->op.left);
|
||||
right = eval_num_arg(data, size, event, arg->op.right);
|
||||
switch (arg->op.op[0]) {
|
||||
|
Loading…
Reference in New Issue
Block a user