All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] trace-cmd: Add parse error checking target
@ 2011-07-16  3:00 Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
                   ` (4 more replies)
  0 siblings, 5 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-16  3:00 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

Add another target 'check-events' which parses all the event formats and
returns whether there are any issues with the print format strings.

With an error in the format, the return value is 22 (EINVAL) and for
success, it is 0.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
 trace-capture.c |    2 +-
 trace-cmd.c     |   22 ++++++++++++++++++++++
 trace-cmd.h     |    2 +-
 trace-usage.c   |    5 +++++
 trace-util.c    |   48 ++++++++++++++++++++++++++++++++----------------
 5 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/trace-capture.c b/trace-capture.c
index 61ff165..5708945 100644
--- a/trace-capture.c
+++ b/trace-capture.c
@@ -1295,7 +1295,7 @@ static void tracing_dialog(struct shark_info *info, const char *tracing)
 	/* Send parse warnings to status display */
 	trace_dialog_register_alt_warning(vpr_stat);
 
-	pevent = tracecmd_local_events(tracing);
+	tracecmd_local_events(tracing, &pevent);
 	trace_dialog_register_alt_warning(NULL);
 
 	cap.pevent = pevent;
diff --git a/trace-cmd.c b/trace-cmd.c
index bff5bbf..a2b6b91 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -158,6 +158,28 @@ int main (int argc, char **argv)
 	} else if (strcmp(argv[1], "stack") == 0) {
 		trace_stack(argc, argv);
 		exit(0);
+	} else if (strcmp(argv[1], "check-events") == 0) {
+		char *tracing;
+		int ret;
+		struct pevent *pevent = NULL;
+
+		tracing = tracecmd_find_tracing_dir();
+
+		if (!tracing) {
+			printf("Can not find or mount tracing directory!\n"
+				"Either tracing is not configured for this "
+				"kernel\n"
+				"or you do not have the proper permissions to "
+				"mount the directory");
+			exit(EINVAL);
+		}
+
+		ret = tracecmd_local_events(tracing, &pevent);
+		if (pevent)
+			pevent_free(pevent);
+
+		ret ? exit(0) : exit(EINVAL);
+
 	} else if (strcmp(argv[1], "record") == 0 ||
 		   strcmp(argv[1], "start") == 0 ||
 		   strcmp(argv[1], "extract") == 0 ||
diff --git a/trace-cmd.h b/trace-cmd.h
index f436845..6aa4744 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -37,7 +37,7 @@ void tracecmd_unload_plugins(struct plugin_list *list);
 
 char **tracecmd_event_systems(const char *tracing_dir);
 char **tracecmd_system_events(const char *tracing_dir, const char *system);
-struct pevent *tracecmd_local_events(const char *tracing_dir);
+int tracecmd_local_events(const char *tracing_dir, struct pevent **event);
 char **tracecmd_local_plugins(const char *tracing_dir);
 
 char **tracecmd_add_list(char **list, const char *name, int len);
diff --git a/trace-usage.c b/trace-usage.c
index 39c8fc1..58ef167 100644
--- a/trace-usage.c
+++ b/trace-usage.c
@@ -150,6 +150,11 @@ static struct usage_help usage_help[] = {
 		"          --reset  reset the maximum stack found\n"
 	},
 	{
+		"check-events",
+		"parse trace event formats",
+		" %s check-format\n"
+	},
+	{
 		NULL, NULL, NULL
 	}
 };
diff --git a/trace-util.c b/trace-util.c
index 674f37e..91ec5a7 100644
--- a/trace-util.c
+++ b/trace-util.c
@@ -621,22 +621,22 @@ static int read_file(const char *file, char **buffer)
 	return len;
 }
 
-static void load_events(struct pevent *pevent, const char *system,
+static int load_events(struct pevent *pevent, const char *system,
 			const char *sys_dir)
 {
 	struct dirent *dent;
 	struct stat st;
 	DIR *dir;
 	int len = 0;
-	int ret;
+	int ret = 0, failure = 0;
 
 	ret = stat(sys_dir, &st);
 	if (ret < 0 || !S_ISDIR(st.st_mode))
-		return;
+		return EINVAL;
 
 	dir = opendir(sys_dir);
 	if (!dir)
-		return;
+		return errno;
 
 	while ((dent = readdir(dir))) {
 		const char *name = dent->d_name;
@@ -662,15 +662,18 @@ static void load_events(struct pevent *pevent, const char *system,
 		if (len < 0)
 			goto free_format;
 
-		pevent_parse_event(pevent, buf, len, system);
+		ret = pevent_parse_event(pevent, buf, len, system);
 		free(buf);
  free_format:
 		free(format);
  free_event:
 		free(event);
+		if (ret)
+			failure = ret;
 	}
 
 	closedir(dir);
+	return failure;
 }
 
 static int read_header(struct pevent *pevent, const char *events_dir)
@@ -704,42 +707,50 @@ static int read_header(struct pevent *pevent, const char *events_dir)
 /**
  * tracecmd_local_events - create a pevent from the events on system
  * @tracing_dir: The directory that contains the events.
+ * @event: The pointer where the list of parsed events will be returned
  *
- * Returns a pevent structure that contains the pevents local to
- * the system.
+ * Returns an int indicating if the parsing was without any errors. Success is
+ * 1.
  */
-struct pevent *tracecmd_local_events(const char *tracing_dir)
+int tracecmd_local_events(const char *tracing_dir, struct pevent **event)
 {
 	struct pevent *pevent = NULL;
 	struct dirent *dent;
 	char *events_dir;
 	struct stat st;
 	DIR *dir;
-	int ret;
+	int ret, failure = 0;
 
 	if (!tracing_dir)
-		return NULL;
+		return 0;
 
 	events_dir = append_file(tracing_dir, "events");
 	if (!events_dir)
-		return NULL;
+		return 0;
 
 	ret = stat(events_dir, &st);
-	if (ret < 0 || !S_ISDIR(st.st_mode))
+	if (ret < 0 || !S_ISDIR(st.st_mode)) {
+		failure = 1;
 		goto out_free;
+	}
 
 	dir = opendir(events_dir);
-	if (!dir)
+	if (!dir) {
+		failure = 1;
 		goto out_free;
+	}
 
 	pevent = pevent_alloc();
-	if (!pevent)
+	if (!pevent) {
+		failure = 1;
 		goto out_free;
+	}
 
 	ret = read_header(pevent, events_dir);
 	if (ret < 0) {
 		pevent_free(pevent);
 		pevent = NULL;
+		failure = 1;
 		goto out_free;
 	}
 
@@ -758,9 +769,12 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
 			continue;
 		}
 
-		load_events(pevent, name, sys);
+		ret = load_events(pevent, name, sys);
 
 		free(sys);
+
+		if (ret)
+			failure = 1;
 	}
 
 	closedir(dir);
@@ -768,7 +782,9 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
  out_free:
 	free(events_dir);
 
-	return pevent;
+	*event = pevent;
+
+	return !failure;
 }
 
 /**
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully
  2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
@ 2011-07-16  3:00 ` Vaibhav Nagarnaik
  2011-07-25 14:03   ` Steven Rostedt
  2012-05-21  9:39   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 3/4] trace-cmd: Handle opcode parsing error Vaibhav Nagarnaik
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-16  3:00 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

If an invalid opcode is encountered, trace-cmd exits with an error.
Instead it can be treated as a soft error where the event's print format
is not parsed and its binary data is dumped out.

This patch adds a return value to arg_num_eval() function to indicate if
the parsing was successful. If not, then the error is considered soft
and the parsing of the offending event fails.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
 parse-events.c |  125 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 83 insertions(+), 42 deletions(-)

diff --git a/parse-events.c b/parse-events.c
index d8f322a..58ffe51 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -1901,90 +1901,120 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer)
 	return eval_type_str(val, arg->typecast.type, pointer);
 }
 
-static long long arg_num_eval(struct print_arg *arg)
+static int arg_num_eval(struct print_arg *arg, long long *val)
 {
 	long long left, right;
-	long long val = 0;
+	int ret = 1;
 
 	switch (arg->type) {
 	case PRINT_ATOM:
-		val = strtoll(arg->atom.atom, NULL, 0);
+		*val = strtoll(arg->atom.atom, NULL, 0);
 		break;
 	case PRINT_TYPE:
-		val = arg_num_eval(arg->typecast.item);
-		val = eval_type(val, arg, 0);
+		ret = arg_num_eval(arg->typecast.item, val);
+		if (!ret)
+			break;
+		*val = eval_type(*val, arg, 0);
 		break;
 	case PRINT_OP:
 		switch (arg->op.op[0]) {
 		case '|':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			if (arg->op.op[1])
-				val = left || right;
+				*val = left || right;
 			else
-				val = left | right;
+				*val = left | right;
 			break;
 		case '&':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			if (arg->op.op[1])
-				val = left && right;
+				*val = left && right;
 			else
-				val = left & right;
+				*val = left & right;
 			break;
 		case '<':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			switch (arg->op.op[1]) {
 			case 0:
-				val = left < right;
+				*val = left < right;
 				break;
 			case '<':
-				val = left << right;
+				*val = left << right;
 				break;
 			case '=':
-				val = left <= right;
+				*val = left <= right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '>':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			switch (arg->op.op[1]) {
 			case 0:
-				val = left > right;
+				*val = left > right;
 				break;
 			case '>':
-				val = left >> right;
+				*val = left >> right;
 				break;
 			case '=':
-				val = left >= right;
+				*val = left >= right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '=':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
-
-			if (arg->op.op[1] != '=')
-				die("unknown op '%s'", arg->op.op);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 
-			val = left == right;
+			if (arg->op.op[1] != '=') {
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
+			} else
+				*val = left == right;
 			break;
 		case '!':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 
 			switch (arg->op.op[1]) {
 			case '=':
-				val = left != right;
+				*val = left != right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '-':
@@ -1992,12 +2022,17 @@ static long long arg_num_eval(struct print_arg *arg)
 			if (arg->op.left->type == PRINT_NULL)
 				left = 0;
 			else
-				left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
-			val = left - right;
+				ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
+			*val = left - right;
 			break;
 		default:
-			die("unknown op '%s'", arg->op.op);
+			do_warning("unknown op '%s'", arg->op.op);
+			ret = 0;
 		}
 		break;
 
@@ -2006,10 +2041,11 @@ static long long arg_num_eval(struct print_arg *arg)
 	case PRINT_STRING:
 	case PRINT_BSTRING:
 	default:
-		die("invalid eval type %d", arg->type);
+		do_warning("invalid eval type %d", arg->type);
+		ret = 0;
 
 	}
-	return val;
+	return ret;
 }
 
 static char *arg_eval (struct print_arg *arg)
@@ -2023,7 +2059,8 @@ static char *arg_eval (struct print_arg *arg)
 	case PRINT_TYPE:
 		return arg_eval(arg->typecast.item);
 	case PRINT_OP:
-		val = arg_num_eval(arg);
+		if (!arg_num_eval(arg, &val))
+			break;
 		sprintf(buf, "%lld", val);
 		return buf;
 
@@ -2065,6 +2102,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
 		memset(field, 0, sizeof(field));
 
 		value = arg_eval(arg);
+		if (value == NULL)
+			goto out_free;
 		field->value = strdup(value);
 
 		free_arg(arg);
@@ -2076,6 +2115,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
 			goto out_free;
 
 		value = arg_eval(arg);
+		if (value == NULL)
+			goto out_free;
 		field->str = strdup(value);
 		free_arg(arg);
 		arg = NULL;
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/4] trace-cmd: Handle opcode parsing error
  2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
@ 2011-07-16  3:00 ` Vaibhav Nagarnaik
  2011-07-25 14:01   ` Steven Rostedt
  2011-07-25 18:40   ` Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 4/4] trace-cmd: Support '+' opcode in print format Vaibhav Nagarnaik
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-16  3:00 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

