xref: /linux/tools/perf/util/scripting-engines/trace-event-perl.c (revision 5a0e3ad6af8660be21ca98a971cd00f331318c05)
1  /*
2   * trace-event-perl.  Feed perf trace 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  
28  #include "../../perf.h"
29  #include "../util.h"
30  #include "../trace-event.h"
31  
32  #include <EXTERN.h>
33  #include <perl.h>
34  
35  void boot_Perf__Trace__Context(pTHX_ CV *cv);
36  void boot_DynaLoader(pTHX_ CV *cv);
37  typedef PerlInterpreter * INTERP;
38  
39  void xs_init(pTHX);
40  
41  void xs_init(pTHX)
42  {
43  	const char *file = __FILE__;
44  	dXSUB_SYS;
45  
46  	newXS("Perf::Trace::Context::bootstrap", boot_Perf__Trace__Context,
47  	      file);
48  	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
49  }
50  
51  INTERP my_perl;
52  
53  #define FTRACE_MAX_EVENT				\
54  	((1 << (sizeof(unsigned short) * 8)) - 1)
55  
56  struct event *events[FTRACE_MAX_EVENT];
57  
58  extern struct scripting_context *scripting_context;
59  
60  static char *cur_field_name;
61  static int zero_flag_atom;
62  
63  static void define_symbolic_value(const char *ev_name,
64  				  const char *field_name,
65  				  const char *field_value,
66  				  const char *field_str)
67  {
68  	unsigned long long value;
69  	dSP;
70  
71  	value = eval_flag(field_value);
72  
73  	ENTER;
74  	SAVETMPS;
75  	PUSHMARK(SP);
76  
77  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
78  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
79  	XPUSHs(sv_2mortal(newSVuv(value)));
80  	XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
81  
82  	PUTBACK;
83  	if (get_cv("main::define_symbolic_value", 0))
84  		call_pv("main::define_symbolic_value", G_SCALAR);
85  	SPAGAIN;
86  	PUTBACK;
87  	FREETMPS;
88  	LEAVE;
89  }
90  
91  static void define_symbolic_values(struct print_flag_sym *field,
92  				   const char *ev_name,
93  				   const char *field_name)
94  {
95  	define_symbolic_value(ev_name, field_name, field->value, field->str);
96  	if (field->next)
97  		define_symbolic_values(field->next, ev_name, field_name);
98  }
99  
100  static void define_symbolic_field(const char *ev_name,
101  				  const char *field_name)
102  {
103  	dSP;
104  
105  	ENTER;
106  	SAVETMPS;
107  	PUSHMARK(SP);
108  
109  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
110  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
111  
112  	PUTBACK;
113  	if (get_cv("main::define_symbolic_field", 0))
114  		call_pv("main::define_symbolic_field", G_SCALAR);
115  	SPAGAIN;
116  	PUTBACK;
117  	FREETMPS;
118  	LEAVE;
119  }
120  
121  static void define_flag_value(const char *ev_name,
122  			      const char *field_name,
123  			      const char *field_value,
124  			      const char *field_str)
125  {
126  	unsigned long long value;
127  	dSP;
128  
129  	value = eval_flag(field_value);
130  
131  	ENTER;
132  	SAVETMPS;
133  	PUSHMARK(SP);
134  
135  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
136  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
137  	XPUSHs(sv_2mortal(newSVuv(value)));
138  	XPUSHs(sv_2mortal(newSVpv(field_str, 0)));
139  
140  	PUTBACK;
141  	if (get_cv("main::define_flag_value", 0))
142  		call_pv("main::define_flag_value", G_SCALAR);
143  	SPAGAIN;
144  	PUTBACK;
145  	FREETMPS;
146  	LEAVE;
147  }
148  
149  static void define_flag_values(struct print_flag_sym *field,
150  			       const char *ev_name,
151  			       const char *field_name)
152  {
153  	define_flag_value(ev_name, field_name, field->value, field->str);
154  	if (field->next)
155  		define_flag_values(field->next, ev_name, field_name);
156  }
157  
158  static void define_flag_field(const char *ev_name,
159  			      const char *field_name,
160  			      const char *delim)
161  {
162  	dSP;
163  
164  	ENTER;
165  	SAVETMPS;
166  	PUSHMARK(SP);
167  
168  	XPUSHs(sv_2mortal(newSVpv(ev_name, 0)));
169  	XPUSHs(sv_2mortal(newSVpv(field_name, 0)));
170  	XPUSHs(sv_2mortal(newSVpv(delim, 0)));
171  
172  	PUTBACK;
173  	if (get_cv("main::define_flag_field", 0))
174  		call_pv("main::define_flag_field", G_SCALAR);
175  	SPAGAIN;
176  	PUTBACK;
177  	FREETMPS;
178  	LEAVE;
179  }
180  
181  static void define_event_symbols(struct event *event,
182  				 const char *ev_name,
183  				 struct print_arg *args)
184  {
185  	switch (args->type) {
186  	case PRINT_NULL:
187  		break;
188  	case PRINT_ATOM:
189  		define_flag_value(ev_name, cur_field_name, "0",
190  				  args->atom.atom);
191  		zero_flag_atom = 0;
192  		break;
193  	case PRINT_FIELD:
194  		if (cur_field_name)
195  			free(cur_field_name);
196  		cur_field_name = strdup(args->field.name);
197  		break;
198  	case PRINT_FLAGS:
199  		define_event_symbols(event, ev_name, args->flags.field);
200  		define_flag_field(ev_name, cur_field_name, args->flags.delim);
201  		define_flag_values(args->flags.flags, ev_name, cur_field_name);
202  		break;
203  	case PRINT_SYMBOL:
204  		define_event_symbols(event, ev_name, args->symbol.field);
205  		define_symbolic_field(ev_name, cur_field_name);
206  		define_symbolic_values(args->symbol.symbols, ev_name,
207  				       cur_field_name);
208  		break;
209  	case PRINT_STRING:
210  		break;
211  	case PRINT_TYPE:
212  		define_event_symbols(event, ev_name, args->typecast.item);
213  		break;
214  	case PRINT_OP:
215  		if (strcmp(args->op.op, ":") == 0)
216  			zero_flag_atom = 1;
217  		define_event_symbols(event, ev_name, args->op.left);
218  		define_event_symbols(event, ev_name, args->op.right);
219  		break;
220  	default:
221  		/* we should warn... */
222  		return;
223  	}
224  
225  	if (args->next)
226  		define_event_symbols(event, ev_name, args->next);
227  }
228  
229  static inline struct event *find_cache_event(int type)
230  {
231  	static char ev_name[256];
232  	struct event *event;
233  
234  	if (events[type])
235  		return events[type];
236  
237  	events[type] = event = trace_find_event(type);
238  	if (!event)
239  		return NULL;
240  
241  	sprintf(ev_name, "%s::%s", event->system, event->name);
242  
243  	define_event_symbols(event, ev_name, event->print_fmt.args);
244  
245  	return event;
246  }
247  
248  static void perl_process_event(int cpu, void *data,
249  			       int size __unused,
250  			       unsigned long long nsecs, char *comm)
251  {
252  	struct format_field *field;
253  	static char handler[256];
254  	unsigned long long val;
255  	unsigned long s, ns;
256  	struct event *event;
257  	int type;
258  	int pid;
259  
260  	dSP;
261  
262  	type = trace_parse_common_type(data);
263  
264  	event = find_cache_event(type);
265  	if (!event)
266  		die("ug! no event found for type %d", type);
267  
268  	pid = trace_parse_common_pid(data);
269  
270  	sprintf(handler, "%s::%s", event->system, event->name);
271  
272  	s = nsecs / NSECS_PER_SEC;
273  	ns = nsecs - s * NSECS_PER_SEC;
274  
275  	scripting_context->event_data = data;
276  
277  	ENTER;
278  	SAVETMPS;
279  	PUSHMARK(SP);
280  
281  	XPUSHs(sv_2mortal(newSVpv(handler, 0)));
282  	XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
283  	XPUSHs(sv_2mortal(newSVuv(cpu)));
284  	XPUSHs(sv_2mortal(newSVuv(s)));
285  	XPUSHs(sv_2mortal(newSVuv(ns)));
286  	XPUSHs(sv_2mortal(newSViv(pid)));
287  	XPUSHs(sv_2mortal(newSVpv(comm, 0)));
288  
289  	/* common fields other than pid can be accessed via xsub fns */
290  
291  	for (field = event->format.fields; field; field = field->next) {
292  		if (field->flags & FIELD_IS_STRING) {
293  			int offset;
294  			if (field->flags & FIELD_IS_DYNAMIC) {
295  				offset = *(int *)(data + field->offset);
296  				offset &= 0xffff;
297  			} else
298  				offset = field->offset;
299  			XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
300  		} else { /* FIELD_IS_NUMERIC */
301  			val = read_size(data + field->offset, field->size);
302  			if (field->flags & FIELD_IS_SIGNED) {
303  				XPUSHs(sv_2mortal(newSViv(val)));
304  			} else {
305  				XPUSHs(sv_2mortal(newSVuv(val)));
306  			}
307  		}
308  	}
309  
310  	PUTBACK;
311  
312  	if (get_cv(handler, 0))
313  		call_pv(handler, G_SCALAR);
314  	else if (get_cv("main::trace_unhandled", 0)) {
315  		XPUSHs(sv_2mortal(newSVpv(handler, 0)));
316  		XPUSHs(sv_2mortal(newSViv(PTR2IV(scripting_context))));
317  		XPUSHs(sv_2mortal(newSVuv(cpu)));
318  		XPUSHs(sv_2mortal(newSVuv(nsecs)));
319  		XPUSHs(sv_2mortal(newSViv(pid)));
320  		XPUSHs(sv_2mortal(newSVpv(comm, 0)));
321  		call_pv("main::trace_unhandled", G_SCALAR);
322  	}
323  	SPAGAIN;
324  	PUTBACK;
325  	FREETMPS;
326  	LEAVE;
327  }
328  
329  static void run_start_sub(void)
330  {
331  	dSP; /* access to Perl stack */
332  	PUSHMARK(SP);
333  
334  	if (get_cv("main::trace_begin", 0))
335  		call_pv("main::trace_begin", G_DISCARD | G_NOARGS);
336  }
337  
338  /*
339   * Start trace script
340   */
341  static int perl_start_script(const char *script, int argc, const char **argv)
342  {
343  	const char **command_line;
344  	int i, err = 0;
345  
346  	command_line = malloc((argc + 2) * sizeof(const char *));
347  	command_line[0] = "";
348  	command_line[1] = script;
349  	for (i = 2; i < argc + 2; i++)
350  		command_line[i] = argv[i - 2];
351  
352  	my_perl = perl_alloc();
353  	perl_construct(my_perl);
354  
355  	if (perl_parse(my_perl, xs_init, argc + 2, (char **)command_line,
356  		       (char **)NULL)) {
357  		err = -1;
358  		goto error;
359  	}
360  
361  	if (perl_run(my_perl)) {
362  		err = -1;
363  		goto error;
364  	}
365  
366  	if (SvTRUE(ERRSV)) {
367  		err = -1;
368  		goto error;
369  	}
370  
371  	run_start_sub();
372  
373  	free(command_line);
374  	fprintf(stderr, "perf trace started with Perl script %s\n\n", script);
375  	return 0;
376  error:
377  	perl_free(my_perl);
378  	free(command_line);
379  
380  	return err;
381  }
382  
383  /*
384   * Stop trace script
385   */
386  static int perl_stop_script(void)
387  {
388  	dSP; /* access to Perl stack */
389  	PUSHMARK(SP);
390  
391  	if (get_cv("main::trace_end", 0))
392  		call_pv("main::trace_end", G_DISCARD | G_NOARGS);
393  
394  	perl_destruct(my_perl);
395  	perl_free(my_perl);
396  
397  	fprintf(stderr, "\nperf trace Perl script stopped\n");
398  
399  	return 0;
400  }
401  
402  static int perl_generate_script(const char *outfile)
403  {
404  	struct event *event = NULL;
405  	struct format_field *f;
406  	char fname[PATH_MAX];
407  	int not_first, count;
408  	FILE *ofp;
409  
410  	sprintf(fname, "%s.pl", outfile);
411  	ofp = fopen(fname, "w");
412  	if (ofp == NULL) {
413  		fprintf(stderr, "couldn't open %s\n", fname);
414  		return -1;
415  	}
416  
417  	fprintf(ofp, "# perf trace event handlers, "
418  		"generated by perf trace -g perl\n");
419  
420  	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
421  		" License version 2\n\n");
422  
423  	fprintf(ofp, "# The common_* event handler fields are the most useful "
424  		"fields common to\n");
425  
426  	fprintf(ofp, "# all events.  They don't necessarily correspond to "
427  		"the 'common_*' fields\n");
428  
429  	fprintf(ofp, "# in the format files.  Those fields not available as "
430  		"handler params can\n");
431  
432  	fprintf(ofp, "# be retrieved using Perl functions of the form "
433  		"common_*($context).\n");
434  
435  	fprintf(ofp, "# See Context.pm for the list of available "
436  		"functions.\n\n");
437  
438  	fprintf(ofp, "use lib \"$ENV{'PERF_EXEC_PATH'}/scripts/perl/"
439  		"Perf-Trace-Util/lib\";\n");
440  
441  	fprintf(ofp, "use lib \"./Perf-Trace-Util/lib\";\n");
442  	fprintf(ofp, "use Perf::Trace::Core;\n");
443  	fprintf(ofp, "use Perf::Trace::Context;\n");
444  	fprintf(ofp, "use Perf::Trace::Util;\n\n");
445  
446  	fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
447  	fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
448  
449  	while ((event = trace_find_next_event(event))) {
450  		fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
451  		fprintf(ofp, "\tmy (");
452  
453  		fprintf(ofp, "$event_name, ");
454  		fprintf(ofp, "$context, ");
455  		fprintf(ofp, "$common_cpu, ");
456  		fprintf(ofp, "$common_secs, ");
457  		fprintf(ofp, "$common_nsecs,\n");
458  		fprintf(ofp, "\t    $common_pid, ");
459  		fprintf(ofp, "$common_comm,\n\t    ");
460  
461  		not_first = 0;
462  		count = 0;
463  
464  		for (f = event->format.fields; f; f = f->next) {
465  			if (not_first++)
466  				fprintf(ofp, ", ");
467  			if (++count % 5 == 0)
468  				fprintf(ofp, "\n\t    ");
469  
470  			fprintf(ofp, "$%s", f->name);
471  		}
472  		fprintf(ofp, ") = @_;\n\n");
473  
474  		fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
475  			"$common_secs, $common_nsecs,\n\t             "
476  			"$common_pid, $common_comm);\n\n");
477  
478  		fprintf(ofp, "\tprintf(\"");
479  
480  		not_first = 0;
481  		count = 0;
482  
483  		for (f = event->format.fields; f; f = f->next) {
484  			if (not_first++)
485  				fprintf(ofp, ", ");
486  			if (count && count % 4 == 0) {
487  				fprintf(ofp, "\".\n\t       \"");
488  			}
489  			count++;
490  
491  			fprintf(ofp, "%s=", f->name);
492  			if (f->flags & FIELD_IS_STRING ||
493  			    f->flags & FIELD_IS_FLAG ||
494  			    f->flags & FIELD_IS_SYMBOLIC)
495  				fprintf(ofp, "%%s");
496  			else if (f->flags & FIELD_IS_SIGNED)
497  				fprintf(ofp, "%%d");
498  			else
499  				fprintf(ofp, "%%u");
500  		}
501  
502  		fprintf(ofp, "\\n\",\n\t       ");
503  
504  		not_first = 0;
505  		count = 0;
506  
507  		for (f = event->format.fields; f; f = f->next) {
508  			if (not_first++)
509  				fprintf(ofp, ", ");
510  
511  			if (++count % 5 == 0)
512  				fprintf(ofp, "\n\t       ");
513  
514  			if (f->flags & FIELD_IS_FLAG) {
515  				if ((count - 1) % 5 != 0) {
516  					fprintf(ofp, "\n\t       ");
517  					count = 4;
518  				}
519  				fprintf(ofp, "flag_str(\"");
520  				fprintf(ofp, "%s::%s\", ", event->system,
521  					event->name);
522  				fprintf(ofp, "\"%s\", $%s)", f->name,
523  					f->name);
524  			} else if (f->flags & FIELD_IS_SYMBOLIC) {
525  				if ((count - 1) % 5 != 0) {
526  					fprintf(ofp, "\n\t       ");
527  					count = 4;
528  				}
529  				fprintf(ofp, "symbol_str(\"");
530  				fprintf(ofp, "%s::%s\", ", event->system,
531  					event->name);
532  				fprintf(ofp, "\"%s\", $%s)", f->name,
533  					f->name);
534  			} else
535  				fprintf(ofp, "$%s", f->name);
536  		}
537  
538  		fprintf(ofp, ");\n");
539  		fprintf(ofp, "}\n\n");
540  	}
541  
542  	fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
543  		"$common_cpu, $common_secs, $common_nsecs,\n\t    "
544  		"$common_pid, $common_comm) = @_;\n\n");
545  
546  	fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
547  		"$common_secs, $common_nsecs,\n\t             $common_pid, "
548  		"$common_comm);\n}\n\n");
549  
550  	fprintf(ofp, "sub print_header\n{\n"
551  		"\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
552  		"\tprintf(\"%%-20s %%5u %%05u.%%09u %%8u %%-20s \",\n\t       "
553  		"$event_name, $cpu, $secs, $nsecs, $pid, $comm);\n}");
554  
555  	fclose(ofp);
556  
557  	fprintf(stderr, "generated Perl script: %s\n", fname);
558  
559  	return 0;
560  }
561  
562  struct scripting_ops perl_scripting_ops = {
563  	.name = "Perl",
564  	.start_script = perl_start_script,
565  	.stop_script = perl_stop_script,
566  	.process_event = perl_process_event,
567  	.generate_script = perl_generate_script,
568  };
569