xref: /linux/tools/perf/util/scripting-engines/trace-event-perl.c (revision de28c15daf60e9625bece22f13a091fac8d05f1d)
1  /*
2   * trace-event-perl.  Feed perf script events to an embedded Perl interpreter.
3   *
4   * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
8   *  the Free Software Foundation; either version 2 of the License, or
9   *  (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   *  GNU General Public License for more details.
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19   *
20   */
21  
22  #include <stdio.h>
23  #include <stdlib.h>
24  #include <string.h>
25  #include <ctype.h>
26  #include <errno.h>
27  #include <linux/bitmap.h>
28  
29  #include "../util.h"
30  #include <EXTERN.h>
31  #include <perl.h>
32  
33  #include "../../perf.h"
34  #include "../thread.h"
35  #include "../event.h"
36  #include "../trace-event.h"
37  #include "../evsel.h"
38  #include "../debug.h"
39  
40  void boot_Perf__Trace__Context(pTHX_ CV *cv);
41  void boot_DynaLoader(pTHX_ CV *cv);
42  typedef PerlInterpreter * INTERP;
43  
44  void xs_init(pTHX);
45  
46  void xs_init(pTHX)
47  {
48  	const char *file = __FILE__;
49  	dXSUB_SYS;
50  
51  	newXS("Perf::Trace::Context::bootstrap", boot_Perf__Trace__Context,
52  	      file);
53  	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
54  }
55  
56  INTERP my_perl;
57  
58  #define FTRACE_MAX_EVENT				\
59  	((1 << (sizeof(unsigned short) * 8)) - 1)
60  
61  static DECLARE_BITMAP(events_defined, FTRACE_MAX_EVENT);
62  
63  extern struct scripting_context *scripting_context;
64  
65  static char *cur_field_name;
66  static int zero_flag_atom;
67  
68  static void define_symbolic_value(const char *ev_name,
69  				  const char *field_name,
70  				  const char *field_value,
71  				  const char *field_str)
72  {
73  	unsigned long long value;
74  	dSP;
75  
76  	value = eval_flag(field_value);
77  
78  	ENTER;
79  	SAVETMPS;
80  	PUSHMARK(SP);
81  
82  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
83  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
84  	XPUSHs(sv_2mortal(newSVuv(value)));
85  	XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
86  
87  	PUTBACK;
88  	if (get_cv("main::define_symbolic_value", 0))
89  		call_pv("main::define_symbolic_value", G_SCALAR);
90  	SPAGAIN;
91  	PUTBACK;
92  	FREETMPS;
93  	LEAVE;
94  }
95  
96  static void define_symbolic_values(struct print_flag_sym *field,
97  				   const char *ev_name,
98  				   const char *field_name)
99  {
100  	define_symbolic_value(ev_name, field_name, field->value, field->str);
101  	if (field->next)
102  		define_symbolic_values(field->next, ev_name, field_name);
103  }
104  
105  static void define_symbolic_field(const char *ev_name,
106  				  const char *field_name)
107  {
108  	dSP;
109  
110  	ENTER;
111  	SAVETMPS;
112  	PUSHMARK(SP);
113  
114  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
115  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
116  
117  	PUTBACK;
118  	if (get_cv("main::define_symbolic_field", 0))
119  		call_pv("main::define_symbolic_field", G_SCALAR);
120  	SPAGAIN;
121  	PUTBACK;
122  	FREETMPS;
123  	LEAVE;
124  }
125  
126  static void define_flag_value(const char *ev_name,
127  			      const char *field_name,
128  			      const char *field_value,
129  			      const char *field_str)
130  {
131  	unsigned long long value;
132  	dSP;
133  
134  	value = eval_flag(field_value);
135  
136  	ENTER;
137  	SAVETMPS;
138  	PUSHMARK(SP);
139  
140  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
141  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
142  	XPUSHs(sv_2mortal(newSVuv(value)));
143  	XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
144  
145  	PUTBACK;
146  	if (get_cv("main::define_flag_value", 0))
147  		call_pv("main::define_flag_value", G_SCALAR);
148  	SPAGAIN;
149  	PUTBACK;
150  	FREETMPS;
151  	LEAVE;
152  }
153  
154  static void define_flag_values(struct print_flag_sym *field,
155  			       const char *ev_name,
156  			       const char *field_name)
157  {
158  	define_flag_value(ev_name, field_name, field->value, field->str);
159  	if (field->next)
160  		define_flag_values(field->next, ev_name, field_name);
161  }
162  
163  static void define_flag_field(const char *ev_name,
164  			      const char *field_name,
165  			      const char *delim)
166  {
167  	dSP;
168  
169  	ENTER;
170  	SAVETMPS;
171  	PUSHMARK(SP);
172  
173  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
174  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
175  	XPUSHs(sv_2mortal(newSVpv(delim, 0)));
176  
177  	PUTBACK;
178  	if (get_cv("main::define_flag_field", 0))
179  		call_pv("main::define_flag_field", G_SCALAR);
180  	SPAGAIN;
181  	PUTBACK;
182  	FREETMPS;
183  	LEAVE;
184  }
185  
186  static void define_event_symbols(struct event_format *event,
187  				 const char *ev_name,
188  				 struct print_arg *args)
189  {
190  	switch (args->type) {
191  	case PRINT_NULL:
192  		break;
193  	case PRINT_ATOM:
194  		define_flag_value(ev_name, cur_field_name, "0",
195  				  args->atom.atom);
196  		zero_flag_atom = 0;
197  		break;
198  	case PRINT_FIELD:
199  		free(cur_field_name);
200  		cur_field_name = strdup(args->field.name);
201  		break;
202  	case PRINT_FLAGS:
203  		define_event_symbols(event, ev_name, args->flags.field);
204  		define_flag_field(ev_name, cur_field_name, args->flags.delim);
205  		define_flag_values(args->flags.flags, ev_name, cur_field_name);
206  		break;
207  	case PRINT_SYMBOL:
208  		define_event_symbols(event, ev_name, args->symbol.field);
209  		define_symbolic_field(ev_name, cur_field_name);
210  		define_symbolic_values(args->symbol.symbols, ev_name,
211  				       cur_field_name);
212  		break;
213  	case PRINT_HEX:
214  		define_event_symbols(event, ev_name, args->hex.field);
215  		define_event_symbols(event, ev_name, args->hex.size);
216  		break;
217  	case PRINT_INT_ARRAY:
218  		define_event_symbols(event, ev_name, args->int_array.field);
219  		define_event_symbols(event, ev_name, args->int_array.count);
220  		define_event_symbols(event, ev_name, args->int_array.el_size);
221  		break;
222  	case PRINT_BSTRING:
223  	case PRINT_DYNAMIC_ARRAY:
224  	case PRINT_STRING:
225  	case PRINT_BITMASK:
226  		break;
227  	case PRINT_TYPE:
228  		define_event_symbols(event, ev_name, args->typecast.item);
229  		break;
230  	case PRINT_OP:
231  		if (strcmp(args->op.op, ":") == 0)
232  			zero_flag_atom = 1;
233  		define_event_symbols(event, ev_name, args->op.left);
234  		define_event_symbols(event, ev_name, args->op.right);
235  		break;
236  	case PRINT_FUNC:
237  	default:
238  		pr_err("Unsupported print arg type\n");
239  		/* we should warn... */
240  		return;
241  	}
242  
243  	if (args->next)
244  		define_event_symbols(event, ev_name, args->next);
245  }
246  
247  static void perl_process_tracepoint(struct perf_sample *sample,
248  				    struct perf_evsel *evsel,
249  				    struct thread *thread)
250  {
251  	struct event_format *event = evsel->tp_format;
252  	struct format_field *field;
253  	static char handler[256];
254  	unsigned long long val;
255  	unsigned long s, ns;
256  	int pid;
257  	int cpu = sample->cpu;
258  	void *data = sample->raw_data;
259  	unsigned long long nsecs = sample->time;
260  	const char *comm = thread__comm_str(thread);
261  
262  	dSP;
263  
264  	if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
265  		return;
266  
267  	if (!event)
268  		die("ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
269  
270  	pid = raw_field_value(event, "common_pid", data);
271  
272  	sprintf(handler, "%s::%s", event->system, event->name);
273  
274  	if (!test_and_set_bit(event->id, events_defined))
275  		define_event_symbols(event, handler, event->print_fmt.args);
276  
277  	s = nsecs / NSECS_PER_SEC;
278  	ns = nsecs - s * NSECS_PER_SEC;
279  
280  	scripting_context->event_data = data;
281  	scripting_context->pevent = evsel->tp_format->pevent;
282  
283  	ENTER;
284  	SAVETMPS;
285  	PUSHMARK(SP);
286  
287  	XPUSHs(sv_2mortal(newSVpv(handler, 0)));
288  	XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
289  	XPUSHs(sv_2mortal(newSVuv(cpu)));
290  	XPUSHs(sv_2mortal(newSVuv(s)));
291  	XPUSHs(sv_2mortal(newSVuv(ns)));
292  	XPUSHs(sv_2mortal(newSViv(pid)));
293  	XPUSHs(sv_2mortal(newSVpv(comm, 0)));
294  
295  	/* common fields other than pid can be accessed via xsub fns */
296  
297  	for (field = event->format.fields; field; field = field->next) {
298  		if (field->flags & FIELD_IS_STRING) {
299  			int offset;
300  			if (field->flags & FIELD_IS_DYNAMIC) {
301  				offset = *(int *)(data + field->offset);
302  				offset &= 0xffff;
303  			} else
304  				offset = field->offset;
305  			XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
306  		} else { /* FIELD_IS_NUMERIC */
307  			val = read_size(event, data + field->offset,
308  					field->size);
309  			if (field->flags & FIELD_IS_SIGNED) {
310  				XPUSHs(sv_2mortal(newSViv(val)));
311  			} else {
312  				XPUSHs(sv_2mortal(newSVuv(val)));
313  			}
314  		}
315  	}
316  
317  	PUTBACK;
318  
319  	if (get_cv(handler, 0))
320  		call_pv(handler, G_SCALAR);
321  	else if (get_cv("main::trace_unhandled", 0)) {
322  		XPUSHs(sv_2mortal(newSVpv(handler, 0)));
323  		XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
324  		XPUSHs(sv_2mortal(newSVuv(cpu)));
325  		XPUSHs(sv_2mortal(newSVuv(nsecs)));
326  		XPUSHs(sv_2mortal(newSViv(pid)));
327  		XPUSHs(sv_2mortal(newSVpv(comm, 0)));
328  		call_pv("main::trace_unhandled", G_SCALAR);
329  	}
330  	SPAGAIN;
331  	PUTBACK;
332  	FREETMPS;
333  	LEAVE;
334  }
335  
336  static void perl_process_event_generic(union perf_event *event,
337  				       struct perf_sample *sample,
338  				       struct perf_evsel *evsel)
339  {
340  	dSP;
341  
342  	if (!get_cv("process_event", 0))
343  		return;
344  
345  	ENTER;
346  	SAVETMPS;
347  	PUSHMARK(SP);
348  	XPUSHs(sv_2mortal(newSVpvn((const char *)event, event->header.size)));
349  	XPUSHs(sv_2mortal(newSVpvn((const char *)&evsel->attr, sizeof(evsel->attr))));
350  	XPUSHs(sv_2mortal(newSVpvn((const char *)sample, sizeof(*sample))));
351  	XPUSHs(sv_2mortal(newSVpvn((const char *)sample->raw_data, sample->raw_size)));
352  	PUTBACK;
353  	call_pv("process_event", G_SCALAR);
354  	SPAGAIN;
355  	PUTBACK;
356  	FREETMPS;
357  	LEAVE;
358  }
359  
360  static void perl_process_event(union perf_event *event,
361  			       struct perf_sample *sample,
362  			       struct perf_evsel *evsel,
363  			       struct addr_location *al)
364  {
365  	perl_process_tracepoint(sample, evsel, al->thread);
366  	perl_process_event_generic(event, sample, evsel);
367  }
368  
369  static void run_start_sub(void)
370  {
371  	dSP; /* access to Perl stack */
372  	PUSHMARK(SP);
373  
374  	if (get_cv("main::trace_begin", 0))
375  		call_pv("main::trace_begin", G_DISCARD | G_NOARGS);
376  }
377  
378  /*
379   * Start trace script
380   */
381  static int perl_start_script(const char *script, int argc, const char **argv)
382  {
383  	const char **command_line;
384  	int i, err = 0;
385  
386  	command_line = malloc((argc + 2) * sizeof(const char *));
387  	command_line[0] = "";
388  	command_line[1] = script;
389  	for (i = 2; i < argc + 2; i++)
390  		command_line[i] = argv[i - 2];
391  
392  	my_perl = perl_alloc();
393  	perl_construct(my_perl);
394  
395  	if (perl_parse(my_perl, xs_init, argc + 2, (char **)command_line,
396  		       (char **)NULL)) {
397  		err = -1;
398  		goto error;
399  	}
400  
401  	if (perl_run(my_perl)) {
402  		err = -1;
403  		goto error;
404  	}
405  
406  	if (SvTRUE(ERRSV)) {
407  		err = -1;
408  		goto error;
409  	}
410  
411  	run_start_sub();
412  
413  	free(command_line);
414  	return 0;
415  error:
416  	perl_free(my_perl);
417  	free(command_line);
418  
419  	return err;
420  }
421  
422  static int perl_flush_script(void)
423  {
424  	return 0;
425  }
426  
427  /*
428   * Stop trace script
429   */
430  static int perl_stop_script(void)
431  {
432  	dSP; /* access to Perl stack */
433  	PUSHMARK(SP);
434  
435  	if (get_cv("main::trace_end", 0))
436  		call_pv("main::trace_end", G_DISCARD | G_NOARGS);
437  
438  	perl_destruct(my_perl);
439  	perl_free(my_perl);
440  
441  	return 0;
442  }
443  
444  static int perl_generate_script(struct pevent *pevent, const char *outfile)
445  {
446  	struct event_format *event = NULL;
447  	struct format_field *f;
448  	char fname[PATH_MAX];
449  	int not_first, count;
450  	FILE *ofp;
451  
452  	sprintf(fname, "%s.pl", outfile);
453  	ofp = fopen(fname, "w");
454  	if (ofp == NULL) {
455  		fprintf(stderr, "couldn't open %s\n", fname);
456  		return -1;
457  	}
458  
459  	fprintf(ofp, "# perf script event handlers, "
460  		"generated by perf script -g perl\n");
461  
462  	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
463  		" License version 2\n\n");
464  
465  	fprintf(ofp, "# The common_* event handler fields are the most useful "
466  		"fields common to\n");
467  
468  	fprintf(ofp, "# all events.  They don't necessarily correspond to "
469  		"the 'common_*' fields\n");
470  
471  	fprintf(ofp, "# in the format files.  Those fields not available as "
472  		"handler params can\n");
473  
474  	fprintf(ofp, "# be retrieved using Perl functions of the form "
475  		"common_*($context).\n");
476  
477  	fprintf(ofp, "# See Context.pm for the list of available "
478  		"functions.\n\n");
479  
480  	fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/"
481  		"Perf-Trace-Util/lib\";\n");
482  
483  	fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n");
484  	fprintf(ofp, "use Perf::Trace::Core;\n");
485  	fprintf(ofp, "use Perf::Trace::Context;\n");
486  	fprintf(ofp, "use Perf::Trace::Util;\n\n");
487  
488  	fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
489  	fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
490  
491  	while ((event = trace_find_next_event(pevent, event))) {
492  		fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
493  		fprintf(ofp, "\tmy (");
494  
495  		fprintf(ofp, "$event_name, ");
496  		fprintf(ofp, "$context, ");
497  		fprintf(ofp, "$common_cpu, ");
498  		fprintf(ofp, "$common_secs, ");
499  		fprintf(ofp, "$common_nsecs,\n");
500  		fprintf(ofp, "\t    $common_pid, ");
501  		fprintf(ofp, "$common_comm,\n\t    ");
502  
503  		not_first = 0;
504  		count = 0;
505  
506  		for (f = event->format.fields; f; f = f->next) {
507  			if (not_first++)
508  				fprintf(ofp, ", ");
509  			if (++count % 5 == 0)
510  				fprintf(ofp, "\n\t    ");
511  
512  			fprintf(ofp, "$%s", f->name);
513  		}
514  		fprintf(ofp, ") = @_;\n\n");
515  
516  		fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
517  			"$common_secs, $common_nsecs,\n\t             "
518  			"$common_pid, $common_comm);\n\n");
519  
520  		fprintf(ofp, "\tprintf(\"");
521  
522  		not_first = 0;
523  		count = 0;
524  
525  		for (f = event->format.fields; f; f = f->next) {
526  			if (not_first++)
527  				fprintf(ofp, ", ");
528  			if (count && count % 4 == 0) {
529  				fprintf(ofp, "\".\n\t       \"");
530  			}
531  			count++;
532  
533  			fprintf(ofp, "%s=", f->name);
534  			if (f->flags & FIELD_IS_STRING ||
535  			    f->flags & FIELD_IS_FLAG ||
536  			    f->flags & FIELD_IS_SYMBOLIC)
537  				fprintf(ofp, "%%s");
538  			else if (f->flags & FIELD_IS_SIGNED)
539  				fprintf(ofp, "%%d");
540  			else
541  				fprintf(ofp, "%%u");
542  		}
543  
544  		fprintf(ofp, "\\n\",\n\t       ");
545  
546  		not_first = 0;
547  		count = 0;
548  
549  		for (f = event->format.fields; f; f = f->next) {
550  			if (not_first++)
551  				fprintf(ofp, ", ");
552  
553  			if (++count % 5 == 0)
554  				fprintf(ofp, "\n\t       ");
555  
556  			if (f->flags & FIELD_IS_FLAG) {
557  				if ((count - 1) % 5 != 0) {
558  					fprintf(ofp, "\n\t       ");
559  					count = 4;
560  				}
561  				fprintf(ofp, "flag_str(\"");
562  				fprintf(ofp, "%s::%s\", ", event->system,
563  					event->name);
564  				fprintf(ofp, "\"%s\", $%s)", f->name,
565  					f->name);
566  			} else if (f->flags & FIELD_IS_SYMBOLIC) {
567  				if ((count - 1) % 5 != 0) {
568  					fprintf(ofp, "\n\t       ");
569  					count = 4;
570  				}
571  				fprintf(ofp, "symbol_str(\"");
572  				fprintf(ofp, "%s::%s\", ", event->system,
573  					event->name);
574  				fprintf(ofp, "\"%s\", $%s)", f->name,
575  					f->name);
576  			} else
577  				fprintf(ofp, "$%s", f->name);
578  		}
579  
580  		fprintf(ofp, ");\n");
581  		fprintf(ofp, "}\n\n");
582  	}
583  
584  	fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
585  		"$common_cpu, $common_secs, $common_nsecs,\n\t    "
586  		"$common_pid, $common_comm) = @_;\n\n");
587  
588  	fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
589  		"$common_secs, $common_nsecs,\n\t             $common_pid, "
590  		"$common_comm);\n}\n\n");
591  
592  	fprintf(ofp, "sub print_header\n{\n"
593  		"\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
594  		"\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t       "
595  		"$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}\n");
596  
597  	fprintf(ofp,
598  		"\n# Packed byte string args of process_event():\n"
599  		"#\n"
600  		"# $event:\tunion perf_event\tutil/event.h\n"
601  		"# $attr:\tstruct perf_event_attr\tlinux/perf_event.h\n"
602  		"# $sample:\tstruct perf_sample\tutil/event.h\n"
603  		"# $raw_data:\tperf_sample->raw_data\tutil/event.h\n"
604  		"\n"
605  		"sub process_event\n"
606  		"{\n"
607  		"\tmy ($event, $attr, $sample, $raw_data) = @_;\n"
608  		"\n"
609  		"\tmy @event\t= unpack(\"LSS\", $event);\n"
610  		"\tmy @attr\t= unpack(\"LLQQQQQLLQQ\", $attr);\n"
611  		"\tmy @sample\t= unpack(\"QLLQQQQQLL\", $sample);\n"
612  		"\tmy @raw_data\t= unpack(\"C*\", $raw_data);\n"
613  		"\n"
614  		"\tuse Data::Dumper;\n"
615  		"\tprint Dumper \\@event, \\@attr, \\@sample, \\@raw_data;\n"
616  		"}\n");
617  
618  	fclose(ofp);
619  
620  	fprintf(stderr, "generated Perl script: %s\n", fname);
621  
622  	return 0;
623  }
624  
625  struct scripting_ops perl_scripting_ops = {
626  	.name = "Perl",
627  	.start_script = perl_start_script,
628  	.flush_script = perl_flush_script,
629  	.stop_script = perl_stop_script,
630  	.process_event = perl_process_event,
631  	.generate_script = perl_generate_script,
632  };
633