If an invalid opcode is encountered in parsing event print format, the
trace-cmd calls exit() without parsing any other events.

This patch adds handling for such an error where the get_op_prio() is
called. If the return value is -1, then the event print format parsing
is skipped and parsing continues.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
 parse-events.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/parse-events.c b/parse-events.c
index 58ffe51..068c77f 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -1588,7 +1588,7 @@ static int get_op_prio(char *op)
 		case '?':
 			return 16;
 		default:
-			die("unknown op '%c'", op[0]);
+			do_warning("unknown op '%c'", op[0]);
 			return -1;
 		}
 	} else {
@@ -1609,22 +1609,22 @@ static int get_op_prio(char *op)
 		} else if (strcmp(op, "||") == 0) {
 			return 15;
 		} else {
-			die("unknown op '%s'", op);
+			do_warning("unknown op '%s'", op);
 			return -1;
 		}
 	}
 }
 
-static void set_op_prio(struct print_arg *arg)
+static int set_op_prio(struct print_arg *arg)
 {
 
 	/* single ops are the greatest */
-	if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
+	if (!arg->op.left || arg->op.left->type == PRINT_NULL)
 		arg->op.prio = 0;
-		return;
-	}
+	else
+		arg->op.prio = get_op_prio(arg->op.op);
 
-	arg->op.prio = get_op_prio(arg->op.op);
+	return arg->op.prio;
 }
 
 /* Note, *tok does not get freed, but will most likely be saved */
@@ -1706,7 +1706,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 		arg->op.op = token;
 		arg->op.left = left;
 
-		set_op_prio(arg);
+		if (-1 == set_op_prio(arg)) {
+			event->flags |= EVENT_FL_FAILED;
+			goto out_free;
+		}
 
 		type = read_token_item(&token);
 		*tok = token;
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 4/4] trace-cmd: Support '+' opcode in print format
  2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
  2011-07-16  3:00 ` [PATCH 3/4] trace-cmd: Handle opcode parsing error Vaibhav Nagarnaik
@ 2011-07-16  3:00 ` Vaibhav Nagarnaik
  2011-07-25 14:02   ` Steven Rostedt
  2012-05-21  9:41   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
  2011-07-25 13:32 ` [PATCH 1/4] trace-cmd: Add parse error checking target Steven Rostedt
  2011-07-25 18:39 ` [PATCH v2 " Vaibhav Nagarnaik
  4 siblings, 2 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-16  3:00 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

The '+' opcode is not supported in the arguments for the print format.
This patch adds support for it.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
 parse-events.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/parse-events.c b/parse-events.c
index 068c77f..2e39415 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -2033,6 +2033,18 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
 				break;
 			*val = left - right;
 			break;
+		case '+':
+			if (arg->op.left->type == PRINT_NULL)
+				left = 0;
+			else
+				ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
+			*val = left + right;
+			break;
 		default:
 			do_warning("unknown op '%s'", arg->op.op);
 			ret = 0;
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/4] trace-cmd: Add parse error checking target
  2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
                   ` (2 preceding siblings ...)
  2011-07-16  3:00 ` [PATCH 4/4] trace-cmd: Support '+' opcode in print format Vaibhav Nagarnaik
@ 2011-07-25 13:32 ` Steven Rostedt
  2011-07-25 18:06   ` Vaibhav Nagarnaik
  2011-07-25 18:39 ` [PATCH v2 " Vaibhav Nagarnaik
  4 siblings, 1 reply; 20+ messages in thread
From: Steven Rostedt @ 2011-07-25 13:32 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
> Add another target 'check-events' which parses all the event formats and
> returns whether there are any issues with the print format strings.
> 
> With an error in the format, the return value is 22 (EINVAL) and for
> success, it is 0.
> 
> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
> ---
>  trace-capture.c |    2 +-
>  trace-cmd.c     |   22 ++++++++++++++++++++++
>  trace-cmd.h     |    2 +-
>  trace-usage.c   |    5 +++++
>  trace-util.c    |   48 ++++++++++++++++++++++++++++++++----------------
>  5 files changed, 61 insertions(+), 18 deletions(-)
> 
> diff --git a/trace-capture.c b/trace-capture.c
> index 61ff165..5708945 100644
> --- a/trace-capture.c
> +++ b/trace-capture.c
> @@ -1295,7 +1295,7 @@ static void tracing_dialog(struct shark_info *info, const char *tracing)
>  	/* Send parse warnings to status display */
>  	trace_dialog_register_alt_warning(vpr_stat);
>  
> -	pevent = tracecmd_local_events(tracing);
> +	tracecmd_local_events(tracing, &pevent);

Ug, please no. I don't see any good reason to move the creation of a
pevent into a pointer than just return it. If you require a different
return code, or (a even better reason) that this may be called without
needing to create a pevent at all, then I can understand this. But
creating an object (sturcture) by passing its address is an anomaly of C
and I like to avoid when possible. Passing an address of a atom value
(int, long) or even maybe a string that is allocated is one thing. But
doing it with a constructor function is just plain ugly.


>  	trace_dialog_register_alt_warning(NULL);
>  
>  	cap.pevent = pevent;
> diff --git a/trace-cmd.c b/trace-cmd.c
> index bff5bbf..a2b6b91 100644
> --- a/trace-cmd.c
> +++ b/trace-cmd.c
> @@ -158,6 +158,28 @@ int main (int argc, char **argv)
>  	} else if (strcmp(argv[1], "stack") == 0) {
>  		trace_stack(argc, argv);
>  		exit(0);
> +	} else if (strcmp(argv[1], "check-events") == 0) {
> +		char *tracing;
> +		int ret;
> +		struct pevent *pevent = NULL;
> +
> +		tracing = tracecmd_find_tracing_dir();
> +
> +		if (!tracing) {
> +			printf("Can not find or mount tracing directory!\n"
> +				"Either tracing is not configured for this "
> +				"kernel\n"
> +				"or you do not have the proper permissions to "
> +				"mount the directory");
> +			exit(EINVAL);
> +		}
> +
> +		ret = tracecmd_local_events(tracing, &pevent);
> +		if (pevent)
> +			pevent_free(pevent);
> +
> +		ret ? exit(0) : exit(EINVAL);
> +

And here the code is even uglier. You just free pevent and the ret is
just a boolean!  Also, that ?: trick is even uglier.


		pevent = tracecmd_local_events(tracing);
		if (!pevent)
			exit(EINVAL);
		pevent_free(pevent);
		exit(0);

Is much more readable.

-- Steve





^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/4] trace-cmd: Handle opcode parsing error
  2011-07-16  3:00 ` [PATCH 3/4] trace-cmd: Handle opcode parsing error Vaibhav Nagarnaik
@ 2011-07-25 14:01   ` Steven Rostedt
  2011-07-25 18:06     ` Vaibhav Nagarnaik
  2011-07-25 18:40   ` Vaibhav Nagarnaik
  1 sibling, 1 reply; 20+ messages in thread
