lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1254809398-8078-7-git-send-email-tzanussi@gmail.com>
Date:	Tue,  6 Oct 2009 01:09:55 -0500
From:	Tom Zanussi <tzanussi@...il.com>
To:	linux-kernel@...r.kernel.org
Cc:	mingo@...e.hu, fweisbec@...il.com, rostedt@...dmis.org,
	lizf@...fujitsu.com, hch@...radead.org
Subject: [RFC][PATCH 6/9] perf trace: Add scripting op for generating empty event handling scripts

To give script writers an easy starting point for writing scripts,
scripting language support for a particular language can implement a
generate_event_handlers() scripting op that will output an empty (or
near-empty) set of handlers in the supported language for all the
events contained in a give perf.data trace file.

This patch adds the generate_event_handlers() scripting op and also
adds a Perl implementation that creates a ready-to-run Perl script
that can be passed to perf trace for generic event printing.  Scripts
generated by this implementation print out all the fields for each
event (and will detect and generate the proper scripting code for
'flag' and 'symbolic' fields), and will additionally generate handlers
for the special 'trace_unhandled', 'trace_begin' and 'trace_end'
handlers.  Script authors can simply remove the printing code to
implement their own custom event handling.

Signed-off-by: Tom Zanussi <tzanussi@...il.com>
---
 tools/perf/builtin-trace.c         |   23 +++++++-
 tools/perf/util/trace-event-perl.c |  114 ++++++++++++++++++++++++++++++++++++
 tools/perf/util/trace-event.h      |    1 +
 3 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 74aec38..b151e77 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -30,6 +30,7 @@ static u64		sample_type;
 static char		const *script_name;
 
 static int		do_perl;
+static int		generate_handlers;
 
 static int default_start_script(const char *script __attribute((unused)))
 {
@@ -41,10 +42,16 @@ static int default_stop_script(void)
 	return 0;
 }
 
+static int default_generate_event_handlers(const char *outfile __attribute ((unused)))
+{
+	return 0;
+}
+
 static struct trace_scripting_operations default_scripting_ops = {
 	.start_script = default_start_script,
 	.stop_script = default_stop_script,
 	.process_event = print_event,
+	.generate_event_handlers = default_generate_event_handlers,
 };
 
 static struct trace_scripting_operations *scripting_ops;
@@ -263,6 +270,8 @@ static const struct option options[] = {
 		    "be more verbose (show symbol address, etc)"),
 	OPT_BOOLEAN('p', "perl", &do_perl,
 		    "send output to a Perl script"),
+	OPT_BOOLEAN('g', "generate-event-handlers", &generate_handlers,
+		    "generate empty event handlers for scripting languages"),
 	OPT_STRING('s', "script", &script_name, "file",
 		    "script file name"),
 	OPT_END()
