1/*
2 * trace-event-python.  Feed trace events to an embedded Python interpreter.
3 *
4 * Copyright (C) 2010 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 <Python.h>
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <errno.h>
28
29#include "../../perf.h"
30#include "../evsel.h"
31#include "../util.h"
32#include "../event.h"
33#include "../thread.h"
34#include "../trace-event.h"
35
36PyMODINIT_FUNC initperf_trace_context(void);
37
38#define FTRACE_MAX_EVENT				\
39	((1 << (sizeof(unsigned short) * 8)) - 1)
40
41struct event_format *events[FTRACE_MAX_EVENT];
42
43#define MAX_FIELDS	64
44#define N_COMMON_FIELDS	7
45
46extern struct scripting_context *scripting_context;
47
48static char *cur_field_name;
49static int zero_flag_atom;
50
51static PyObject *main_module, *main_dict;
52
53static void handler_call_die(const char *handler_name)
54{
55	PyErr_Print();
56	Py_FatalError("problem in Python trace event handler");
57}
58
59/*
60 * Insert val into into the dictionary and decrement the reference counter.
61 * This is necessary for dictionaries since PyDict_SetItemString() does not
62 * steal a reference, as opposed to PyTuple_SetItem().
63 */
64static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val)
65{
66	PyDict_SetItemString(dict, key, val);
67	Py_DECREF(val);
68}
69
70static void define_value(enum print_arg_type field_type,
71			 const char *ev_name,
72			 const char *field_name,
73			 const char *field_value,
74			 const char *field_str)
75{
76	const char *handler_name = "define_flag_value";
77	PyObject *handler, *t, *retval;
78	unsigned long long value;
79	unsigned n = 0;
80
81	if (field_type == PRINT_SYMBOL)
82		handler_name = "define_symbolic_value";
83
84	t = PyTuple_New(4);
85	if (!t)
86		Py_FatalError("couldn't create Python tuple");
87
88	value = eval_flag(field_value);
89
90	PyTuple_SetItem(t, n++, PyString_FromString(ev_name));
91	PyTuple_SetItem(t, n++, PyString_FromString(field_name));
92	PyTuple_SetItem(t, n++, PyInt_FromLong(value));
93	PyTuple_SetItem(t, n++, PyString_FromString(field_str));
94
95	handler = PyDict_GetItemString(main_dict, handler_name);
96	if (handler && PyCallable_Check(handler)) {
97		retval = PyObject_CallObject(handler, t);
98		if (retval == NULL)
99			handler_call_die(handler_name);
100	}
101
102	Py_DECREF(t);
103}
104
105static void define_values(enum print_arg_type field_type,
106			  struct print_flag_sym *field,
107			  const char *ev_name,
108			  const char *field_name)
109{
110	define_value(field_type, ev_name, field_name, field->value,
111		     field->str);
112
113	if (field->next)
114		define_values(field_type, field->next, ev_name, field_name);
115}
116
117static void define_field(enum print_arg_type field_type,
118			 const char *ev_name,
119			 const char *field_name,
120			 const char *delim)
121{
122	const char *handler_name = "define_flag_field";
123	PyObject *handler, *t, *retval;
124	unsigned n = 0;
125
126	if (field_type == PRINT_SYMBOL)
127		handler_name = "define_symbolic_field";
128
129	if (field_type == PRINT_FLAGS)
130		t = PyTuple_New(3);
131	else
132		t = PyTuple_New(2);
133	if (!t)
134		Py_FatalError("couldn't create Python tuple");
135
136	PyTuple_SetItem(t, n++, PyString_FromString(ev_name));
137	PyTuple_SetItem(t, n++, PyString_FromString(field_name));
138	if (field_type == PRINT_FLAGS)
139		PyTuple_SetItem(t, n++, PyString_FromString(delim));
140
141	handler = PyDict_GetItemString(main_dict, handler_name);
142	if (handler && PyCallable_Check(handler)) {
143		retval = PyObject_CallObject(handler, t);
144		if (retval == NULL)
145			handler_call_die(handler_name);
146	}
147
148	Py_DECREF(t);
149}
150
151static void define_event_symbols(struct event_format *event,
152				 const char *ev_name,
153				 struct print_arg *args)
154{
155	switch (args->type) {
156	case PRINT_NULL:
157		break;
158	case PRINT_ATOM:
159		define_value(PRINT_FLAGS, ev_name, cur_field_name, "0",
160			     args->atom.atom);
161		zero_flag_atom = 0;
162		break;
163	case PRINT_FIELD:
164		if (cur_field_name)
165			free(cur_field_name);
166		cur_field_name = strdup(args->field.name);
167		break;
168	case PRINT_FLAGS:
169		define_event_symbols(event, ev_name, args->flags.field);
170		define_field(PRINT_FLAGS, ev_name, cur_field_name,
171			     args->flags.delim);
172		define_values(PRINT_FLAGS, args->flags.flags, ev_name,
173			      cur_field_name);
174		break;
175	case PRINT_SYMBOL:
176		define_event_symbols(event, ev_name, args->symbol.field);
177		define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL);
178		define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
179			      cur_field_name);
180		break;
181	case PRINT_HEX:
182		define_event_symbols(event, ev_name, args->hex.field);
183		define_event_symbols(event, ev_name, args->hex.size);
184		break;
185	case PRINT_STRING:
186		break;
187	case PRINT_TYPE:
188		define_event_symbols(event, ev_name, args->typecast.item);
189		break;
190	case PRINT_OP:
191		if (strcmp(args->op.op, ":") == 0)
192			zero_flag_atom = 1;
193		define_event_symbols(event, ev_name, args->op.left);
194		define_event_symbols(event, ev_name, args->op.right);
195		break;
196	default:
197		/* gcc warns for these? */
198	case PRINT_BSTRING:
199	case PRINT_DYNAMIC_ARRAY:
200	case PRINT_FUNC:
201		/* we should warn... */
202		return;
203	}
204
205	if (args->next)
206		define_event_symbols(event, ev_name, args->next);
207}
208
209static inline struct event_format *find_cache_event(struct perf_evsel *evsel)
210{
211	static char ev_name[256];
212	struct event_format *event;
213	int type = evsel->attr.config;
214
215	/*
216 	 * XXX: Do we really need to cache this since now we have evsel->tp_format
217 	 * cached already? Need to re-read this "cache" routine that as well calls
218 	 * define_event_symbols() :-\
219 	 */
220	if (events[type])
221		return events[type];
222
223	events[type] = event = evsel->tp_format;
224	if (!event)
225		return NULL;
226
227	sprintf(ev_name, "%s__%s", event->system, event->name);
228
229	define_event_symbols(event, ev_name, event->print_fmt.args);
230
231	return event;
232}
233
234static void python_process_tracepoint(union perf_event *perf_event
235				      __maybe_unused,
236				 struct perf_sample *sample,
237				 struct perf_evsel *evsel,
238				 struct machine *machine __maybe_unused,
239				 struct thread *thread,
240				 struct addr_location *al)
241{
242	PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
243	static char handler_name[256];
244	struct format_field *field;
245	unsigned long long val;
246	unsigned long s, ns;
247	struct event_format *event;
248	unsigned n = 0;
249	int pid;
250	int cpu = sample->cpu;
251	void *data = sample->raw_data;
252	unsigned long long nsecs = sample->time;
253	char *comm = thread->comm;
254
255	t = PyTuple_New(MAX_FIELDS);
256	if (!t)
257		Py_FatalError("couldn't create Python tuple");
258
259	event = find_cache_event(evsel);
260	if (!event)
261		die("ug! no event found for type %d", (int)evsel->attr.config);
262
263	pid = raw_field_value(event, "common_pid", data);
264
265	sprintf(handler_name, "%s__%s", event->system, event->name);
266
267	handler = PyDict_GetItemString(main_dict, handler_name);
268	if (handler && !PyCallable_Check(handler))
269		handler = NULL;
270	if (!handler) {
271		dict = PyDict_New();
272		if (!dict)
273			Py_FatalError("couldn't create Python dict");
274	}
275	s = nsecs / NSECS_PER_SEC;
276	ns = nsecs - s * NSECS_PER_SEC;
277
278	scripting_context->event_data = data;
279	scripting_context->pevent = evsel->tp_format->pevent;
280
281	context = PyCObject_FromVoidPtr(scripting_context, NULL);
282
283	PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
284	PyTuple_SetItem(t, n++, context);
285
286	if (handler) {
287		PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
288		PyTuple_SetItem(t, n++, PyInt_FromLong(s));
289		PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
290		PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
291		PyTuple_SetItem(t, n++, PyString_FromString(comm));
292	} else {
293		pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
294		pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
295		pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
296		pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
297		pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
298	}
299	for (field = event->format.fields; field; field = field->next) {
300		if (field->flags & FIELD_IS_STRING) {
301			int offset;
302			if (field->flags & FIELD_IS_DYNAMIC) {
303				offset = *(int *)(data + field->offset);
304				offset &= 0xffff;
305			} else
306				offset = field->offset;
307			obj = PyString_FromString((char *)data + offset);
308		} else { /* FIELD_IS_NUMERIC */
309			val = read_size(event, data + field->offset,
310					field->size);
311			if (field->flags & FIELD_IS_SIGNED) {
312				if ((long long)val >= LONG_MIN &&
313				    (long long)val <= LONG_MAX)
314					obj = PyInt_FromLong(val);
315				else
316					obj = PyLong_FromLongLong(val);
317			} else {
318				if (val <= LONG_MAX)
319					obj = PyInt_FromLong(val);
320				else
321					obj = PyLong_FromUnsignedLongLong(val);
322			}
323		}
324		if (handler)
325			PyTuple_SetItem(t, n++, obj);
326		else
327			pydict_set_item_string_decref(dict, field->name, obj);
328
329	}
330	if (!handler)
331		PyTuple_SetItem(t, n++, dict);
332
333	if (_PyTuple_Resize(&t, n) == -1)
334		Py_FatalError("error resizing Python tuple");
335
336	if (handler) {
337		retval = PyObject_CallObject(handler, t);
338		if (retval == NULL)
339			handler_call_die(handler_name);
340	} else {
341		handler = PyDict_GetItemString(main_dict, "trace_unhandled");
342		if (handler && PyCallable_Check(handler)) {
343
344			retval = PyObject_CallObject(handler, t);
345			if (retval == NULL)
346				handler_call_die("trace_unhandled");
347		}
348		Py_DECREF(dict);
349	}
350
351	Py_DECREF(t);
352}
353
354static void python_process_general_event(union perf_event *perf_event
355					 __maybe_unused,
356					 struct perf_sample *sample,
357					 struct perf_evsel *evsel,
358					 struct machine *machine __maybe_unused,
359					 struct thread *thread,
360					 struct addr_location *al)
361{
362	PyObject *handler, *retval, *t, *dict;
363	static char handler_name[64];
364	unsigned n = 0;
365
366	/*
367	 * Use the MAX_FIELDS to make the function expandable, though
368	 * currently there is only one item for the tuple.
369	 */
370	t = PyTuple_New(MAX_FIELDS);
371	if (!t)
372		Py_FatalError("couldn't create Python tuple");
373
374	dict = PyDict_New();
375	if (!dict)
376		Py_FatalError("couldn't create Python dictionary");
377
378	snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
379
380	handler = PyDict_GetItemString(main_dict, handler_name);
381	if (!handler || !PyCallable_Check(handler))
382		goto exit;
383
384	pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
385	pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
386			(const char *)&evsel->attr, sizeof(evsel->attr)));
387	pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize(
388			(const char *)sample, sizeof(*sample)));
389	pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
390			(const char *)sample->raw_data, sample->raw_size));
391	pydict_set_item_string_decref(dict, "comm",
392			PyString_FromString(thread->comm));
393	if (al->map) {
394		pydict_set_item_string_decref(dict, "dso",
395			PyString_FromString(al->map->dso->name));
396	}
397	if (al->sym) {
398		pydict_set_item_string_decref(dict, "symbol",
399			PyString_FromString(al->sym->name));
400	}
401
402	PyTuple_SetItem(t, n++, dict);
403	if (_PyTuple_Resize(&t, n) == -1)
404		Py_FatalError("error resizing Python tuple");
405
406	retval = PyObject_CallObject(handler, t);
407	if (retval == NULL)
408		handler_call_die(handler_name);
409exit:
410	Py_DECREF(dict);
411	Py_DECREF(t);
412}
413
414static void python_process_event(union perf_event *perf_event,
415				 struct perf_sample *sample,
416				 struct perf_evsel *evsel,
417				 struct machine *machine,
418				 struct thread *thread,
419				 struct addr_location *al)
420{
421	switch (evsel->attr.type) {
422	case PERF_TYPE_TRACEPOINT:
423		python_process_tracepoint(perf_event, sample, evsel,
424					  machine, thread, al);
425		break;
426	/* Reserve for future process_hw/sw/raw APIs */
427	default:
428		python_process_general_event(perf_event, sample, evsel,
429					     machine, thread, al);
430	}
431}
432
433static int run_start_sub(void)
434{
435	PyObject *handler, *retval;
436	int err = 0;
437
438	main_module = PyImport_AddModule("__main__");
439	if (main_module == NULL)
440		return -1;
441	Py_INCREF(main_module);
442
443	main_dict = PyModule_GetDict(main_module);
444	if (main_dict == NULL) {
445		err = -1;
446		goto error;
447	}
448	Py_INCREF(main_dict);
449
450	handler = PyDict_GetItemString(main_dict, "trace_begin");
451	if (handler == NULL || !PyCallable_Check(handler))
452		goto out;
453
454	retval = PyObject_CallObject(handler, NULL);
455	if (retval == NULL)
456		handler_call_die("trace_begin");
457
458	Py_DECREF(retval);
459	return err;
460error:
461	Py_XDECREF(main_dict);
462	Py_XDECREF(main_module);
463out:
464	return err;
465}
466
467/*
468 * Start trace script
469 */
470static int python_start_script(const char *script, int argc, const char **argv)
471{
472	const char **command_line;
473	char buf[PATH_MAX];
474	int i, err = 0;
475	FILE *fp;
476
477	command_line = malloc((argc + 1) * sizeof(const char *));
478	command_line[0] = script;
479	for (i = 1; i < argc + 1; i++)
480		command_line[i] = argv[i - 1];
481
482	Py_Initialize();
483
484	initperf_trace_context();
485
486	PySys_SetArgv(argc + 1, (char **)command_line);
487
488	fp = fopen(script, "r");
489	if (!fp) {
490		sprintf(buf, "Can't open python script \"%s\"", script);
491		perror(buf);
492		err = -1;
493		goto error;
494	}
495
496	err = PyRun_SimpleFile(fp, script);
497	if (err) {
498		fprintf(stderr, "Error running python script %s\n", script);
499		goto error;
500	}
501
502	err = run_start_sub();
503	if (err) {
504		fprintf(stderr, "Error starting python script %s\n", script);
505		goto error;
506	}
507
508	free(command_line);
509
510	return err;
511error:
512	Py_Finalize();
513	free(command_line);
514
515	return err;
516}
517
518/*
519 * Stop trace script
520 */
521static int python_stop_script(void)
522{
523	PyObject *handler, *retval;
524	int err = 0;
525
526	handler = PyDict_GetItemString(main_dict, "trace_end");
527	if (handler == NULL || !PyCallable_Check(handler))
528		goto out;
529
530	retval = PyObject_CallObject(handler, NULL);
531	if (retval == NULL)
532		handler_call_die("trace_end");
533	else
534		Py_DECREF(retval);
535out:
536	Py_XDECREF(main_dict);
537	Py_XDECREF(main_module);
538	Py_Finalize();
539
540	return err;
541}
542
543static int python_generate_script(struct pevent *pevent, const char *outfile)
544{
545	struct event_format *event = NULL;
546	struct format_field *f;
547	char fname[PATH_MAX];
548	int not_first, count;
549	FILE *ofp;
550
551	sprintf(fname, "%s.py", outfile);
552	ofp = fopen(fname, "w");
553	if (ofp == NULL) {
554		fprintf(stderr, "couldn't open %s\n", fname);
555		return -1;
556	}
557	fprintf(ofp, "# perf script event handlers, "
558		"generated by perf script -g python\n");
559
560	fprintf(ofp, "# Licensed under the terms of the GNU GPL"
561		" License version 2\n\n");
562
563	fprintf(ofp, "# The common_* event handler fields are the most useful "
564		"fields common to\n");
565
566	fprintf(ofp, "# all events.  They don't necessarily correspond to "
567		"the 'common_*' fields\n");
568
569	fprintf(ofp, "# in the format files.  Those fields not available as "
570		"handler params can\n");
571
572	fprintf(ofp, "# be retrieved using Python functions of the form "
573		"common_*(context).\n");
574
575	fprintf(ofp, "# See the perf-trace-python Documentation for the list "
576		"of available functions.\n\n");
577
578	fprintf(ofp, "import os\n");
579	fprintf(ofp, "import sys\n\n");
580
581	fprintf(ofp, "sys.path.append(os.environ['PERF_EXEC_PATH'] + \\\n");
582	fprintf(ofp, "\t'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')\n");
583	fprintf(ofp, "\nfrom perf_trace_context import *\n");
584	fprintf(ofp, "from Core import *\n\n\n");
585
586	fprintf(ofp, "def trace_begin():\n");
587	fprintf(ofp, "\tprint \"in trace_begin\"\n\n");
588
589	fprintf(ofp, "def trace_end():\n");
590	fprintf(ofp, "\tprint \"in trace_end\"\n\n");
591
592	while ((event = trace_find_next_event(pevent, event))) {
593		fprintf(ofp, "def %s__%s(", event->system, event->name);
594		fprintf(ofp, "event_name, ");
595		fprintf(ofp, "context, ");
596		fprintf(ofp, "common_cpu,\n");
597		fprintf(ofp, "\tcommon_secs, ");
598		fprintf(ofp, "common_nsecs, ");
599		fprintf(ofp, "common_pid, ");
600		fprintf(ofp, "common_comm,\n\t");
601
602		not_first = 0;
603		count = 0;
604
605		for (f = event->format.fields; f; f = f->next) {
606			if (not_first++)
607				fprintf(ofp, ", ");
608			if (++count % 5 == 0)
609				fprintf(ofp, "\n\t");
610
611			fprintf(ofp, "%s", f->name);
612		}
613		fprintf(ofp, "):\n");
614
615		fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
616			"common_secs, common_nsecs,\n\t\t\t"
617			"common_pid, common_comm)\n\n");
618
619		fprintf(ofp, "\t\tprint \"");
620
621		not_first = 0;
622		count = 0;
623
624		for (f = event->format.fields; f; f = f->next) {
625			if (not_first++)
626				fprintf(ofp, ", ");
627			if (count && count % 3 == 0) {
628				fprintf(ofp, "\" \\\n\t\t\"");
629			}
630			count++;
631
632			fprintf(ofp, "%s=", f->name);
633			if (f->flags & FIELD_IS_STRING ||
634			    f->flags & FIELD_IS_FLAG ||
635			    f->flags & FIELD_IS_SYMBOLIC)
636				fprintf(ofp, "%%s");
637			else if (f->flags & FIELD_IS_SIGNED)
638				fprintf(ofp, "%%d");
639			else
640				fprintf(ofp, "%%u");
641		}
642
643		fprintf(ofp, "\\n\" %% \\\n\t\t(");
644
645		not_first = 0;
646		count = 0;
647
648		for (f = event->format.fields; f; f = f->next) {
649			if (not_first++)
650				fprintf(ofp, ", ");
651
652			if (++count % 5 == 0)
653				fprintf(ofp, "\n\t\t");
654
655			if (f->flags & FIELD_IS_FLAG) {
656				if ((count - 1) % 5 != 0) {
657					fprintf(ofp, "\n\t\t");
658					count = 4;
659				}
660				fprintf(ofp, "flag_str(\"");
661				fprintf(ofp, "%s__%s\", ", event->system,
662					event->name);
663				fprintf(ofp, "\"%s\", %s)", f->name,
664					f->name);
665			} else if (f->flags & FIELD_IS_SYMBOLIC) {
666				if ((count - 1) % 5 != 0) {
667					fprintf(ofp, "\n\t\t");
668					count = 4;
669				}
670				fprintf(ofp, "symbol_str(\"");
671				fprintf(ofp, "%s__%s\", ", event->system,
672					event->name);
673				fprintf(ofp, "\"%s\", %s)", f->name,
674					f->name);
675			} else
676				fprintf(ofp, "%s", f->name);
677		}
678
679		fprintf(ofp, "),\n\n");
680	}
681
682	fprintf(ofp, "def trace_unhandled(event_name, context, "
683		"event_fields_dict):\n");
684
685	fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
686		"for k,v in sorted(event_fields_dict.items())])\n\n");
687
688	fprintf(ofp, "def print_header("
689		"event_name, cpu, secs, nsecs, pid, comm):\n"
690		"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
691		"(event_name, cpu, secs, nsecs, pid, comm),\n");
692
693	fclose(ofp);
694
695	fprintf(stderr, "generated Python script: %s\n", fname);
696
697	return 0;
698}
699
700struct scripting_ops python_scripting_ops = {
701	.name = "Python",
702	.start_script = python_start_script,
703	.stop_script = python_stop_script,
704	.process_event = python_process_event,
705	.generate_script = python_generate_script,
706};
707