From: Steven Rostedt @ 2011-07-25 14:01 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
>  
>  /* Note, *tok does not get freed, but will most likely be saved */
> @@ -1706,7 +1706,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
>  		arg->op.op = token;
>  		arg->op.left = left;
>  
> -		set_op_prio(arg);
> +		if (-1 == set_op_prio(arg)) {

I'm fine with the patch up to here. I understand the constant first
compare, but it doesn't make sense here. Either use:

	if (set_op_prio(arg) < 0) ...
 or
	if (set_op_prio(arg) == -1)...


The reason the -1 == doesn't make sense is because:

	if (set_op_proi(arg) = -1)

would fail too.

And it is much easier to read.

-- Steve

> +			event->flags |= EVENT_FL_FAILED;
> +			goto out_free;
> +		}
>  
>  		type = read_token_item(&token);
>  		*tok = token;



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] trace-cmd: Support '+' opcode in print format
  2011-07-16  3:00 ` [PATCH 4/4] trace-cmd: Support '+' opcode in print format Vaibhav Nagarnaik
@ 2011-07-25 14:02   ` Steven Rostedt
  2012-05-21  9:41   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
  1 sibling, 0 replies; 20+ messages in thread
From: Steven Rostedt @ 2011-07-25 14:02 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
> The '+' opcode is not supported in the arguments for the print format.
> This patch adds support for it.

Thanks! This was on my todo list.

-- Steve

> 
> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
> ---
>  parse-events.c |   12 ++++++++++++
>  1 files changed, 12 insertions(+), 0 deletions(-)
> 
> diff --git a/parse-events.c b/parse-events.c
> index 068c77f..2e39415 100644
> --- a/parse-events.c
> +++ b/parse-events.c
> @@ -2033,6 +2033,18 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
>  				break;
>  			*val = left - right;
>  			break;
> +		case '+':
> +			if (arg->op.left->type == PRINT_NULL)
> +				left = 0;
> +			else
> +				ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
> +			*val = left + right;
> +			break;
>  		default:
>  			do_warning("unknown op '%s'", arg->op.op);
>  			ret = 0;



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully
  2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
@ 2011-07-25 14:03   ` Steven Rostedt
  2012-05-21  9:39   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
  1 sibling, 0 replies; 20+ messages in thread
From: Steven Rostedt @ 2011-07-25 14:03 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
> If an invalid opcode is encountered, trace-cmd exits with an error.
> Instead it can be treated as a soft error where the event's print format
> is not parsed and its binary data is dumped out.
> 
> This patch adds a return value to arg_num_eval() function to indicate if
> the parsing was successful. If not, then the error is considered soft
> and the parsing of the offending event fails.
> 
> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>

Thanks Vaibhav, applied!

-- Steve

> ---
>  parse-events.c |  125 +++++++++++++++++++++++++++++++++++++-------------------
>  1 files changed, 83 insertions(+), 42 deletions(-)
> 
> diff --git a/parse-events.c b/parse-events.c
> index d8f322a..58ffe51 100644
> --- a/parse-events.c
> +++ b/parse-events.c
> @@ -1901,90 +1901,120 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer)
>  	return eval_type_str(val, arg->typecast.type, pointer);
>  }
>  
> -static long long arg_num_eval(struct print_arg *arg)
> +static int arg_num_eval(struct print_arg *arg, long long *val)
>  {
>  	long long left, right;
> -	long long val = 0;
> +	int ret = 1;
>  
>  	switch (arg->type) {
>  	case PRINT_ATOM:
> -		val = strtoll(arg->atom.atom, NULL, 0);
> +		*val = strtoll(arg->atom.atom, NULL, 0);
>  		break;
>  	case PRINT_TYPE:
> -		val = arg_num_eval(arg->typecast.item);
> -		val = eval_type(val, arg, 0);
> +		ret = arg_num_eval(arg->typecast.item, val);
> +		if (!ret)
> +			break;
> +		*val = eval_type(*val, arg, 0);
>  		break;
>  	case PRINT_OP:
>  		switch (arg->op.op[0]) {
>  		case '|':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  			if (arg->op.op[1])
> -				val = left || right;
> +				*val = left || right;
>  			else
> -				val = left | right;
> +				*val = left | right;
>  			break;
>  		case '&':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  			if (arg->op.op[1])
> -				val = left && right;
> +				*val = left && right;
>  			else
> -				val = left & right;
> +				*val = left & right;
>  			break;
>  		case '<':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  			switch (arg->op.op[1]) {
>  			case 0:
> -				val = left < right;
> +				*val = left < right;
>  				break;
>  			case '<':
> -				val = left << right;
> +				*val = left << right;
>  				break;
>  			case '=':
> -				val = left <= right;
> +				*val = left <= right;
>  				break;
>  			default:
> -				die("unknown op '%s'", arg->op.op);
> +				do_warning("unknown op '%s'", arg->op.op);
> +				ret = 0;
>  			}
>  			break;
>  		case '>':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  			switch (arg->op.op[1]) {
>  			case 0:
> -				val = left > right;
> +				*val = left > right;
>  				break;
>  			case '>':
> -				val = left >> right;
> +				*val = left >> right;
>  				break;
>  			case '=':
> -				val = left >= right;
> +				*val = left >= right;
>  				break;
>  			default:
> -				die("unknown op '%s'", arg->op.op);
> +				do_warning("unknown op '%s'", arg->op.op);
> +				ret = 0;
>  			}
>  			break;
>  		case '=':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> -
> -			if (arg->op.op[1] != '=')
> -				die("unknown op '%s'", arg->op.op);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  
> -			val = left == right;
> +			if (arg->op.op[1] != '=') {
> +				do_warning("unknown op '%s'", arg->op.op);
> +				ret = 0;
> +			} else
> +				*val = left == right;
>  			break;
>  		case '!':
> -			left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> +			ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
>  
>  			switch (arg->op.op[1]) {
>  			case '=':
> -				val = left != right;
> +				*val = left != right;
>  				break;
>  			default:
> -				die("unknown op '%s'", arg->op.op);
> +				do_warning("unknown op '%s'", arg->op.op);
> +				ret = 0;
>  			}
>  			break;
>  		case '-':
> @@ -1992,12 +2022,17 @@ static long long arg_num_eval(struct print_arg *arg)
>  			if (arg->op.left->type == PRINT_NULL)
>  				left = 0;
>  			else
> -				left = arg_num_eval(arg->op.left);
> -			right = arg_num_eval(arg->op.right);
> -			val = left - right;
> +				ret = arg_num_eval(arg->op.left, &left);
> +			if (!ret)
> +				break;
> +			ret = arg_num_eval(arg->op.right, &right);
> +			if (!ret)
> +				break;
> +			*val = left - right;
>  			break;
>  		default:
> -			die("unknown op '%s'", arg->op.op);
> +			do_warning("unknown op '%s'", arg->op.op);
> +			ret = 0;
>  		}
>  		break;
>  
> @@ -2006,10 +2041,11 @@ static long long arg_num_eval(struct print_arg *arg)
>  	case PRINT_STRING:
>  	case PRINT_BSTRING:
>  	default:
> -		die("invalid eval type %d", arg->type);
> +		do_warning("invalid eval type %d", arg->type);
> +		ret = 0;
>  
>  	}
> -	return val;
> +	return ret;
>  }
>  
>  static char *arg_eval (struct print_arg *arg)
> @@ -2023,7 +2059,8 @@ static char *arg_eval (struct print_arg *arg)
>  	case PRINT_TYPE:
>  		return arg_eval(arg->typecast.item);
>  	case PRINT_OP:
> -		val = arg_num_eval(arg);
> +		if (!arg_num_eval(arg, &val))
> +			break;
>  		sprintf(buf, "%lld", val);
>  		return buf;
>  
> @@ -2065,6 +2102,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
>  		memset(field, 0, sizeof(field));
>  
>  		value = arg_eval(arg);
> +		if (value == NULL)
> +			goto out_free;
>  		field->value = strdup(value);
>  
>  		free_arg(arg);
> @@ -2076,6 +2115,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
>  			goto out_free;
>  
>  		value = arg_eval(arg);
> +		if (value == NULL)
> +			goto out_free;
>  		field->str = strdup(value);
>  		free_arg(arg);
>  		arg = NULL;



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/4] trace-cmd: Add parse error checking target
  2011-07-25 13:32 ` [PATCH 1/4] trace-cmd: Add parse error checking target Steven Rostedt
