Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0959b8d6 authored by Steven Rostedt's avatar Steven Rostedt Committed by Ingo Molnar
Browse files

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: default avatarSteven 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: default avatarIngo Molnar <mingo@elte.hu>
parent 298ebc3e
Loading
Loading
Loading
Loading
+62 −0
Original line number Original line Diff line number Diff line
@@ -1046,6 +1046,35 @@ process_cond(struct event *event, struct print_arg *top, char **tok)
	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]) {