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:
committed by
Ingo Molnar
parent
298ebc3ef2
commit
0959b8d65c
@@ -1046,6 +1046,35 @@ out_free:
|
|||||||
return EVENT_ERROR;
|
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)
|
static int get_op_prio(char *op)
|
||||||
{
|
{
|
||||||
if (!op[1]) {
|
if (!op[1]) {
|
||||||
@@ -1192,6 +1221,18 @@ process_op(struct event *event, struct print_arg *arg, char **tok)
|
|||||||
|
|
||||||
arg->op.right = right;
|
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 {
|
} else {
|
||||||
die("unknown op '%s'", token);
|
die("unknown op '%s'", token);
|
||||||
/* the arg is now the left side */
|
/* 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 val = 0;
|
||||||
unsigned long long left, right;
|
unsigned long long left, right;
|
||||||
|
struct print_arg *larg;
|
||||||
|
|
||||||
switch (arg->type) {
|
switch (arg->type) {
|
||||||
case PRINT_NULL:
|
case PRINT_NULL:
|
||||||
@@ -1957,6 +1999,26 @@ static unsigned long long eval_num_arg(void *data, int size,
|
|||||||
return 0;
|
return 0;
|
||||||
break;
|
break;
|
||||||
case PRINT_OP:
|
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);
|
left = eval_num_arg(data, size, event, arg->op.left);
|
||||||
right = eval_num_arg(data, size, event, arg->op.right);
|
right = eval_num_arg(data, size, event, arg->op.right);
|
||||||
switch (arg->op.op[0]) {
|
switch (arg->op.op[0]) {
|
||||||
|
Reference in New Issue
Block a user