@ 2011-07-25 18:06   ` Vaibhav Nagarnaik
  0 siblings, 0 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-25 18:06 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Michael Rubin, David Sharp, linux-kernel

On Mon, Jul 25, 2011 at 6:32 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
>> Add another target 'check-events' which parses all the event formats and
>> returns whether there are any issues with the print format strings.
>>
>> With an error in the format, the return value is 22 (EINVAL) and for
>> success, it is 0.
>>
>> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
>> ---
>>  trace-capture.c |    2 +-
>>  trace-cmd.c     |   22 ++++++++++++++++++++++
>>  trace-cmd.h     |    2 +-
>>  trace-usage.c   |    5 +++++
>>  trace-util.c    |   48 ++++++++++++++++++++++++++++++++----------------
>>  5 files changed, 61 insertions(+), 18 deletions(-)
>>
>> diff --git a/trace-capture.c b/trace-capture.c
>> index 61ff165..5708945 100644
>> --- a/trace-capture.c
>> +++ b/trace-capture.c
>> @@ -1295,7 +1295,7 @@ static void tracing_dialog(struct shark_info *info, const char *tracing)
>>       /* Send parse warnings to status display */
>>       trace_dialog_register_alt_warning(vpr_stat);
>>
>> -     pevent = tracecmd_local_events(tracing);
>> +     tracecmd_local_events(tracing, &pevent);
>
> Ug, please no. I don't see any good reason to move the creation of a
> pevent into a pointer than just return it. If you require a different
> return code, or (a even better reason) that this may be called without
> needing to create a pevent at all, then I can understand this. But
> creating an object (sturcture) by passing its address is an anomaly of C
> and I like to avoid when possible. Passing an address of a atom value
> (int, long) or even maybe a string that is allocated is one thing. But
> doing it with a constructor function is just plain ugly.

I agree it is ugly, but I wanted to preserve the legacy behavior where
even with parsing failures, tracecmd_local_events() returns a filled in
parsed events. This is the easiest way to return a filled in pevent and
indicate whether there were *any* parsing failures.

Now that I think about it, I can add the boolean in the returned pevent
structure to have the same effect and keep the same constructor
signature. I will send the updated patch in a moment.

>
>
>>       trace_dialog_register_alt_warning(NULL);
>>
>>       cap.pevent = pevent;
>> diff --git a/trace-cmd.c b/trace-cmd.c
>> index bff5bbf..a2b6b91 100644
>> --- a/trace-cmd.c
>> +++ b/trace-cmd.c
>> @@ -158,6 +158,28 @@ int main (int argc, char **argv)
>>       } else if (strcmp(argv[1], "stack") == 0) {
>>               trace_stack(argc, argv);
>>               exit(0);
>> +     } else if (strcmp(argv[1], "check-events") == 0) {
>> +             char *tracing;
>> +             int ret;
>> +             struct pevent *pevent = NULL;
>> +
>> +             tracing = tracecmd_find_tracing_dir();
>> +
>> +             if (!tracing) {
>> +                     printf("Can not find or mount tracing directory!\n"
>> +                             "Either tracing is not configured for this "
>> +                             "kernel\n"
>> +                             "or you do not have the proper permissions to "
>> +                             "mount the directory");
>> +                     exit(EINVAL);
>> +             }
>> +
>> +             ret = tracecmd_local_events(tracing, &pevent);
>> +             if (pevent)
>> +                     pevent_free(pevent);
>> +
>> +             ret ? exit(0) : exit(EINVAL);
>> +
>
> And here the code is even uglier. You just free pevent and the ret is
> just a boolean!  Also, that ?: trick is even uglier.
>
>
>                pevent = tracecmd_local_events(tracing);
>                if (!pevent)
>                        exit(EINVAL);
>                pevent_free(pevent);
>                exit(0);
>
> Is much more readable.
>
> -- Steve
>
>
>
>
>

Vaibhav Nagarnaik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 3/4] trace-cmd: Handle opcode parsing error
  2011-07-25 14:01   ` Steven Rostedt