@@ -270,11 +279,14 @@ static const struct option options[] = {
 
 static int setup_scripting(const char *script)
 {
+	if (do_perl && generate_handlers)
+		goto setup;
+
 	if ((do_perl && !script) || (script && !do_perl))
 		usage_with_options(annotate_usage, options);
 
 	scripting_ops = &default_scripting_ops;
-
+setup:
 	if (do_perl) {
 		scripting_ops = setup_perl_scripting();
 		if (!scripting_ops)
@@ -312,9 +324,16 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
 	if (err)
 		goto out;
 
+	if (generate_handlers) {
+		trace_report();
+		err = scripting_ops->generate_event_handlers("perf-trace.pl");
+		goto out;
+	}
+
 	if (script_name) {
 		err = scripting_ops->start_script(script_name);
-		goto out;
+		if (err)
+			goto out;
 	}
 
 	err = __cmd_trace();
diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c
index 1264e14..657b87a 100644
--- a/tools/perf/util/trace-event-perl.c
+++ b/tools/perf/util/trace-event-perl.c
@@ -356,10 +356,124 @@ static int perl_stop_script(void)
 	return 0;
 }
 
+static int perl_generate_event_handlers(const char *outfile)
+{
+	struct event *event = NULL;
+	struct format_field *f;
+	int not_first;
+	FILE *ofp;
+
+	ofp = fopen(outfile, "w");
+	if (ofp == NULL) {
+		fprintf(stderr, "couldn't open %s\n", outfile);
+		return -1;
+	}
+
+	fprintf(ofp, "# perf trace event handlers, "
+		"generated by perf trace -p -g\n\n");
+
+	fprintf(ofp, "# The common_* event handler fields are the most useful "
+		"fields common to\n");
+
+	fprintf(ofp, "# all events.  They don't necessarily correspond to "
+		"the 'common_*' fields\n");
+
+	fprintf(ofp, "# in the status files.  Those fields not available as "
+		"handler params can\n");
+
+	fprintf(ofp, "# be retrieved via script functions of the form "
+		"get_common_*().\n\n");
+
+	fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/"
+		"Perf-Trace-Util/lib\";\n");
+
+	fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n");
+	fprintf(ofp, "use Perf::Trace::Core;\n");
+	fprintf(ofp, "use Perf::Trace::Util;\n\n");
+
+	fprintf(ofp, "sub trace_begin\n{\n    # optional\n}\n\n");
+	fprintf(ofp, "sub trace_end\n{\n    # optional\n}\n\n");
+
+	while ((event = trace_find_next_event(event))) {
+		fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
+		fprintf(ofp, "    my (");
+
+		fprintf(ofp, "$event_name, ");
+		fprintf(ofp, "$common_cpu, ");
+		fprintf(ofp, "$common_secs, ");
+		fprintf(ofp, "$common_nsecs, ");
+		fprintf(ofp, "$common_pid, ");
+		fprintf(ofp, "$common_comm,\n        ");
+
+		not_first = 0;
+
+		for (f = event->format.fields; f; f = f->next) {
+			if (not_first++)
+				fprintf(ofp, ", ");
+
+			fprintf(ofp, "$%s", f->name);
+		}
+		fprintf(ofp, ") = @_;\n\n");
+
+		fprintf(ofp, "    print_header($event_name, $common_cpu, "
+			"$common_secs, $common_nsecs, $common_pid, "
+			"$common_comm);\n\n");
+
+		fprintf(ofp, "    printf(\"");
+
+		not_first = 0;
+
+		for (f = event->format.fields; f; f = f->next) {
+			if (not_first++)
+				fprintf(ofp, ", ");
+
+			fprintf(ofp, "%s=", f->name);
+			if (f->flags & FIELD_IS_STRING)
+				fprintf(ofp, "%%s");
+			else if (f->flags & FIELD_IS_SIGNED)
+				fprintf(ofp, "%%d");
+			else
+				fprintf(ofp, "%%u");
+		}
+
+		fprintf(ofp, "\\n\", ");
+
+		not_first = 0;
+
+		for (f = event->format.fields; f; f = f->next) {
+			if (not_first++)
+				fprintf(ofp, ", ");
+
+			fprintf(ofp, "$%s", f->name);
+		}
+
+		fprintf(ofp, ");\n");
+		fprintf(ofp, "}\n\n");
+	}
+
+	fprintf(ofp, "sub trace_unhandled\n{\n    my ($event_name, "
+		"$common_cpu, $common_secs, $common_nsecs, $common_pid, "
+		"$common_comm) = @_;\n\n");
+
+	fprintf(ofp, "    print_header($event_name, $common_cpu, "
+		"$common_secs, $common_nsecs, $common_pid, "
+		"$common_comm);\n}\n\n");
+
+	fprintf(ofp, "sub print_header\n{\n"
+		"    my ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
+		"    printf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \", "
+		"$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}");
+
+	fclose(ofp);
+
+	return 0;
+}
+
 struct trace_scripting_operations perl_scripting_ops = {
 	.start_script = perl_start_script,
 	.stop_script = perl_stop_script,
 	.process_event = perl_process_event,
+	.generate_event_handlers = perl_generate_event_handlers,
 };
 
 #ifdef NO_LIBPERL
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index f812a8e..582e0eb 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -255,6 +255,7 @@ struct trace_scripting_operations {
 	int (*stop_script) (void);
 	void (*process_event) (int cpu, void *data, int size,
 			       unsigned long long nsecs, char *comm);
+	int (*generate_event_handlers) (const char *outfile);
 };
 
 extern struct trace_scripting_operations perl_scripting_ops;
-- 
1.6.4.GIT

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