@ 2011-07-25 18:06     ` Vaibhav Nagarnaik
  0 siblings, 0 replies; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-25 18:06 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Michael Rubin, David Sharp, linux-kernel

On Mon, Jul 25, 2011 at 7:01 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Fri, 2011-07-15 at 20:00 -0700, Vaibhav Nagarnaik wrote:
>>
>>  /* Note, *tok does not get freed, but will most likely be saved */
>> @@ -1706,7 +1706,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
>>               arg->op.op = token;
>>               arg->op.left = left;
>>
>> -             set_op_prio(arg);
>> +             if (-1 == set_op_prio(arg)) {
>
> I'm fine with the patch up to here. I understand the constant first
> compare, but it doesn't make sense here. Either use:
>
>        if (set_op_prio(arg) < 0) ...
>  or
>        if (set_op_prio(arg) == -1)...
>
>
> The reason the -1 == doesn't make sense is because:
>
>        if (set_op_proi(arg) = -1)
>
> would fail too.
>
> And it is much easier to read.
>
> -- Steve
>

Sure. I am sending the updated patch.

>> +                     event->flags |= EVENT_FL_FAILED;
>> +                     goto out_free;
>> +             }
>>
>>               type = read_token_item(&token);
>>               *tok = token;
>
>
>

Vaibhav Nagarnaik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
                   ` (3 preceding siblings ...)
  2011-07-25 13:32 ` [PATCH 1/4] trace-cmd: Add parse error checking target Steven Rostedt
@ 2011-07-25 18:39 ` Vaibhav Nagarnaik
  2011-07-29 14:19   ` Steven Rostedt
  4 siblings, 1 reply; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-25 18:39 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

Add another target 'check-events' which parses all the event formats and
returns whether there are any issues with the print format strings.

With an error in the format, the return value is 22 (EINVAL) and for
success, it is 0.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
Changelog v2-v1:
* Pass any parsing failures in pevent structure

 parse-events.h |    2 ++
 trace-cmd.c    |   25 +++++++++++++++++++++++++
 trace-usage.c  |    5 +++++
 trace-util.c   |   36 ++++++++++++++++++++++++++----------
 4 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/parse-events.h b/parse-events.h
index c32d715..f5cab15 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -402,6 +402,8 @@ struct pevent {
 	struct event_handler *handlers;
 	struct pevent_function_handler *func_handlers;
 
+	int parsing_failures;
+
 	/* cache */
 	struct event_format *last_event;
 };
diff --git a/trace-cmd.c b/trace-cmd.c
index bff5bbf..5cfd97f 100644
--- a/trace-cmd.c
+++ b/trace-cmd.c
@@ -158,6 +158,31 @@ int main (int argc, char **argv)
 	} else if (strcmp(argv[1], "stack") == 0) {
 		trace_stack(argc, argv);
 		exit(0);
+	} else if (strcmp(argv[1], "check-events") == 0) {
+		char *tracing;
+		int ret;
+		struct pevent *pevent = NULL;
+
+		tracing = tracecmd_find_tracing_dir();
+
+		if (!tracing) {
+			printf("Can not find or mount tracing directory!\n"
+				"Either tracing is not configured for this "
+				"kernel\n"
+				"or you do not have the proper permissions to "
+				"mount the directory");
+			exit(EINVAL);
+		}
+
+		ret = 0;
+		pevent = tracecmd_local_events(tracing);
+		if (!pevent)
+			exit(EINVAL);
+		if (pevent->parsing_failures)
+			ret = EINVAL;
+		pevent_free(pevent);
+		exit(ret);
+
 	} else if (strcmp(argv[1], "record") == 0 ||
 		   strcmp(argv[1], "start") == 0 ||
 		   strcmp(argv[1], "extract") == 0 ||
diff --git a/trace-usage.c b/trace-usage.c
index 39c8fc1..58ef167 100644
--- a/trace-usage.c
+++ b/trace-usage.c
@@ -150,6 +150,11 @@ static struct usage_help usage_help[] = {
 		"          --reset  reset the maximum stack found\n"
 	},
 	{
+		"check-events",
+		"parse trace event formats",
+		" %s check-format\n"
+	},
+	{
 		NULL, NULL, NULL
 	}
 };
diff --git a/trace-util.c b/trace-util.c
index 674f37e..01894f8 100644
--- a/trace-util.c
+++ b/trace-util.c
@@ -621,22 +621,22 @@ static int read_file(const char *file, char **buffer)
 	return len;
 }
 
-static void load_events(struct pevent *pevent, const char *system,
+static int load_events(struct pevent *pevent, const char *system,
 			const char *sys_dir)
 {
 	struct dirent *dent;
 	struct stat st;
 	DIR *dir;
 	int len = 0;
-	int ret;
+	int ret = 0, failure = 0;
 
 	ret = stat(sys_dir, &st);
 	if (ret < 0 || !S_ISDIR(st.st_mode))
-		return;
+		return EINVAL;
 
 	dir = opendir(sys_dir);
 	if (!dir)
-		return;
+		return errno;
 
 	while ((dent = readdir(dir))) {
 		const char *name = dent->d_name;
@@ -662,15 +662,18 @@ static void load_events(struct pevent *pevent, const char *system,
 		if (len < 0)
 			goto free_format;
 
-		pevent_parse_event(pevent, buf, len, system);
+		ret = pevent_parse_event(pevent, buf, len, system);
 		free(buf);
  free_format:
 		free(format);
  free_event:
 		free(event);
+		if (ret)
+			failure = ret;
 	}
 
 	closedir(dir);
+	return failure;
 }
 
 static int read_header(struct pevent *pevent, const char *events_dir)
@@ -715,7 +718,7 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
 	char *events_dir;
 	struct stat st;
 	DIR *dir;
-	int ret;
+	int ret, failure = 0;
 
 	if (!tracing_dir)
 		return NULL;
@@ -725,21 +728,28 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
 		return NULL;
 
 	ret = stat(events_dir, &st);
-	if (ret < 0 || !S_ISDIR(st.st_mode))
+	if (ret < 0 || !S_ISDIR(st.st_mode)) {
+		failure = 1;
 		goto out_free;
+	}
 
 	dir = opendir(events_dir);
-	if (!dir)
+	if (!dir) {
+		failure = 1;
 		goto out_free;
+	}
 
 	pevent = pevent_alloc();
-	if (!pevent)
+	if (!pevent) {
+		failure = 1;
 		goto out_free;
+	}
 
 	ret = read_header(pevent, events_dir);
 	if (ret < 0) {
 		pevent_free(pevent);
 		pevent = NULL;
+		failure = 1;
 		goto out_free;
 	}
 
@@ -758,9 +768,12 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
 			continue;
 		}
 
-		load_events(pevent, name, sys);
+		ret = load_events(pevent, name, sys);
 
 		free(sys);
+
+		if (ret)
+			failure = 1;
 	}
 
 	closedir(dir);
@@ -768,6 +781,9 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
  out_free:
 	free(events_dir);
 
+	if (pevent)
+		pevent->parsing_failures = failure;
+
 	return pevent;
 }
 
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 3/4] trace-cmd: Handle opcode parsing error
  2011-07-16  3:00 ` [PATCH 3/4] trace-cmd: Handle opcode parsing error Vaibhav Nagarnaik
  2011-07-25 14:01   ` Steven Rostedt
@ 2011-07-25 18:40   ` Vaibhav Nagarnaik
  2012-05-21  9:39     ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
  1 sibling, 1 reply; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-25 18:40 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Michael Rubin, David Sharp, linux-kernel, Vaibhav Nagarnaik

If an invalid opcode is encountered in parsing event print format, the
trace-cmd calls exit() without parsing any other events.

This patch adds handling for such an error where the get_op_prio() is
called. If the return value is -1, then the event print format parsing
is skipped and parsing continues.

Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
---
 parse-events.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/parse-events.c b/parse-events.c
index 58ffe51..c62ca5a 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -1588,7 +1588,7 @@ static int get_op_prio(char *op)
 		case '?':
 			return 16;
 		default:
-			die("unknown op '%c'", op[0]);
+			do_warning("unknown op '%c'", op[0]);
 			return -1;
 		}
 	} else {
@@ -1609,22 +1609,22 @@ static int get_op_prio(char *op)
 		} else if (strcmp(op, "||") == 0) {
 			return 15;
 		} else {
-			die("unknown op '%s'", op);
+			do_warning("unknown op '%s'", op);
 			return -1;
 		}
 	}
 }
 
-static void set_op_prio(struct print_arg *arg)
+static int set_op_prio(struct print_arg *arg)
 {
 
 	/* single ops are the greatest */
-	if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
+	if (!arg->op.left || arg->op.left->type == PRINT_NULL)
 		arg->op.prio = 0;
-		return;
-	}
+	else
+		arg->op.prio = get_op_prio(arg->op.op);
 
-	arg->op.prio = get_op_prio(arg->op.op);
+	return arg->op.prio;
 }
 
 /* Note, *tok does not get freed, but will most likely be saved */
@@ -1706,7 +1706,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 		arg->op.op = token;
 		arg->op.left = left;
 
-		set_op_prio(arg);
+		if (set_op_prio(arg) == -1) {
+			event->flags |= EVENT_FL_FAILED;
+			goto out_free;
+		}
 
 		type = read_token_item(&token);
 		*tok = token;
-- 
1.7.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-25 18:39 ` [PATCH v2 " Vaibhav Nagarnaik
@ 2011-07-29 14:19   ` Steven Rostedt
  2011-07-29 17:41     ` Vaibhav Nagarnaik
  0 siblings, 1 reply; 20+ messages in thread
From: Steven Rostedt @ 2011-07-29 14:19 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Mon, 2011-07-25 at 11:39 -0700, Vaibhav Nagarnaik wrote:
> Add another target 'check-events' which parses all the event formats and
> returns whether there are any issues with the print format strings.
> 
> With an error in the format, the return value is 22 (EINVAL) and for
> success, it is 0.

Could you write up a man page for this too?


> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
> ---
> Changelog v2-v1:
> * Pass any parsing failures in pevent structure
> 
>  parse-events.h |    2 ++
>  trace-cmd.c    |   25 +++++++++++++++++++++++++
>  trace-usage.c  |    5 +++++
>  trace-util.c   |   36 ++++++++++++++++++++++++++----------
>  4 files changed, 58 insertions(+), 10 deletions(-)
> 
> diff --git a/parse-events.h b/parse-events.h
> index c32d715..f5cab15 100644
> --- a/parse-events.h
> +++ b/parse-events.h
> @@ -402,6 +402,8 @@ struct pevent {
>  	struct event_handler *handlers;
>  	struct pevent_function_handler *func_handlers;
>  
> +	int parsing_failures;
> +
>  	/* cache */
>  	struct event_format *last_event;
>  };
> diff --git a/trace-cmd.c b/trace-cmd.c
> index bff5bbf..5cfd97f 100644
> --- a/trace-cmd.c
> +++ b/trace-cmd.c
> @@ -158,6 +158,31 @@ int main (int argc, char **argv)
>  	} else if (strcmp(argv[1], "stack") == 0) {
>  		trace_stack(argc, argv);
>  		exit(0);
> +	} else if (strcmp(argv[1], "check-events") == 0) {
> +		char *tracing;
> +		int ret;
> +		struct pevent *pevent = NULL;
> +
> +		tracing = tracecmd_find_tracing_dir();
> +
> +		if (!tracing) {
> +			printf("Can not find or mount tracing directory!\n"
> +				"Either tracing is not configured for this "
> +				"kernel\n"
> +				"or you do not have the proper permissions to "
> +				"mount the directory");
> +			exit(EINVAL);
> +		}
> +
> +		ret = 0;
> +		pevent = tracecmd_local_events(tracing);
> +		if (!pevent)
> +			exit(EINVAL);
> +		if (pevent->parsing_failures)
> +			ret = EINVAL;

Hmm, what about doing:

	if (!pevent || pevent->parsing_failures)
		ret = EINVAL;



> +		pevent_free(pevent);

And allow pevent_free() to take a NULL pointer?

Hmm, I'll just apply this patch and then make the update. But could you
still send a man page patch?

Thanks!

-- Steve

> +		exit(ret);
> +
>  	} else if (strcmp(argv[1], "record") == 0 ||
>  		   strcmp(argv[1], "start") == 0 ||
>  		   strcmp(argv[1], "extract") == 0 ||
> diff --git a/trace-usage.c b/trace-usage.c
> index 39c8fc1..58ef167 100644
> --- a/trace-usage.c
> +++ b/trace-usage.c
> @@ -150,6 +150,11 @@ static struct usage_help usage_help[] = {
>  		"          --reset  reset the maximum stack found\n"
>  	},
>  	{
> +		"check-events",
> +		"parse trace event formats",
> +		" %s check-format\n"
> +	},
> +	{
>  		NULL, NULL, NULL
>  	}
>  };
> diff --git a/trace-util.c b/trace-util.c
> index 674f37e..01894f8 100644
> --- a/trace-util.c
> +++ b/trace-util.c
> @@ -621,22 +621,22 @@ static int read_file(const char *file, char **buffer)
>  	return len;
>  }
>  
> -static void load_events(struct pevent *pevent, const char *system,
> +static int load_events(struct pevent *pevent, const char *system,
>  			const char *sys_dir)
>  {
>  	struct dirent *dent;
>  	struct stat st;
>  	DIR *dir;
>  	int len = 0;
> -	int ret;
> +	int ret = 0, failure = 0;
>  
>  	ret = stat(sys_dir, &st);
>  	if (ret < 0 || !S_ISDIR(st.st_mode))
> -		return;
> +		return EINVAL;
>  
>  	dir = opendir(sys_dir);
>  	if (!dir)
> -		return;
> +		return errno;
>  
>  	while ((dent = readdir(dir))) {
>  		const char *name = dent->d_name;
> @@ -662,15 +662,18 @@ static void load_events(struct pevent *pevent, const char *system,
>  		if (len < 0)
>  			goto free_format;
>  
> -		pevent_parse_event(pevent, buf, len, system);
> +		ret = pevent_parse_event(pevent, buf, len, system);
>  		free(buf);
>   free_format:
>  		free(format);
>   free_event:
>  		free(event);
> +		if (ret)
> +			failure = ret;
>  	}
>  
>  	closedir(dir);
> +	return failure;
>  }
>  
>  static int read_header(struct pevent *pevent, const char *events_dir)
> @@ -715,7 +718,7 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
>  	char *events_dir;
>  	struct stat st;
>  	DIR *dir;
> -	int ret;
> +	int ret, failure = 0;
>  
>  	if (!tracing_dir)
>  		return NULL;
> @@ -725,21 +728,28 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
>  		return NULL;
>  
>  	ret = stat(events_dir, &st);
> -	if (ret < 0 || !S_ISDIR(st.st_mode))
> +	if (ret < 0 || !S_ISDIR(st.st_mode)) {
> +		failure = 1;
>  		goto out_free;
> +	}
>  
>  	dir = opendir(events_dir);
> -	if (!dir)
> +	if (!dir) {
> +		failure = 1;
>  		goto out_free;
> +	}
>  
>  	pevent = pevent_alloc();
> -	if (!pevent)
> +	if (!pevent) {
> +		failure = 1;
>  		goto out_free;
> +	}
>  
>  	ret = read_header(pevent, events_dir);
>  	if (ret < 0) {
>  		pevent_free(pevent);
>  		pevent = NULL;
> +		failure = 1;
>  		goto out_free;
>  	}
>  
> @@ -758,9 +768,12 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
>  			continue;
>  		}
>  
> -		load_events(pevent, name, sys);
> +		ret = load_events(pevent, name, sys);
>  
>  		free(sys);
> +
> +		if (ret)
> +			failure = 1;
>  	}
>  
>  	closedir(dir);
> @@ -768,6 +781,9 @@ struct pevent *tracecmd_local_events(const char *tracing_dir)
>   out_free:
>  	free(events_dir);
>  
> +	if (pevent)
> +		pevent->parsing_failures = failure;
> +
>  	return pevent;
>  }
>  



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-29 14:19   ` Steven Rostedt
@ 2011-07-29 17:41     ` Vaibhav Nagarnaik
  2011-07-29 17:53       ` Steven Rostedt
  0 siblings, 1 reply; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-29 17:41 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, Jul 29, 2011 at 7:19 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Mon, 2011-07-25 at 11:39 -0700, Vaibhav Nagarnaik wrote:
>> Add another target 'check-events' which parses all the event formats and
>> returns whether there are any issues with the print format strings.
>>
>> With an error in the format, the return value is 22 (EINVAL) and for
>> success, it is 0.
>
> Could you write up a man page for this too?
>
>
>> Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
>> ---
>> Changelog v2-v1:
>> * Pass any parsing failures in pevent structure
>>
>>  parse-events.h |    2 ++
>>  trace-cmd.c    |   25 +++++++++++++++++++++++++
>>  trace-usage.c  |    5 +++++
>>  trace-util.c   |   36 ++++++++++++++++++++++++++----------
>>  4 files changed, 58 insertions(+), 10 deletions(-)
>>
>> diff --git a/parse-events.h b/parse-events.h
>> index c32d715..f5cab15 100644
>> --- a/parse-events.h
>> +++ b/parse-events.h
>> @@ -402,6 +402,8 @@ struct pevent {
>>       struct event_handler *handlers;
>>       struct pevent_function_handler *func_handlers;
>>
>> +     int parsing_failures;
>> +
>>       /* cache */
>>       struct event_format *last_event;
>>  };
>> diff --git a/trace-cmd.c b/trace-cmd.c
>> index bff5bbf..5cfd97f 100644
>> --- a/trace-cmd.c
>> +++ b/trace-cmd.c
>> @@ -158,6 +158,31 @@ int main (int argc, char **argv)
>>       } else if (strcmp(argv[1], "stack") == 0) {
>>               trace_stack(argc, argv);
>>               exit(0);
>> +     } else if (strcmp(argv[1], "check-events") == 0) {
>> +             char *tracing;
>> +             int ret;
>> +             struct pevent *pevent = NULL;
>> +
>> +             tracing = tracecmd_find_tracing_dir();
>> +
>> +             if (!tracing) {
>> +                     printf("Can not find or mount tracing directory!\n"
>> +                             "Either tracing is not configured for this "
>> +                             "kernel\n"
>> +                             "or you do not have the proper permissions to "
>> +                             "mount the directory");
>> +                     exit(EINVAL);
>> +             }
>> +
>> +             ret = 0;
>> +             pevent = tracecmd_local_events(tracing);
>> +             if (!pevent)
>> +                     exit(EINVAL);
>> +             if (pevent->parsing_failures)
>> +                     ret = EINVAL;
>
> Hmm, what about doing:
>
>        if (!pevent || pevent->parsing_failures)
>                ret = EINVAL;
>
>
>
>> +             pevent_free(pevent);
>
> And allow pevent_free() to take a NULL pointer?
>
> Hmm, I'll just apply this patch and then make the update. But could you
> still send a man page patch?

Thanks Steve. I will send the man page patch.

Vaibhav Nagarnaik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-29 17:41     ` Vaibhav Nagarnaik
@ 2011-07-29 17:53       ` Steven Rostedt
  2011-07-29 19:07         ` Vaibhav Nagarnaik
  0 siblings, 1 reply; 20+ messages in thread
From: Steven Rostedt @ 2011-07-29 17:53 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-29 at 10:41 -0700, Vaibhav Nagarnaik wrote:

> Thanks Steve. I will send the man page patch.

BTW, I played with this and I have a few issues. I'll still accept the
patch as it's not that big of a deal. But here's some improvements that
can be made.


It should load in the plugins. As the plugins can process failed events
well. If you don't want the plugins than you can just do what we do with
report, add a -N to prevent plugins from being loaded.

It should also read a trace.dat file if one is provided on the command
line. If you don't add a file then it will use the local events of the
system, if possible.

This would make it even more useful.

Thanks!

-- Steve



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-29 17:53       ` Steven Rostedt
@ 2011-07-29 19:07         ` Vaibhav Nagarnaik
  2011-07-30  1:33           ` Steven Rostedt
  0 siblings, 1 reply; 20+ messages in thread
From: Vaibhav Nagarnaik @ 2011-07-29 19:07 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, Jul 29, 2011 at 10:53 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> On Fri, 2011-07-29 at 10:41 -0700, Vaibhav Nagarnaik wrote:
>
>> Thanks Steve. I will send the man page patch.
>
> BTW, I played with this and I have a few issues. I'll still accept the
> patch as it's not that big of a deal. But here's some improvements that
> can be made.
>
>
> It should load in the plugins. As the plugins can process failed events
> well. If you don't want the plugins than you can just do what we do with
> report, add a -N to prevent plugins from being loaded.

Thanks for the suggestion, I didn't know about plugins adding parsing
capability. I will add loading the available plugins for this option.

> It should also read a trace.dat file if one is provided on the command
> line. If you don't add a file then it will use the local events of the
> system, if possible.

Our intention with this patch was to reuse the format string parsing
functionality in trace-cmd to look for any errors in new trace events
added by various kernel developers. So this was targeted to test for
event format errors and report them during a new kernel release.

A trace.dat file has already recorded all the data from the machine and
when 'report' is used on it, the format string errors will be reported
regardless. I don't see how using 'check-events' on a trace.dat file
would be useful. Thoughts?


Vaibhav Nagarnaik

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH v2 1/4] trace-cmd: Add parse error checking target
  2011-07-29 19:07         ` Vaibhav Nagarnaik
@ 2011-07-30  1:33           ` Steven Rostedt
  0 siblings, 0 replies; 20+ messages in thread
From: Steven Rostedt @ 2011-07-30  1:33 UTC (permalink / raw)
  To: Vaibhav Nagarnaik; +Cc: Michael Rubin, David Sharp, linux-kernel

On Fri, 2011-07-29 at 12:07 -0700, Vaibhav Nagarnaik wrote:
> On Fri, Jul 29, 2011 at 10:53 AM, Steven Rostedt <rostedt@goodmis.org> wrote:

> Our intention with this patch was to reuse the format string parsing
> functionality in trace-cmd to look for any errors in new trace events
> added by various kernel developers. So this was targeted to test for
> event format errors and report them during a new kernel release.

Note, I plan on working on the libperf.so soon and this will allow
plugins to be added for both perf and trace-cmd, and will make depending
on a working print-fmt less.

> 
> A trace.dat file has already recorded all the data from the machine and
> when 'report' is used on it, the format string errors will be reported
> regardless. I don't see how using 'check-events' on a trace.dat file
> would be useful. Thoughts?

Just to see if there's issues in a trace.dat file. But perhaps we could
just add a --check to report. I just figured that it shouldn't be to
hard to add, and may prove useful in the future.

Actually, since plugins may not be on all boxes, and a trace.dat file
can come from anywhere. It could be useful to know if the box you are
reading the trace.dat file has the necessary plugins for it or not.

-- Steve



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [tip:perf/core] parse-events: Handle invalid opcode parsing gracefully
  2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
  2011-07-25 14:03   ` Steven Rostedt
@ 2012-05-21  9:39   ` tip-bot for Vaibhav Nagarnaik
  1 sibling, 0 replies; 20+ messages in thread
From: tip-bot for Vaibhav Nagarnaik @ 2012-05-21  9:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, vnagarnaik, hpa, mingo, peterz, dhsharp,
	namhyung.kim, bp, jolsa, fweisbec, acme, mrubin, rostedt, tglx,
	asharma

Commit-ID:  d69afed55be1016c2bcfcb3e00cd5365d2f557f6
Gitweb:     http://git.kernel.org/tip/d69afed55be1016c2bcfcb3e00cd5365d2f557f6
Author:     Vaibhav Nagarnaik <vnagarnaik@google.com>
AuthorDate: Fri, 6 Apr 2012 00:48:00 +0200
Committer:  Frederic Weisbecker <fweisbec@gmail.com>
CommitDate: Wed, 25 Apr 2012 13:35:28 +0200

parse-events: Handle invalid opcode parsing gracefully

If an invalid opcode is encountered, trace-cmd exits with an error.
Instead it can be treated as a soft error where the event's print format
is not parsed and its binary data is dumped out.

This patch adds a return value to arg_num_eval() function to indicate if
the parsing was successful. If not, then the error is considered soft
and the parsing of the offending event fails.

Cc: Michael Rubin <mrubin@google.com>
Cc: David Sharp <dhsharp@google.com>
Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
Link: http://lkml.kernel.org/r/1310785241-3799-2-git-send-email-vnagarnaik@google.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
 tools/lib/traceevent/event-parse.c |  125 ++++++++++++++++++++++++------------
 1 files changed, 83 insertions(+), 42 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 16da20c..ef2c65f 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -1915,90 +1915,120 @@ eval_type(unsigned long long val, struct print_arg *arg, int pointer)
 	return eval_type_str(val, arg->typecast.type, pointer);
 }
 
-static long long arg_num_eval(struct print_arg *arg)
+static int arg_num_eval(struct print_arg *arg, long long *val)
 {
 	long long left, right;
-	long long val = 0;
+	int ret = 1;
 
 	switch (arg->type) {
 	case PRINT_ATOM:
-		val = strtoll(arg->atom.atom, NULL, 0);
+		*val = strtoll(arg->atom.atom, NULL, 0);
 		break;
 	case PRINT_TYPE:
-		val = arg_num_eval(arg->typecast.item);
-		val = eval_type(val, arg, 0);
+		ret = arg_num_eval(arg->typecast.item, val);
+		if (!ret)
+			break;
+		*val = eval_type(*val, arg, 0);
 		break;
 	case PRINT_OP:
 		switch (arg->op.op[0]) {
 		case '|':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			if (arg->op.op[1])
-				val = left || right;
+				*val = left || right;
 			else
-				val = left | right;
+				*val = left | right;
 			break;
 		case '&':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			if (arg->op.op[1])
-				val = left && right;
+				*val = left && right;
 			else
-				val = left & right;
+				*val = left & right;
 			break;
 		case '<':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			switch (arg->op.op[1]) {
 			case 0:
-				val = left < right;
+				*val = left < right;
 				break;
 			case '<':
-				val = left << right;
+				*val = left << right;
 				break;
 			case '=':
-				val = left <= right;
+				*val = left <= right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '>':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 			switch (arg->op.op[1]) {
 			case 0:
-				val = left > right;
+				*val = left > right;
 				break;
 			case '>':
-				val = left >> right;
+				*val = left >> right;
 				break;
 			case '=':
-				val = left >= right;
+				*val = left >= right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '=':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
-
-			if (arg->op.op[1] != '=')
-				die("unknown op '%s'", arg->op.op);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 
-			val = left == right;
+			if (arg->op.op[1] != '=') {
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
+			} else
+				*val = left == right;
 			break;
 		case '!':
-			left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
+			ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
 
 			switch (arg->op.op[1]) {
 			case '=':
-				val = left != right;
+				*val = left != right;
 				break;
 			default:
-				die("unknown op '%s'", arg->op.op);
+				do_warning("unknown op '%s'", arg->op.op);
+				ret = 0;
 			}
 			break;
 		case '-':
@@ -2006,12 +2036,17 @@ static long long arg_num_eval(struct print_arg *arg)
 			if (arg->op.left->type == PRINT_NULL)
 				left = 0;
 			else
-				left = arg_num_eval(arg->op.left);
-			right = arg_num_eval(arg->op.right);
-			val = left - right;
+				ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
+			*val = left - right;
 			break;
 		default:
-			die("unknown op '%s'", arg->op.op);
+			do_warning("unknown op '%s'", arg->op.op);
+			ret = 0;
 		}
 		break;
 
@@ -2020,10 +2055,11 @@ static long long arg_num_eval(struct print_arg *arg)
 	case PRINT_STRING:
 	case PRINT_BSTRING:
 	default:
-		die("invalid eval type %d", arg->type);
+		do_warning("invalid eval type %d", arg->type);
+		ret = 0;
 
 	}
-	return val;
+	return ret;
 }
 
 static char *arg_eval (struct print_arg *arg)
@@ -2037,7 +2073,8 @@ static char *arg_eval (struct print_arg *arg)
 	case PRINT_TYPE:
 		return arg_eval(arg->typecast.item);
 	case PRINT_OP:
-		val = arg_num_eval(arg);
+		if (!arg_num_eval(arg, &val))
+			break;
 		sprintf(buf, "%lld", val);
 		return buf;
 
@@ -2079,6 +2116,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
 		memset(field, 0, sizeof(*field));
 
 		value = arg_eval(arg);
+		if (value == NULL)
+			goto out_free;
 		field->value = strdup(value);
 
 		free_arg(arg);
@@ -2090,6 +2129,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
 			goto out_free;
 
 		value = arg_eval(arg);
+		if (value == NULL)
+			goto out_free;
 		field->str = strdup(value);
 		free_arg(arg);
 		arg = NULL;

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] parse-events: Handle opcode parsing error
  2011-07-25 18:40   ` Vaibhav Nagarnaik
@ 2012-05-21  9:39     ` tip-bot for Vaibhav Nagarnaik
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Vaibhav Nagarnaik @ 2012-05-21  9:39 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, vnagarnaik, hpa, mingo, peterz, dhsharp,
	namhyung.kim, bp, jolsa, fweisbec, acme, mrubin, rostedt, tglx,
	asharma

Commit-ID:  14ffde0e966efab6724e2de3ab470b78d4e01109
Gitweb:     http://git.kernel.org/tip/14ffde0e966efab6724e2de3ab470b78d4e01109
Author:     Vaibhav Nagarnaik <vnagarnaik@google.com>
AuthorDate: Fri, 6 Apr 2012 00:48:01 +0200
Committer:  Frederic Weisbecker <fweisbec@gmail.com>
CommitDate: Wed, 25 Apr 2012 13:35:32 +0200

parse-events: Handle opcode parsing error

If an invalid opcode is encountered in parsing event print format, the
trace-cmd calls exit() without parsing any other events.

This patch adds handling for such an error where the get_op_prio() is
called. If the return value is -1, then the event print format parsing
is skipped and parsing continues.

Cc: Michael Rubin <mrubin@google.com>
Cc: David Sharp <dhsharp@google.com>
Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
Link: http://lkml.kernel.org/r/1311619257-4970-1-git-send-email-vnagarnaik@google.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
 tools/lib/traceevent/event-parse.c |   19 +++++++++++--------
 1 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index ef2c65f..cdb32c7 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -1592,7 +1592,7 @@ static int get_op_prio(char *op)
 		case '?':
 			return 16;
 		default:
-			die("unknown op '%c'", op[0]);
+			do_warning("unknown op '%c'", op[0]);
 			return -1;
 		}
 	} else {
@@ -1613,22 +1613,22 @@ static int get_op_prio(char *op)
 		} else if (strcmp(op, "||") == 0) {
 			return 15;
 		} else {
-			die("unknown op '%s'", op);
+			do_warning("unknown op '%s'", op);
 			return -1;
 		}
 	}
 }
 
-static void set_op_prio(struct print_arg *arg)
+static int set_op_prio(struct print_arg *arg)
 {
 
 	/* single ops are the greatest */
-	if (!arg->op.left || arg->op.left->type == PRINT_NULL) {
+	if (!arg->op.left || arg->op.left->type == PRINT_NULL)
 		arg->op.prio = 0;
-		return;
-	}
+	else
+		arg->op.prio = get_op_prio(arg->op.op);
 
-	arg->op.prio = get_op_prio(arg->op.op);
+	return arg->op.prio;
 }
 
 /* Note, *tok does not get freed, but will most likely be saved */
@@ -1710,7 +1710,10 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
 		arg->op.op = token;
 		arg->op.left = left;
 
-		set_op_prio(arg);
+		if (set_op_prio(arg) == -1) {
+			event->flags |= EVENT_FL_FAILED;
+			goto out_free;
+		}
 
 		type = read_token_item(&token);
 		*tok = token;

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] parse-events: Support '+' opcode in print format
  2011-07-16  3:00 ` [PATCH 4/4] trace-cmd: Support '+' opcode in print format Vaibhav Nagarnaik
  2011-07-25 14:02   ` Steven Rostedt
@ 2012-05-21  9:41   ` tip-bot for Vaibhav Nagarnaik
  1 sibling, 0 replies; 20+ messages in thread
From: tip-bot for Vaibhav Nagarnaik @ 2012-05-21  9:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, vnagarnaik, hpa, mingo, peterz, dhsharp,
	namhyung.kim, bp, jolsa, fweisbec, acme, mrubin, rostedt, tglx,
	asharma

Commit-ID:  b48285980de2070948c8ac73629c605ad9202589
Gitweb:     http://git.kernel.org/tip/b48285980de2070948c8ac73629c605ad9202589
Author:     Vaibhav Nagarnaik <vnagarnaik@google.com>
AuthorDate: Fri, 6 Apr 2012 00:48:03 +0200
Committer:  Frederic Weisbecker <fweisbec@gmail.com>
CommitDate: Wed, 25 Apr 2012 13:35:38 +0200

parse-events: Support '+' opcode in print format

The '+' opcode is not supported in the arguments for the print format.
This patch adds support for it.

Cc: Michael Rubin <mrubin@google.com>
Cc: David Sharp <dhsharp@google.com>
Signed-off-by: Vaibhav Nagarnaik <vnagarnaik@google.com>
Link: http://lkml.kernel.org/r/1310785241-3799-4-git-send-email-vnagarnaik@google.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Arun Sharma <asharma@fb.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
 tools/lib/traceevent/event-parse.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 4d5092f..476626a 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2047,6 +2047,18 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
 				break;
 			*val = left - right;
 			break;
+		case '+':
+			if (arg->op.left->type == PRINT_NULL)
+				left = 0;
+			else
+				ret = arg_num_eval(arg->op.left, &left);
+			if (!ret)
+				break;
+			ret = arg_num_eval(arg->op.right, &right);
+			if (!ret)
+				break;
+			*val = left + right;
+			break;
 		default:
 			do_warning("unknown op '%s'", arg->op.op);
 			ret = 0;

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2012-05-21  9:42 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-16  3:00 [PATCH 1/4] trace-cmd: Add parse error checking target Vaibhav Nagarnaik
2011-07-16  3:00 ` [PATCH 2/4] trace-cmd: Handle invalid opcode parsing gracefully Vaibhav Nagarnaik
2011-07-25 14:03   ` Steven Rostedt
2012-05-21  9:39   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
2011-07-16  3:00 ` [PATCH 3/4] trace-cmd: Handle opcode parsing error Vaibhav Nagarnaik
2011-07-25 14:01   ` Steven Rostedt
2011-07-25 18:06     ` Vaibhav Nagarnaik
2011-07-25 18:40   ` Vaibhav Nagarnaik
2012-05-21  9:39     ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
2011-07-16  3:00 ` [PATCH 4/4] trace-cmd: Support '+' opcode in print format Vaibhav Nagarnaik
2011-07-25 14:02   ` Steven Rostedt
2012-05-21  9:41   ` [tip:perf/core] parse-events: " tip-bot for Vaibhav Nagarnaik
2011-07-25 13:32 ` [PATCH 1/4] trace-cmd: Add parse error checking target Steven Rostedt
2011-07-25 18:06   ` Vaibhav Nagarnaik
2011-07-25 18:39 ` [PATCH v2 " Vaibhav Nagarnaik
2011-07-29 14:19   ` Steven Rostedt
2011-07-29 17:41     ` Vaibhav Nagarnaik
2011-07-29 17:53       ` Steven Rostedt
2011-07-29 19:07         ` Vaibhav Nagarnaik
2011-07-30  1:33           ` Steven Rostedt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.