| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 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> | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 27 | #include <stdbool.h> | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 28 | #include <errno.h> | 
| Jiri Olsa | adf5bcf | 2014-10-26 23:44:05 +0100 | [diff] [blame] | 29 | #include <linux/bitmap.h> | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 30 |  | 
 | 31 | #include "../../perf.h" | 
| Jiri Olsa | 84f5d36 | 2014-07-14 23:46:48 +0200 | [diff] [blame] | 32 | #include "../debug.h" | 
| Arnaldo Carvalho de Melo | 8f651ea | 2014-10-09 16:12:24 -0300 | [diff] [blame] | 33 | #include "../callchain.h" | 
| Arnaldo Carvalho de Melo | fcf65bf | 2012-08-07 09:58:03 -0300 | [diff] [blame] | 34 | #include "../evsel.h" | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 35 | #include "../util.h" | 
| Arnaldo Carvalho de Melo | 743eb86 | 2011-11-28 07:56:39 -0200 | [diff] [blame] | 36 | #include "../event.h" | 
 | 37 | #include "../thread.h" | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 38 | #include "../comm.h" | 
 | 39 | #include "../machine.h" | 
 | 40 | #include "../db-export.h" | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 41 | #include "../thread-stack.h" | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 42 | #include "../trace-event.h" | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 43 | #include "../machine.h" | 
| Jiri Olsa | aef9026 | 2016-01-05 22:09:11 +0100 | [diff] [blame] | 44 | #include "thread_map.h" | 
 | 45 | #include "cpumap.h" | 
 | 46 | #include "stat.h" | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 47 |  | 
 | 48 | PyMODINIT_FUNC initperf_trace_context(void); | 
 | 49 |  | 
| Steven Rostedt (Red Hat) | 609a740 | 2015-05-13 13:44:36 -0400 | [diff] [blame] | 50 | #define TRACE_EVENT_TYPE_MAX				\ | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 51 | 	((1 << (sizeof(unsigned short) * 8)) - 1) | 
 | 52 |  | 
| Steven Rostedt (Red Hat) | 609a740 | 2015-05-13 13:44:36 -0400 | [diff] [blame] | 53 | static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 54 |  | 
 | 55 | #define MAX_FIELDS	64 | 
 | 56 | #define N_COMMON_FIELDS	7 | 
 | 57 |  | 
 | 58 | extern struct scripting_context *scripting_context; | 
 | 59 |  | 
 | 60 | static char *cur_field_name; | 
 | 61 | static int zero_flag_atom; | 
 | 62 |  | 
 | 63 | static PyObject *main_module, *main_dict; | 
 | 64 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 65 | struct tables { | 
 | 66 | 	struct db_export	dbe; | 
 | 67 | 	PyObject		*evsel_handler; | 
 | 68 | 	PyObject		*machine_handler; | 
 | 69 | 	PyObject		*thread_handler; | 
 | 70 | 	PyObject		*comm_handler; | 
 | 71 | 	PyObject		*comm_thread_handler; | 
 | 72 | 	PyObject		*dso_handler; | 
 | 73 | 	PyObject		*symbol_handler; | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 74 | 	PyObject		*branch_type_handler; | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 75 | 	PyObject		*sample_handler; | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 76 | 	PyObject		*call_path_handler; | 
 | 77 | 	PyObject		*call_return_handler; | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 78 | 	bool			db_export_mode; | 
 | 79 | }; | 
 | 80 |  | 
 | 81 | static struct tables tables_global; | 
 | 82 |  | 
| Joseph Schuchart | 05f832e | 2014-07-09 16:16:31 +0200 | [diff] [blame] | 83 | static void handler_call_die(const char *handler_name) NORETURN; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 84 | static void handler_call_die(const char *handler_name) | 
 | 85 | { | 
 | 86 | 	PyErr_Print(); | 
 | 87 | 	Py_FatalError("problem in Python trace event handler"); | 
| Joseph Schuchart | 05f832e | 2014-07-09 16:16:31 +0200 | [diff] [blame] | 88 | 	// Py_FatalError does not return | 
 | 89 | 	// but we have to make the compiler happy | 
 | 90 | 	abort(); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 91 | } | 
 | 92 |  | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 93 | /* | 
 | 94 |  * Insert val into into the dictionary and decrement the reference counter. | 
| Arnaldo Carvalho de Melo | 48000a1 | 2014-12-17 17:24:45 -0300 | [diff] [blame] | 95 |  * This is necessary for dictionaries since PyDict_SetItemString() does not | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 96 |  * steal a reference, as opposed to PyTuple_SetItem(). | 
 | 97 |  */ | 
 | 98 | static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val) | 
 | 99 | { | 
 | 100 | 	PyDict_SetItemString(dict, key, val); | 
 | 101 | 	Py_DECREF(val); | 
 | 102 | } | 
 | 103 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 104 | static PyObject *get_handler(const char *handler_name) | 
 | 105 | { | 
 | 106 | 	PyObject *handler; | 
 | 107 |  | 
 | 108 | 	handler = PyDict_GetItemString(main_dict, handler_name); | 
 | 109 | 	if (handler && !PyCallable_Check(handler)) | 
 | 110 | 		return NULL; | 
 | 111 | 	return handler; | 
 | 112 | } | 
 | 113 |  | 
 | 114 | static void call_object(PyObject *handler, PyObject *args, const char *die_msg) | 
 | 115 | { | 
 | 116 | 	PyObject *retval; | 
 | 117 |  | 
 | 118 | 	retval = PyObject_CallObject(handler, args); | 
 | 119 | 	if (retval == NULL) | 
 | 120 | 		handler_call_die(die_msg); | 
 | 121 | 	Py_DECREF(retval); | 
 | 122 | } | 
 | 123 |  | 
 | 124 | static void try_call_object(const char *handler_name, PyObject *args) | 
 | 125 | { | 
 | 126 | 	PyObject *handler; | 
 | 127 |  | 
 | 128 | 	handler = get_handler(handler_name); | 
 | 129 | 	if (handler) | 
 | 130 | 		call_object(handler, args, handler_name); | 
 | 131 | } | 
 | 132 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 133 | static void define_value(enum print_arg_type field_type, | 
 | 134 | 			 const char *ev_name, | 
 | 135 | 			 const char *field_name, | 
 | 136 | 			 const char *field_value, | 
 | 137 | 			 const char *field_str) | 
 | 138 | { | 
 | 139 | 	const char *handler_name = "define_flag_value"; | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 140 | 	PyObject *t; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 141 | 	unsigned long long value; | 
 | 142 | 	unsigned n = 0; | 
 | 143 |  | 
 | 144 | 	if (field_type == PRINT_SYMBOL) | 
 | 145 | 		handler_name = "define_symbolic_value"; | 
 | 146 |  | 
| Tom Zanussi | 44ad9cd | 2010-02-22 01:12:59 -0600 | [diff] [blame] | 147 | 	t = PyTuple_New(4); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 148 | 	if (!t) | 
 | 149 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 150 |  | 
 | 151 | 	value = eval_flag(field_value); | 
 | 152 |  | 
 | 153 | 	PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); | 
 | 154 | 	PyTuple_SetItem(t, n++, PyString_FromString(field_name)); | 
 | 155 | 	PyTuple_SetItem(t, n++, PyInt_FromLong(value)); | 
 | 156 | 	PyTuple_SetItem(t, n++, PyString_FromString(field_str)); | 
 | 157 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 158 | 	try_call_object(handler_name, t); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 159 |  | 
 | 160 | 	Py_DECREF(t); | 
 | 161 | } | 
 | 162 |  | 
 | 163 | static void define_values(enum print_arg_type field_type, | 
 | 164 | 			  struct print_flag_sym *field, | 
 | 165 | 			  const char *ev_name, | 
 | 166 | 			  const char *field_name) | 
 | 167 | { | 
 | 168 | 	define_value(field_type, ev_name, field_name, field->value, | 
 | 169 | 		     field->str); | 
 | 170 |  | 
 | 171 | 	if (field->next) | 
 | 172 | 		define_values(field_type, field->next, ev_name, field_name); | 
 | 173 | } | 
 | 174 |  | 
 | 175 | static void define_field(enum print_arg_type field_type, | 
 | 176 | 			 const char *ev_name, | 
 | 177 | 			 const char *field_name, | 
 | 178 | 			 const char *delim) | 
 | 179 | { | 
 | 180 | 	const char *handler_name = "define_flag_field"; | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 181 | 	PyObject *t; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 182 | 	unsigned n = 0; | 
 | 183 |  | 
 | 184 | 	if (field_type == PRINT_SYMBOL) | 
 | 185 | 		handler_name = "define_symbolic_field"; | 
 | 186 |  | 
| Tom Zanussi | 44ad9cd | 2010-02-22 01:12:59 -0600 | [diff] [blame] | 187 | 	if (field_type == PRINT_FLAGS) | 
 | 188 | 		t = PyTuple_New(3); | 
 | 189 | 	else | 
 | 190 | 		t = PyTuple_New(2); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 191 | 	if (!t) | 
 | 192 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 193 |  | 
 | 194 | 	PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); | 
 | 195 | 	PyTuple_SetItem(t, n++, PyString_FromString(field_name)); | 
 | 196 | 	if (field_type == PRINT_FLAGS) | 
 | 197 | 		PyTuple_SetItem(t, n++, PyString_FromString(delim)); | 
 | 198 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 199 | 	try_call_object(handler_name, t); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 200 |  | 
 | 201 | 	Py_DECREF(t); | 
 | 202 | } | 
 | 203 |  | 
| Steven Rostedt | aaf045f | 2012-04-06 00:47:56 +0200 | [diff] [blame] | 204 | static void define_event_symbols(struct event_format *event, | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 205 | 				 const char *ev_name, | 
 | 206 | 				 struct print_arg *args) | 
 | 207 | { | 
 | 208 | 	switch (args->type) { | 
 | 209 | 	case PRINT_NULL: | 
 | 210 | 		break; | 
 | 211 | 	case PRINT_ATOM: | 
 | 212 | 		define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", | 
 | 213 | 			     args->atom.atom); | 
 | 214 | 		zero_flag_atom = 0; | 
 | 215 | 		break; | 
 | 216 | 	case PRINT_FIELD: | 
| Arnaldo Carvalho de Melo | f538565 | 2013-12-26 15:54:57 -0300 | [diff] [blame] | 217 | 		free(cur_field_name); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 218 | 		cur_field_name = strdup(args->field.name); | 
 | 219 | 		break; | 
 | 220 | 	case PRINT_FLAGS: | 
 | 221 | 		define_event_symbols(event, ev_name, args->flags.field); | 
 | 222 | 		define_field(PRINT_FLAGS, ev_name, cur_field_name, | 
 | 223 | 			     args->flags.delim); | 
 | 224 | 		define_values(PRINT_FLAGS, args->flags.flags, ev_name, | 
 | 225 | 			      cur_field_name); | 
 | 226 | 		break; | 
 | 227 | 	case PRINT_SYMBOL: | 
 | 228 | 		define_event_symbols(event, ev_name, args->symbol.field); | 
 | 229 | 		define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); | 
 | 230 | 		define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, | 
 | 231 | 			      cur_field_name); | 
 | 232 | 		break; | 
| Namhyung Kim | e080e6f | 2012-06-27 09:41:41 +0900 | [diff] [blame] | 233 | 	case PRINT_HEX: | 
 | 234 | 		define_event_symbols(event, ev_name, args->hex.field); | 
 | 235 | 		define_event_symbols(event, ev_name, args->hex.size); | 
 | 236 | 		break; | 
| Javi Merino | b839e1e8 | 2015-03-24 11:07:19 +0000 | [diff] [blame] | 237 | 	case PRINT_INT_ARRAY: | 
 | 238 | 		define_event_symbols(event, ev_name, args->int_array.field); | 
 | 239 | 		define_event_symbols(event, ev_name, args->int_array.count); | 
 | 240 | 		define_event_symbols(event, ev_name, args->int_array.el_size); | 
 | 241 | 		break; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 242 | 	case PRINT_STRING: | 
 | 243 | 		break; | 
 | 244 | 	case PRINT_TYPE: | 
 | 245 | 		define_event_symbols(event, ev_name, args->typecast.item); | 
 | 246 | 		break; | 
 | 247 | 	case PRINT_OP: | 
 | 248 | 		if (strcmp(args->op.op, ":") == 0) | 
 | 249 | 			zero_flag_atom = 1; | 
 | 250 | 		define_event_symbols(event, ev_name, args->op.left); | 
 | 251 | 		define_event_symbols(event, ev_name, args->op.right); | 
 | 252 | 		break; | 
 | 253 | 	default: | 
| Steven Rostedt | aaf045f | 2012-04-06 00:47:56 +0200 | [diff] [blame] | 254 | 		/* gcc warns for these? */ | 
 | 255 | 	case PRINT_BSTRING: | 
 | 256 | 	case PRINT_DYNAMIC_ARRAY: | 
| He Kuang | 7605594 | 2015-08-29 04:22:05 +0000 | [diff] [blame] | 257 | 	case PRINT_DYNAMIC_ARRAY_LEN: | 
| Steven Rostedt | aaf045f | 2012-04-06 00:47:56 +0200 | [diff] [blame] | 258 | 	case PRINT_FUNC: | 
| Steven Rostedt (Red Hat) | 473a778 | 2014-06-02 23:20:16 -0400 | [diff] [blame] | 259 | 	case PRINT_BITMASK: | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 260 | 		/* we should warn... */ | 
 | 261 | 		return; | 
 | 262 | 	} | 
 | 263 |  | 
 | 264 | 	if (args->next) | 
 | 265 | 		define_event_symbols(event, ev_name, args->next); | 
 | 266 | } | 
 | 267 |  | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 268 | static PyObject *get_field_numeric_entry(struct event_format *event, | 
 | 269 | 		struct format_field *field, void *data) | 
 | 270 | { | 
| Sebastian Andrzej Siewior | 8ac631c | 2014-05-27 18:14:34 +0200 | [diff] [blame] | 271 | 	bool is_array = field->flags & FIELD_IS_ARRAY; | 
 | 272 | 	PyObject *obj, *list = NULL; | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 273 | 	unsigned long long val; | 
| Sebastian Andrzej Siewior | 8ac631c | 2014-05-27 18:14:34 +0200 | [diff] [blame] | 274 | 	unsigned int item_size, n_items, i; | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 275 |  | 
| Sebastian Andrzej Siewior | 8ac631c | 2014-05-27 18:14:34 +0200 | [diff] [blame] | 276 | 	if (is_array) { | 
 | 277 | 		list = PyList_New(field->arraylen); | 
 | 278 | 		item_size = field->size / field->arraylen; | 
 | 279 | 		n_items = field->arraylen; | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 280 | 	} else { | 
| Sebastian Andrzej Siewior | 8ac631c | 2014-05-27 18:14:34 +0200 | [diff] [blame] | 281 | 		item_size = field->size; | 
 | 282 | 		n_items = 1; | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 283 | 	} | 
| Sebastian Andrzej Siewior | 8ac631c | 2014-05-27 18:14:34 +0200 | [diff] [blame] | 284 |  | 
 | 285 | 	for (i = 0; i < n_items; i++) { | 
 | 286 |  | 
 | 287 | 		val = read_size(event, data + field->offset + i * item_size, | 
 | 288 | 				item_size); | 
 | 289 | 		if (field->flags & FIELD_IS_SIGNED) { | 
 | 290 | 			if ((long long)val >= LONG_MIN && | 
 | 291 | 					(long long)val <= LONG_MAX) | 
 | 292 | 				obj = PyInt_FromLong(val); | 
 | 293 | 			else | 
 | 294 | 				obj = PyLong_FromLongLong(val); | 
 | 295 | 		} else { | 
 | 296 | 			if (val <= LONG_MAX) | 
 | 297 | 				obj = PyInt_FromLong(val); | 
 | 298 | 			else | 
 | 299 | 				obj = PyLong_FromUnsignedLongLong(val); | 
 | 300 | 		} | 
 | 301 | 		if (is_array) | 
 | 302 | 			PyList_SET_ITEM(list, i, obj); | 
 | 303 | 	} | 
 | 304 | 	if (is_array) | 
 | 305 | 		obj = list; | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 306 | 	return obj; | 
 | 307 | } | 
 | 308 |  | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 309 |  | 
 | 310 | static PyObject *python_process_callchain(struct perf_sample *sample, | 
 | 311 | 					 struct perf_evsel *evsel, | 
 | 312 | 					 struct addr_location *al) | 
 | 313 | { | 
 | 314 | 	PyObject *pylist; | 
 | 315 |  | 
 | 316 | 	pylist = PyList_New(0); | 
 | 317 | 	if (!pylist) | 
 | 318 | 		Py_FatalError("couldn't create Python list"); | 
 | 319 |  | 
 | 320 | 	if (!symbol_conf.use_callchain || !sample->callchain) | 
 | 321 | 		goto exit; | 
 | 322 |  | 
| Arnaldo Carvalho de Melo | cc8b7c2 | 2014-10-23 15:26:17 -0300 | [diff] [blame] | 323 | 	if (thread__resolve_callchain(al->thread, evsel, | 
 | 324 | 				      sample, NULL, NULL, | 
| Adrian Hunter | 44cbe72 | 2015-09-25 16:15:50 +0300 | [diff] [blame] | 325 | 				      scripting_max_stack) != 0) { | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 326 | 		pr_err("Failed to resolve callchain. Skipping\n"); | 
 | 327 | 		goto exit; | 
 | 328 | 	} | 
 | 329 | 	callchain_cursor_commit(&callchain_cursor); | 
 | 330 |  | 
 | 331 |  | 
 | 332 | 	while (1) { | 
 | 333 | 		PyObject *pyelem; | 
 | 334 | 		struct callchain_cursor_node *node; | 
 | 335 | 		node = callchain_cursor_current(&callchain_cursor); | 
 | 336 | 		if (!node) | 
 | 337 | 			break; | 
 | 338 |  | 
 | 339 | 		pyelem = PyDict_New(); | 
 | 340 | 		if (!pyelem) | 
 | 341 | 			Py_FatalError("couldn't create Python dictionary"); | 
 | 342 |  | 
 | 343 |  | 
 | 344 | 		pydict_set_item_string_decref(pyelem, "ip", | 
 | 345 | 				PyLong_FromUnsignedLongLong(node->ip)); | 
 | 346 |  | 
 | 347 | 		if (node->sym) { | 
 | 348 | 			PyObject *pysym  = PyDict_New(); | 
 | 349 | 			if (!pysym) | 
 | 350 | 				Py_FatalError("couldn't create Python dictionary"); | 
 | 351 | 			pydict_set_item_string_decref(pysym, "start", | 
 | 352 | 					PyLong_FromUnsignedLongLong(node->sym->start)); | 
 | 353 | 			pydict_set_item_string_decref(pysym, "end", | 
 | 354 | 					PyLong_FromUnsignedLongLong(node->sym->end)); | 
 | 355 | 			pydict_set_item_string_decref(pysym, "binding", | 
 | 356 | 					PyInt_FromLong(node->sym->binding)); | 
 | 357 | 			pydict_set_item_string_decref(pysym, "name", | 
 | 358 | 					PyString_FromStringAndSize(node->sym->name, | 
 | 359 | 							node->sym->namelen)); | 
 | 360 | 			pydict_set_item_string_decref(pyelem, "sym", pysym); | 
 | 361 | 		} | 
 | 362 |  | 
 | 363 | 		if (node->map) { | 
 | 364 | 			struct map *map = node->map; | 
 | 365 | 			const char *dsoname = "[unknown]"; | 
 | 366 | 			if (map && map->dso && (map->dso->name || map->dso->long_name)) { | 
 | 367 | 				if (symbol_conf.show_kernel_path && map->dso->long_name) | 
 | 368 | 					dsoname = map->dso->long_name; | 
 | 369 | 				else if (map->dso->name) | 
 | 370 | 					dsoname = map->dso->name; | 
 | 371 | 			} | 
 | 372 | 			pydict_set_item_string_decref(pyelem, "dso", | 
 | 373 | 					PyString_FromString(dsoname)); | 
 | 374 | 		} | 
 | 375 |  | 
 | 376 | 		callchain_cursor_advance(&callchain_cursor); | 
 | 377 | 		PyList_Append(pylist, pyelem); | 
 | 378 | 		Py_DECREF(pyelem); | 
 | 379 | 	} | 
 | 380 |  | 
 | 381 | exit: | 
 | 382 | 	return pylist; | 
 | 383 | } | 
 | 384 |  | 
 | 385 |  | 
| Arnaldo Carvalho de Melo | b7fff6b5 | 2013-12-19 16:34:52 -0300 | [diff] [blame] | 386 | static void python_process_tracepoint(struct perf_sample *sample, | 
 | 387 | 				      struct perf_evsel *evsel, | 
| Arnaldo Carvalho de Melo | b7fff6b5 | 2013-12-19 16:34:52 -0300 | [diff] [blame] | 388 | 				      struct addr_location *al) | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 389 | { | 
| Jiri Olsa | adf5bcf | 2014-10-26 23:44:05 +0100 | [diff] [blame] | 390 | 	struct event_format *event = evsel->tp_format; | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 391 | 	PyObject *handler, *context, *t, *obj, *callchain; | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 392 | 	PyObject *dict = NULL; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 393 | 	static char handler_name[256]; | 
 | 394 | 	struct format_field *field; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 395 | 	unsigned long s, ns; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 396 | 	unsigned n = 0; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 397 | 	int pid; | 
| David Ahern | be6d842 | 2011-03-09 22:23:23 -0700 | [diff] [blame] | 398 | 	int cpu = sample->cpu; | 
 | 399 | 	void *data = sample->raw_data; | 
 | 400 | 	unsigned long long nsecs = sample->time; | 
| Arnaldo Carvalho de Melo | f9d5d54 | 2015-04-01 13:29:25 -0300 | [diff] [blame] | 401 | 	const char *comm = thread__comm_str(al->thread); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 402 |  | 
 | 403 | 	t = PyTuple_New(MAX_FIELDS); | 
 | 404 | 	if (!t) | 
 | 405 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 406 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 407 | 	if (!event) | 
| Arnaldo Carvalho de Melo | fcf65bf | 2012-08-07 09:58:03 -0300 | [diff] [blame] | 408 | 		die("ug! no event found for type %d", (int)evsel->attr.config); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 409 |  | 
| Arnaldo Carvalho de Melo | 9782243 | 2012-08-07 23:50:21 -0300 | [diff] [blame] | 410 | 	pid = raw_field_value(event, "common_pid", data); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 411 |  | 
 | 412 | 	sprintf(handler_name, "%s__%s", event->system, event->name); | 
 | 413 |  | 
| Jiri Olsa | adf5bcf | 2014-10-26 23:44:05 +0100 | [diff] [blame] | 414 | 	if (!test_and_set_bit(event->id, events_defined)) | 
 | 415 | 		define_event_symbols(event, handler_name, event->print_fmt.args); | 
 | 416 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 417 | 	handler = get_handler(handler_name); | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 418 | 	if (!handler) { | 
 | 419 | 		dict = PyDict_New(); | 
 | 420 | 		if (!dict) | 
 | 421 | 			Py_FatalError("couldn't create Python dict"); | 
 | 422 | 	} | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 423 | 	s = nsecs / NSECS_PER_SEC; | 
 | 424 | 	ns = nsecs - s * NSECS_PER_SEC; | 
 | 425 |  | 
 | 426 | 	scripting_context->event_data = data; | 
| Tom Zanussi | 2de9533 | 2013-01-18 13:51:27 -0600 | [diff] [blame] | 427 | 	scripting_context->pevent = evsel->tp_format->pevent; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 428 |  | 
 | 429 | 	context = PyCObject_FromVoidPtr(scripting_context, NULL); | 
 | 430 |  | 
 | 431 | 	PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); | 
| Kyle McMartin | fb7d0b3 | 2011-01-24 11:13:04 -0500 | [diff] [blame] | 432 | 	PyTuple_SetItem(t, n++, context); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 433 |  | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 434 | 	/* ip unwinding */ | 
 | 435 | 	callchain = python_process_callchain(sample, evsel, al); | 
 | 436 |  | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 437 | 	if (handler) { | 
 | 438 | 		PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 
 | 439 | 		PyTuple_SetItem(t, n++, PyInt_FromLong(s)); | 
 | 440 | 		PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); | 
 | 441 | 		PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); | 
 | 442 | 		PyTuple_SetItem(t, n++, PyString_FromString(comm)); | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 443 | 		PyTuple_SetItem(t, n++, callchain); | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 444 | 	} else { | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 445 | 		pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); | 
 | 446 | 		pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); | 
 | 447 | 		pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); | 
 | 448 | 		pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); | 
 | 449 | 		pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 450 | 		pydict_set_item_string_decref(dict, "common_callchain", callchain); | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 451 | 	} | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 452 | 	for (field = event->format.fields; field; field = field->next) { | 
 | 453 | 		if (field->flags & FIELD_IS_STRING) { | 
 | 454 | 			int offset; | 
 | 455 | 			if (field->flags & FIELD_IS_DYNAMIC) { | 
 | 456 | 				offset = *(int *)(data + field->offset); | 
 | 457 | 				offset &= 0xffff; | 
 | 458 | 			} else | 
 | 459 | 				offset = field->offset; | 
| Tom Zanussi | b1dcc03 | 2010-04-01 23:58:25 -0500 | [diff] [blame] | 460 | 			obj = PyString_FromString((char *)data + offset); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 461 | 		} else { /* FIELD_IS_NUMERIC */ | 
| Sebastian Andrzej Siewior | 33058b9 | 2014-05-27 18:14:33 +0200 | [diff] [blame] | 462 | 			obj = get_field_numeric_entry(event, field, data); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 463 | 		} | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 464 | 		if (handler) | 
 | 465 | 			PyTuple_SetItem(t, n++, obj); | 
 | 466 | 		else | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 467 | 			pydict_set_item_string_decref(dict, field->name, obj); | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 468 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 469 | 	} | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 470 |  | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 471 | 	if (!handler) | 
 | 472 | 		PyTuple_SetItem(t, n++, dict); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 473 |  | 
 | 474 | 	if (_PyTuple_Resize(&t, n) == -1) | 
 | 475 | 		Py_FatalError("error resizing Python tuple"); | 
 | 476 |  | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 477 | 	if (handler) { | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 478 | 		call_object(handler, t, handler_name); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 479 | 	} else { | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 480 | 		try_call_object("trace_unhandled", t); | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 481 | 		Py_DECREF(dict); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 482 | 	} | 
 | 483 |  | 
 | 484 | 	Py_DECREF(t); | 
 | 485 | } | 
 | 486 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 487 | static PyObject *tuple_new(unsigned int sz) | 
 | 488 | { | 
 | 489 | 	PyObject *t; | 
 | 490 |  | 
 | 491 | 	t = PyTuple_New(sz); | 
 | 492 | 	if (!t) | 
 | 493 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 494 | 	return t; | 
 | 495 | } | 
 | 496 |  | 
 | 497 | static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) | 
 | 498 | { | 
 | 499 | #if BITS_PER_LONG == 64 | 
 | 500 | 	return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | 
 | 501 | #endif | 
 | 502 | #if BITS_PER_LONG == 32 | 
 | 503 | 	return PyTuple_SetItem(t, pos, PyLong_FromLongLong(val)); | 
 | 504 | #endif | 
 | 505 | } | 
 | 506 |  | 
 | 507 | static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) | 
 | 508 | { | 
 | 509 | 	return PyTuple_SetItem(t, pos, PyInt_FromLong(val)); | 
 | 510 | } | 
 | 511 |  | 
 | 512 | static int tuple_set_string(PyObject *t, unsigned int pos, const char *s) | 
 | 513 | { | 
 | 514 | 	return PyTuple_SetItem(t, pos, PyString_FromString(s)); | 
 | 515 | } | 
 | 516 |  | 
 | 517 | static int python_export_evsel(struct db_export *dbe, struct perf_evsel *evsel) | 
 | 518 | { | 
 | 519 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 520 | 	PyObject *t; | 
 | 521 |  | 
 | 522 | 	t = tuple_new(2); | 
 | 523 |  | 
 | 524 | 	tuple_set_u64(t, 0, evsel->db_id); | 
 | 525 | 	tuple_set_string(t, 1, perf_evsel__name(evsel)); | 
 | 526 |  | 
 | 527 | 	call_object(tables->evsel_handler, t, "evsel_table"); | 
 | 528 |  | 
 | 529 | 	Py_DECREF(t); | 
 | 530 |  | 
 | 531 | 	return 0; | 
 | 532 | } | 
 | 533 |  | 
 | 534 | static int python_export_machine(struct db_export *dbe, | 
 | 535 | 				 struct machine *machine) | 
 | 536 | { | 
 | 537 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 538 | 	PyObject *t; | 
 | 539 |  | 
 | 540 | 	t = tuple_new(3); | 
 | 541 |  | 
 | 542 | 	tuple_set_u64(t, 0, machine->db_id); | 
 | 543 | 	tuple_set_s32(t, 1, machine->pid); | 
 | 544 | 	tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); | 
 | 545 |  | 
 | 546 | 	call_object(tables->machine_handler, t, "machine_table"); | 
 | 547 |  | 
 | 548 | 	Py_DECREF(t); | 
 | 549 |  | 
 | 550 | 	return 0; | 
 | 551 | } | 
 | 552 |  | 
 | 553 | static int python_export_thread(struct db_export *dbe, struct thread *thread, | 
 | 554 | 				u64 main_thread_db_id, struct machine *machine) | 
 | 555 | { | 
 | 556 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 557 | 	PyObject *t; | 
 | 558 |  | 
 | 559 | 	t = tuple_new(5); | 
 | 560 |  | 
 | 561 | 	tuple_set_u64(t, 0, thread->db_id); | 
 | 562 | 	tuple_set_u64(t, 1, machine->db_id); | 
 | 563 | 	tuple_set_u64(t, 2, main_thread_db_id); | 
 | 564 | 	tuple_set_s32(t, 3, thread->pid_); | 
 | 565 | 	tuple_set_s32(t, 4, thread->tid); | 
 | 566 |  | 
 | 567 | 	call_object(tables->thread_handler, t, "thread_table"); | 
 | 568 |  | 
 | 569 | 	Py_DECREF(t); | 
 | 570 |  | 
 | 571 | 	return 0; | 
 | 572 | } | 
 | 573 |  | 
 | 574 | static int python_export_comm(struct db_export *dbe, struct comm *comm) | 
 | 575 | { | 
 | 576 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 577 | 	PyObject *t; | 
 | 578 |  | 
 | 579 | 	t = tuple_new(2); | 
 | 580 |  | 
 | 581 | 	tuple_set_u64(t, 0, comm->db_id); | 
 | 582 | 	tuple_set_string(t, 1, comm__str(comm)); | 
 | 583 |  | 
 | 584 | 	call_object(tables->comm_handler, t, "comm_table"); | 
 | 585 |  | 
 | 586 | 	Py_DECREF(t); | 
 | 587 |  | 
 | 588 | 	return 0; | 
 | 589 | } | 
 | 590 |  | 
 | 591 | static int python_export_comm_thread(struct db_export *dbe, u64 db_id, | 
 | 592 | 				     struct comm *comm, struct thread *thread) | 
 | 593 | { | 
 | 594 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 595 | 	PyObject *t; | 
 | 596 |  | 
 | 597 | 	t = tuple_new(3); | 
 | 598 |  | 
 | 599 | 	tuple_set_u64(t, 0, db_id); | 
 | 600 | 	tuple_set_u64(t, 1, comm->db_id); | 
 | 601 | 	tuple_set_u64(t, 2, thread->db_id); | 
 | 602 |  | 
 | 603 | 	call_object(tables->comm_thread_handler, t, "comm_thread_table"); | 
 | 604 |  | 
 | 605 | 	Py_DECREF(t); | 
 | 606 |  | 
 | 607 | 	return 0; | 
 | 608 | } | 
 | 609 |  | 
 | 610 | static int python_export_dso(struct db_export *dbe, struct dso *dso, | 
 | 611 | 			     struct machine *machine) | 
 | 612 | { | 
 | 613 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 614 | 	char sbuild_id[BUILD_ID_SIZE * 2 + 1]; | 
 | 615 | 	PyObject *t; | 
 | 616 |  | 
 | 617 | 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); | 
 | 618 |  | 
 | 619 | 	t = tuple_new(5); | 
 | 620 |  | 
 | 621 | 	tuple_set_u64(t, 0, dso->db_id); | 
 | 622 | 	tuple_set_u64(t, 1, machine->db_id); | 
 | 623 | 	tuple_set_string(t, 2, dso->short_name); | 
 | 624 | 	tuple_set_string(t, 3, dso->long_name); | 
 | 625 | 	tuple_set_string(t, 4, sbuild_id); | 
 | 626 |  | 
 | 627 | 	call_object(tables->dso_handler, t, "dso_table"); | 
 | 628 |  | 
 | 629 | 	Py_DECREF(t); | 
 | 630 |  | 
 | 631 | 	return 0; | 
 | 632 | } | 
 | 633 |  | 
 | 634 | static int python_export_symbol(struct db_export *dbe, struct symbol *sym, | 
 | 635 | 				struct dso *dso) | 
 | 636 | { | 
 | 637 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 638 | 	u64 *sym_db_id = symbol__priv(sym); | 
 | 639 | 	PyObject *t; | 
 | 640 |  | 
 | 641 | 	t = tuple_new(6); | 
 | 642 |  | 
 | 643 | 	tuple_set_u64(t, 0, *sym_db_id); | 
 | 644 | 	tuple_set_u64(t, 1, dso->db_id); | 
 | 645 | 	tuple_set_u64(t, 2, sym->start); | 
 | 646 | 	tuple_set_u64(t, 3, sym->end); | 
 | 647 | 	tuple_set_s32(t, 4, sym->binding); | 
 | 648 | 	tuple_set_string(t, 5, sym->name); | 
 | 649 |  | 
 | 650 | 	call_object(tables->symbol_handler, t, "symbol_table"); | 
 | 651 |  | 
 | 652 | 	Py_DECREF(t); | 
 | 653 |  | 
 | 654 | 	return 0; | 
 | 655 | } | 
 | 656 |  | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 657 | static int python_export_branch_type(struct db_export *dbe, u32 branch_type, | 
 | 658 | 				     const char *name) | 
 | 659 | { | 
 | 660 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 661 | 	PyObject *t; | 
 | 662 |  | 
 | 663 | 	t = tuple_new(2); | 
 | 664 |  | 
 | 665 | 	tuple_set_s32(t, 0, branch_type); | 
 | 666 | 	tuple_set_string(t, 1, name); | 
 | 667 |  | 
 | 668 | 	call_object(tables->branch_type_handler, t, "branch_type_table"); | 
 | 669 |  | 
 | 670 | 	Py_DECREF(t); | 
 | 671 |  | 
 | 672 | 	return 0; | 
 | 673 | } | 
 | 674 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 675 | static int python_export_sample(struct db_export *dbe, | 
 | 676 | 				struct export_sample *es) | 
 | 677 | { | 
 | 678 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 679 | 	PyObject *t; | 
 | 680 |  | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 681 | 	t = tuple_new(21); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 682 |  | 
 | 683 | 	tuple_set_u64(t, 0, es->db_id); | 
 | 684 | 	tuple_set_u64(t, 1, es->evsel->db_id); | 
 | 685 | 	tuple_set_u64(t, 2, es->al->machine->db_id); | 
| Arnaldo Carvalho de Melo | b83e868 | 2015-04-02 11:16:05 -0300 | [diff] [blame] | 686 | 	tuple_set_u64(t, 3, es->al->thread->db_id); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 687 | 	tuple_set_u64(t, 4, es->comm_db_id); | 
 | 688 | 	tuple_set_u64(t, 5, es->dso_db_id); | 
 | 689 | 	tuple_set_u64(t, 6, es->sym_db_id); | 
 | 690 | 	tuple_set_u64(t, 7, es->offset); | 
 | 691 | 	tuple_set_u64(t, 8, es->sample->ip); | 
 | 692 | 	tuple_set_u64(t, 9, es->sample->time); | 
 | 693 | 	tuple_set_s32(t, 10, es->sample->cpu); | 
 | 694 | 	tuple_set_u64(t, 11, es->addr_dso_db_id); | 
 | 695 | 	tuple_set_u64(t, 12, es->addr_sym_db_id); | 
 | 696 | 	tuple_set_u64(t, 13, es->addr_offset); | 
 | 697 | 	tuple_set_u64(t, 14, es->sample->addr); | 
 | 698 | 	tuple_set_u64(t, 15, es->sample->period); | 
 | 699 | 	tuple_set_u64(t, 16, es->sample->weight); | 
 | 700 | 	tuple_set_u64(t, 17, es->sample->transaction); | 
 | 701 | 	tuple_set_u64(t, 18, es->sample->data_src); | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 702 | 	tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); | 
 | 703 | 	tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 704 |  | 
 | 705 | 	call_object(tables->sample_handler, t, "sample_table"); | 
 | 706 |  | 
 | 707 | 	Py_DECREF(t); | 
 | 708 |  | 
 | 709 | 	return 0; | 
 | 710 | } | 
 | 711 |  | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 712 | static int python_export_call_path(struct db_export *dbe, struct call_path *cp) | 
 | 713 | { | 
 | 714 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 715 | 	PyObject *t; | 
 | 716 | 	u64 parent_db_id, sym_db_id; | 
 | 717 |  | 
 | 718 | 	parent_db_id = cp->parent ? cp->parent->db_id : 0; | 
 | 719 | 	sym_db_id = cp->sym ? *(u64 *)symbol__priv(cp->sym) : 0; | 
 | 720 |  | 
 | 721 | 	t = tuple_new(4); | 
 | 722 |  | 
 | 723 | 	tuple_set_u64(t, 0, cp->db_id); | 
 | 724 | 	tuple_set_u64(t, 1, parent_db_id); | 
 | 725 | 	tuple_set_u64(t, 2, sym_db_id); | 
 | 726 | 	tuple_set_u64(t, 3, cp->ip); | 
 | 727 |  | 
 | 728 | 	call_object(tables->call_path_handler, t, "call_path_table"); | 
 | 729 |  | 
 | 730 | 	Py_DECREF(t); | 
 | 731 |  | 
 | 732 | 	return 0; | 
 | 733 | } | 
 | 734 |  | 
 | 735 | static int python_export_call_return(struct db_export *dbe, | 
 | 736 | 				     struct call_return *cr) | 
 | 737 | { | 
 | 738 | 	struct tables *tables = container_of(dbe, struct tables, dbe); | 
 | 739 | 	u64 comm_db_id = cr->comm ? cr->comm->db_id : 0; | 
 | 740 | 	PyObject *t; | 
 | 741 |  | 
 | 742 | 	t = tuple_new(11); | 
 | 743 |  | 
 | 744 | 	tuple_set_u64(t, 0, cr->db_id); | 
 | 745 | 	tuple_set_u64(t, 1, cr->thread->db_id); | 
 | 746 | 	tuple_set_u64(t, 2, comm_db_id); | 
 | 747 | 	tuple_set_u64(t, 3, cr->cp->db_id); | 
 | 748 | 	tuple_set_u64(t, 4, cr->call_time); | 
 | 749 | 	tuple_set_u64(t, 5, cr->return_time); | 
 | 750 | 	tuple_set_u64(t, 6, cr->branch_count); | 
 | 751 | 	tuple_set_u64(t, 7, cr->call_ref); | 
 | 752 | 	tuple_set_u64(t, 8, cr->return_ref); | 
 | 753 | 	tuple_set_u64(t, 9, cr->cp->parent->db_id); | 
 | 754 | 	tuple_set_s32(t, 10, cr->flags); | 
 | 755 |  | 
 | 756 | 	call_object(tables->call_return_handler, t, "call_return_table"); | 
 | 757 |  | 
 | 758 | 	Py_DECREF(t); | 
 | 759 |  | 
 | 760 | 	return 0; | 
 | 761 | } | 
 | 762 |  | 
 | 763 | static int python_process_call_return(struct call_return *cr, void *data) | 
 | 764 | { | 
 | 765 | 	struct db_export *dbe = data; | 
 | 766 |  | 
 | 767 | 	return db_export__call_return(dbe, cr); | 
 | 768 | } | 
 | 769 |  | 
| Arnaldo Carvalho de Melo | b7fff6b5 | 2013-12-19 16:34:52 -0300 | [diff] [blame] | 770 | static void python_process_general_event(struct perf_sample *sample, | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 771 | 					 struct perf_evsel *evsel, | 
| Feng Tang | 87b6a3a | 2012-08-09 13:46:13 +0800 | [diff] [blame] | 772 | 					 struct addr_location *al) | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 773 | { | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 774 | 	PyObject *handler, *t, *dict, *callchain, *dict_sample; | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 775 | 	static char handler_name[64]; | 
 | 776 | 	unsigned n = 0; | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 777 |  | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 778 | 	/* | 
 | 779 | 	 * Use the MAX_FIELDS to make the function expandable, though | 
| Feng Tang | 87b6a3a | 2012-08-09 13:46:13 +0800 | [diff] [blame] | 780 | 	 * currently there is only one item for the tuple. | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 781 | 	 */ | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 782 | 	t = PyTuple_New(MAX_FIELDS); | 
 | 783 | 	if (!t) | 
 | 784 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 785 |  | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 786 | 	dict = PyDict_New(); | 
 | 787 | 	if (!dict) | 
 | 788 | 		Py_FatalError("couldn't create Python dictionary"); | 
 | 789 |  | 
| Joseph Schuchart | 57608cf | 2014-07-10 13:50:56 +0200 | [diff] [blame] | 790 | 	dict_sample = PyDict_New(); | 
 | 791 | 	if (!dict_sample) | 
 | 792 | 		Py_FatalError("couldn't create Python dictionary"); | 
 | 793 |  | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 794 | 	snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | 
 | 795 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 796 | 	handler = get_handler(handler_name); | 
 | 797 | 	if (!handler) | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 798 | 		goto exit; | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 799 |  | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 800 | 	pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | 
 | 801 | 	pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 802 | 			(const char *)&evsel->attr, sizeof(evsel->attr))); | 
| Joseph Schuchart | 57608cf | 2014-07-10 13:50:56 +0200 | [diff] [blame] | 803 |  | 
 | 804 | 	pydict_set_item_string_decref(dict_sample, "pid", | 
 | 805 | 			PyInt_FromLong(sample->pid)); | 
 | 806 | 	pydict_set_item_string_decref(dict_sample, "tid", | 
 | 807 | 			PyInt_FromLong(sample->tid)); | 
 | 808 | 	pydict_set_item_string_decref(dict_sample, "cpu", | 
 | 809 | 			PyInt_FromLong(sample->cpu)); | 
 | 810 | 	pydict_set_item_string_decref(dict_sample, "ip", | 
 | 811 | 			PyLong_FromUnsignedLongLong(sample->ip)); | 
 | 812 | 	pydict_set_item_string_decref(dict_sample, "time", | 
 | 813 | 			PyLong_FromUnsignedLongLong(sample->time)); | 
 | 814 | 	pydict_set_item_string_decref(dict_sample, "period", | 
 | 815 | 			PyLong_FromUnsignedLongLong(sample->period)); | 
 | 816 | 	pydict_set_item_string_decref(dict, "sample", dict_sample); | 
 | 817 |  | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 818 | 	pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 819 | 			(const char *)sample->raw_data, sample->raw_size)); | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 820 | 	pydict_set_item_string_decref(dict, "comm", | 
| Arnaldo Carvalho de Melo | f9d5d54 | 2015-04-01 13:29:25 -0300 | [diff] [blame] | 821 | 			PyString_FromString(thread__comm_str(al->thread))); | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 822 | 	if (al->map) { | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 823 | 		pydict_set_item_string_decref(dict, "dso", | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 824 | 			PyString_FromString(al->map->dso->name)); | 
 | 825 | 	} | 
 | 826 | 	if (al->sym) { | 
| Joseph Schuchart | c0268e8 | 2013-10-24 10:10:51 -0300 | [diff] [blame] | 827 | 		pydict_set_item_string_decref(dict, "symbol", | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 828 | 			PyString_FromString(al->sym->name)); | 
 | 829 | 	} | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 830 |  | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 831 | 	/* ip unwinding */ | 
 | 832 | 	callchain = python_process_callchain(sample, evsel, al); | 
 | 833 | 	pydict_set_item_string_decref(dict, "callchain", callchain); | 
 | 834 |  | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 835 | 	PyTuple_SetItem(t, n++, dict); | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 836 | 	if (_PyTuple_Resize(&t, n) == -1) | 
 | 837 | 		Py_FatalError("error resizing Python tuple"); | 
 | 838 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 839 | 	call_object(handler, t, handler_name); | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 840 | exit: | 
| Feng Tang | fd6b858 | 2012-08-08 17:57:53 +0800 | [diff] [blame] | 841 | 	Py_DECREF(dict); | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 842 | 	Py_DECREF(t); | 
 | 843 | } | 
 | 844 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 845 | static void python_process_event(union perf_event *event, | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 846 | 				 struct perf_sample *sample, | 
 | 847 | 				 struct perf_evsel *evsel, | 
| Feng Tang | 73994dc | 2012-08-08 17:57:52 +0800 | [diff] [blame] | 848 | 				 struct addr_location *al) | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 849 | { | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 850 | 	struct tables *tables = &tables_global; | 
 | 851 |  | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 852 | 	switch (evsel->attr.type) { | 
 | 853 | 	case PERF_TYPE_TRACEPOINT: | 
| Arnaldo Carvalho de Melo | f9d5d54 | 2015-04-01 13:29:25 -0300 | [diff] [blame] | 854 | 		python_process_tracepoint(sample, evsel, al); | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 855 | 		break; | 
 | 856 | 	/* Reserve for future process_hw/sw/raw APIs */ | 
 | 857 | 	default: | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 858 | 		if (tables->db_export_mode) | 
| Arnaldo Carvalho de Melo | 7327259 | 2015-04-02 11:08:30 -0300 | [diff] [blame] | 859 | 			db_export__sample(&tables->dbe, event, sample, evsel, al); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 860 | 		else | 
| Arnaldo Carvalho de Melo | f9d5d54 | 2015-04-01 13:29:25 -0300 | [diff] [blame] | 861 | 			python_process_general_event(sample, evsel, al); | 
| Feng Tang | 6a6daec | 2012-08-08 17:57:51 +0800 | [diff] [blame] | 862 | 	} | 
 | 863 | } | 
 | 864 |  | 
| Jiri Olsa | aef9026 | 2016-01-05 22:09:11 +0100 | [diff] [blame] | 865 | static void get_handler_name(char *str, size_t size, | 
 | 866 | 			     struct perf_evsel *evsel) | 
 | 867 | { | 
 | 868 | 	char *p = str; | 
 | 869 |  | 
 | 870 | 	scnprintf(str, size, "stat__%s", perf_evsel__name(evsel)); | 
 | 871 |  | 
 | 872 | 	while ((p = strchr(p, ':'))) { | 
 | 873 | 		*p = '_'; | 
 | 874 | 		p++; | 
 | 875 | 	} | 
 | 876 | } | 
 | 877 |  | 
 | 878 | static void | 
 | 879 | process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp, | 
 | 880 | 	     struct perf_counts_values *count) | 
 | 881 | { | 
 | 882 | 	PyObject *handler, *t; | 
 | 883 | 	static char handler_name[256]; | 
 | 884 | 	int n = 0; | 
 | 885 |  | 
 | 886 | 	t = PyTuple_New(MAX_FIELDS); | 
 | 887 | 	if (!t) | 
 | 888 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 889 |  | 
 | 890 | 	get_handler_name(handler_name, sizeof(handler_name), | 
 | 891 | 			 counter); | 
 | 892 |  | 
 | 893 | 	handler = get_handler(handler_name); | 
 | 894 | 	if (!handler) { | 
 | 895 | 		pr_debug("can't find python handler %s\n", handler_name); | 
 | 896 | 		return; | 
 | 897 | 	} | 
 | 898 |  | 
 | 899 | 	PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 
 | 900 | 	PyTuple_SetItem(t, n++, PyInt_FromLong(thread)); | 
 | 901 |  | 
 | 902 | 	tuple_set_u64(t, n++, tstamp); | 
 | 903 | 	tuple_set_u64(t, n++, count->val); | 
 | 904 | 	tuple_set_u64(t, n++, count->ena); | 
 | 905 | 	tuple_set_u64(t, n++, count->run); | 
 | 906 |  | 
 | 907 | 	if (_PyTuple_Resize(&t, n) == -1) | 
 | 908 | 		Py_FatalError("error resizing Python tuple"); | 
 | 909 |  | 
 | 910 | 	call_object(handler, t, handler_name); | 
 | 911 |  | 
 | 912 | 	Py_DECREF(t); | 
 | 913 | } | 
 | 914 |  | 
 | 915 | static void python_process_stat(struct perf_stat_config *config, | 
 | 916 | 				struct perf_evsel *counter, u64 tstamp) | 
 | 917 | { | 
 | 918 | 	struct thread_map *threads = counter->threads; | 
 | 919 | 	struct cpu_map *cpus = counter->cpus; | 
 | 920 | 	int cpu, thread; | 
 | 921 |  | 
 | 922 | 	if (config->aggr_mode == AGGR_GLOBAL) { | 
 | 923 | 		process_stat(counter, -1, -1, tstamp, | 
 | 924 | 			     &counter->counts->aggr); | 
 | 925 | 		return; | 
 | 926 | 	} | 
 | 927 |  | 
 | 928 | 	for (thread = 0; thread < threads->nr; thread++) { | 
 | 929 | 		for (cpu = 0; cpu < cpus->nr; cpu++) { | 
 | 930 | 			process_stat(counter, cpus->map[cpu], | 
 | 931 | 				     thread_map__pid(threads, thread), tstamp, | 
 | 932 | 				     perf_counts(counter->counts, cpu, thread)); | 
 | 933 | 		} | 
 | 934 | 	} | 
 | 935 | } | 
 | 936 |  | 
 | 937 | static void python_process_stat_interval(u64 tstamp) | 
 | 938 | { | 
 | 939 | 	PyObject *handler, *t; | 
 | 940 | 	static const char handler_name[] = "stat__interval"; | 
 | 941 | 	int n = 0; | 
 | 942 |  | 
 | 943 | 	t = PyTuple_New(MAX_FIELDS); | 
 | 944 | 	if (!t) | 
 | 945 | 		Py_FatalError("couldn't create Python tuple"); | 
 | 946 |  | 
 | 947 | 	handler = get_handler(handler_name); | 
 | 948 | 	if (!handler) { | 
 | 949 | 		pr_debug("can't find python handler %s\n", handler_name); | 
 | 950 | 		return; | 
 | 951 | 	} | 
 | 952 |  | 
 | 953 | 	tuple_set_u64(t, n++, tstamp); | 
 | 954 |  | 
 | 955 | 	if (_PyTuple_Resize(&t, n) == -1) | 
 | 956 | 		Py_FatalError("error resizing Python tuple"); | 
 | 957 |  | 
 | 958 | 	call_object(handler, t, handler_name); | 
 | 959 |  | 
 | 960 | 	Py_DECREF(t); | 
 | 961 | } | 
 | 962 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 963 | static int run_start_sub(void) | 
 | 964 | { | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 965 | 	main_module = PyImport_AddModule("__main__"); | 
 | 966 | 	if (main_module == NULL) | 
 | 967 | 		return -1; | 
 | 968 | 	Py_INCREF(main_module); | 
 | 969 |  | 
 | 970 | 	main_dict = PyModule_GetDict(main_module); | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 971 | 	if (main_dict == NULL) | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 972 | 		goto error; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 973 | 	Py_INCREF(main_dict); | 
 | 974 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 975 | 	try_call_object("trace_begin", NULL); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 976 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 977 | 	return 0; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 978 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 979 | error: | 
 | 980 | 	Py_XDECREF(main_dict); | 
 | 981 | 	Py_XDECREF(main_module); | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 982 | 	return -1; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 983 | } | 
 | 984 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 985 | #define SET_TABLE_HANDLER_(name, handler_name, table_name) do {		\ | 
 | 986 | 	tables->handler_name = get_handler(#table_name);		\ | 
 | 987 | 	if (tables->handler_name)					\ | 
 | 988 | 		tables->dbe.export_ ## name = python_export_ ## name;	\ | 
 | 989 | } while (0) | 
 | 990 |  | 
 | 991 | #define SET_TABLE_HANDLER(name) \ | 
 | 992 | 	SET_TABLE_HANDLER_(name, name ## _handler, name ## _table) | 
 | 993 |  | 
 | 994 | static void set_table_handlers(struct tables *tables) | 
 | 995 | { | 
 | 996 | 	const char *perf_db_export_mode = "perf_db_export_mode"; | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 997 | 	const char *perf_db_export_calls = "perf_db_export_calls"; | 
 | 998 | 	PyObject *db_export_mode, *db_export_calls; | 
 | 999 | 	bool export_calls = false; | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1000 | 	int ret; | 
 | 1001 |  | 
 | 1002 | 	memset(tables, 0, sizeof(struct tables)); | 
 | 1003 | 	if (db_export__init(&tables->dbe)) | 
 | 1004 | 		Py_FatalError("failed to initialize export"); | 
 | 1005 |  | 
 | 1006 | 	db_export_mode = PyDict_GetItemString(main_dict, perf_db_export_mode); | 
 | 1007 | 	if (!db_export_mode) | 
 | 1008 | 		return; | 
 | 1009 |  | 
 | 1010 | 	ret = PyObject_IsTrue(db_export_mode); | 
 | 1011 | 	if (ret == -1) | 
 | 1012 | 		handler_call_die(perf_db_export_mode); | 
 | 1013 | 	if (!ret) | 
 | 1014 | 		return; | 
 | 1015 |  | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 1016 | 	tables->dbe.crp = NULL; | 
 | 1017 | 	db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); | 
 | 1018 | 	if (db_export_calls) { | 
 | 1019 | 		ret = PyObject_IsTrue(db_export_calls); | 
 | 1020 | 		if (ret == -1) | 
 | 1021 | 			handler_call_die(perf_db_export_calls); | 
 | 1022 | 		export_calls = !!ret; | 
 | 1023 | 	} | 
 | 1024 |  | 
 | 1025 | 	if (export_calls) { | 
 | 1026 | 		tables->dbe.crp = | 
 | 1027 | 			call_return_processor__new(python_process_call_return, | 
 | 1028 | 						   &tables->dbe); | 
 | 1029 | 		if (!tables->dbe.crp) | 
 | 1030 | 			Py_FatalError("failed to create calls processor"); | 
 | 1031 | 	} | 
 | 1032 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1033 | 	tables->db_export_mode = true; | 
 | 1034 | 	/* | 
 | 1035 | 	 * Reserve per symbol space for symbol->db_id via symbol__priv() | 
 | 1036 | 	 */ | 
 | 1037 | 	symbol_conf.priv_size = sizeof(u64); | 
 | 1038 |  | 
 | 1039 | 	SET_TABLE_HANDLER(evsel); | 
 | 1040 | 	SET_TABLE_HANDLER(machine); | 
 | 1041 | 	SET_TABLE_HANDLER(thread); | 
 | 1042 | 	SET_TABLE_HANDLER(comm); | 
 | 1043 | 	SET_TABLE_HANDLER(comm_thread); | 
 | 1044 | 	SET_TABLE_HANDLER(dso); | 
 | 1045 | 	SET_TABLE_HANDLER(symbol); | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 1046 | 	SET_TABLE_HANDLER(branch_type); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1047 | 	SET_TABLE_HANDLER(sample); | 
| Adrian Hunter | 6a70307 | 2014-10-30 16:09:47 +0200 | [diff] [blame] | 1048 | 	SET_TABLE_HANDLER(call_path); | 
 | 1049 | 	SET_TABLE_HANDLER(call_return); | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1050 | } | 
 | 1051 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1052 | /* | 
 | 1053 |  * Start trace script | 
 | 1054 |  */ | 
 | 1055 | static int python_start_script(const char *script, int argc, const char **argv) | 
 | 1056 | { | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1057 | 	struct tables *tables = &tables_global; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1058 | 	const char **command_line; | 
 | 1059 | 	char buf[PATH_MAX]; | 
 | 1060 | 	int i, err = 0; | 
 | 1061 | 	FILE *fp; | 
 | 1062 |  | 
 | 1063 | 	command_line = malloc((argc + 1) * sizeof(const char *)); | 
 | 1064 | 	command_line[0] = script; | 
 | 1065 | 	for (i = 1; i < argc + 1; i++) | 
 | 1066 | 		command_line[i] = argv[i - 1]; | 
 | 1067 |  | 
 | 1068 | 	Py_Initialize(); | 
 | 1069 |  | 
 | 1070 | 	initperf_trace_context(); | 
 | 1071 |  | 
 | 1072 | 	PySys_SetArgv(argc + 1, (char **)command_line); | 
 | 1073 |  | 
 | 1074 | 	fp = fopen(script, "r"); | 
 | 1075 | 	if (!fp) { | 
 | 1076 | 		sprintf(buf, "Can't open python script \"%s\"", script); | 
 | 1077 | 		perror(buf); | 
 | 1078 | 		err = -1; | 
 | 1079 | 		goto error; | 
 | 1080 | 	} | 
 | 1081 |  | 
 | 1082 | 	err = PyRun_SimpleFile(fp, script); | 
 | 1083 | 	if (err) { | 
 | 1084 | 		fprintf(stderr, "Error running python script %s\n", script); | 
 | 1085 | 		goto error; | 
 | 1086 | 	} | 
 | 1087 |  | 
 | 1088 | 	err = run_start_sub(); | 
 | 1089 | 	if (err) { | 
 | 1090 | 		fprintf(stderr, "Error starting python script %s\n", script); | 
 | 1091 | 		goto error; | 
 | 1092 | 	} | 
 | 1093 |  | 
 | 1094 | 	free(command_line); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1095 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1096 | 	set_table_handlers(tables); | 
 | 1097 |  | 
| Adrian Hunter | c29414f | 2014-10-30 16:09:44 +0200 | [diff] [blame] | 1098 | 	if (tables->db_export_mode) { | 
 | 1099 | 		err = db_export__branch_types(&tables->dbe); | 
 | 1100 | 		if (err) | 
 | 1101 | 			goto error; | 
 | 1102 | 	} | 
 | 1103 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1104 | 	return err; | 
 | 1105 | error: | 
 | 1106 | 	Py_Finalize(); | 
 | 1107 | 	free(command_line); | 
 | 1108 |  | 
 | 1109 | 	return err; | 
 | 1110 | } | 
 | 1111 |  | 
| Adrian Hunter | d445dd2 | 2014-08-15 22:08:37 +0300 | [diff] [blame] | 1112 | static int python_flush_script(void) | 
 | 1113 | { | 
| Adrian Hunter | 758008b | 2014-10-30 16:09:48 +0200 | [diff] [blame] | 1114 | 	struct tables *tables = &tables_global; | 
 | 1115 |  | 
 | 1116 | 	return db_export__flush(&tables->dbe); | 
| Adrian Hunter | d445dd2 | 2014-08-15 22:08:37 +0300 | [diff] [blame] | 1117 | } | 
 | 1118 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1119 | /* | 
 | 1120 |  * Stop trace script | 
 | 1121 |  */ | 
 | 1122 | static int python_stop_script(void) | 
 | 1123 | { | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1124 | 	struct tables *tables = &tables_global; | 
 | 1125 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 1126 | 	try_call_object("trace_end", NULL); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1127 |  | 
| Adrian Hunter | df919b4 | 2014-10-23 13:45:14 +0300 | [diff] [blame] | 1128 | 	db_export__exit(&tables->dbe); | 
 | 1129 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1130 | 	Py_XDECREF(main_dict); | 
 | 1131 | 	Py_XDECREF(main_module); | 
 | 1132 | 	Py_Finalize(); | 
 | 1133 |  | 
| Adrian Hunter | a5563ed | 2014-07-31 09:01:01 +0300 | [diff] [blame] | 1134 | 	return 0; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1135 | } | 
 | 1136 |  | 
| Arnaldo Carvalho de Melo | da37896 | 2012-06-27 13:08:42 -0300 | [diff] [blame] | 1137 | static int python_generate_script(struct pevent *pevent, const char *outfile) | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1138 | { | 
| Steven Rostedt | aaf045f | 2012-04-06 00:47:56 +0200 | [diff] [blame] | 1139 | 	struct event_format *event = NULL; | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1140 | 	struct format_field *f; | 
 | 1141 | 	char fname[PATH_MAX]; | 
 | 1142 | 	int not_first, count; | 
 | 1143 | 	FILE *ofp; | 
 | 1144 |  | 
 | 1145 | 	sprintf(fname, "%s.py", outfile); | 
 | 1146 | 	ofp = fopen(fname, "w"); | 
 | 1147 | 	if (ofp == NULL) { | 
 | 1148 | 		fprintf(stderr, "couldn't open %s\n", fname); | 
 | 1149 | 		return -1; | 
 | 1150 | 	} | 
| Ingo Molnar | 133dc4c | 2010-11-16 18:45:39 +0100 | [diff] [blame] | 1151 | 	fprintf(ofp, "# perf script event handlers, " | 
 | 1152 | 		"generated by perf script -g python\n"); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1153 |  | 
 | 1154 | 	fprintf(ofp, "# Licensed under the terms of the GNU GPL" | 
 | 1155 | 		" License version 2\n\n"); | 
 | 1156 |  | 
 | 1157 | 	fprintf(ofp, "# The common_* event handler fields are the most useful " | 
 | 1158 | 		"fields common to\n"); | 
 | 1159 |  | 
 | 1160 | 	fprintf(ofp, "# all events.  They don't necessarily correspond to " | 
 | 1161 | 		"the 'common_*' fields\n"); | 
 | 1162 |  | 
 | 1163 | 	fprintf(ofp, "# in the format files.  Those fields not available as " | 
 | 1164 | 		"handler params can\n"); | 
 | 1165 |  | 
 | 1166 | 	fprintf(ofp, "# be retrieved using Python functions of the form " | 
 | 1167 | 		"common_*(context).\n"); | 
 | 1168 |  | 
 | 1169 | 	fprintf(ofp, "# See the perf-trace-python Documentation for the list " | 
 | 1170 | 		"of available functions.\n\n"); | 
 | 1171 |  | 
 | 1172 | 	fprintf(ofp, "import os\n"); | 
 | 1173 | 	fprintf(ofp, "import sys\n\n"); | 
 | 1174 |  | 
 | 1175 | 	fprintf(ofp, "sys.path.append(os.environ['PERF_EXEC_PATH'] + \\\n"); | 
 | 1176 | 	fprintf(ofp, "\t'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')\n"); | 
 | 1177 | 	fprintf(ofp, "\nfrom perf_trace_context import *\n"); | 
 | 1178 | 	fprintf(ofp, "from Core import *\n\n\n"); | 
 | 1179 |  | 
 | 1180 | 	fprintf(ofp, "def trace_begin():\n"); | 
 | 1181 | 	fprintf(ofp, "\tprint \"in trace_begin\"\n\n"); | 
 | 1182 |  | 
 | 1183 | 	fprintf(ofp, "def trace_end():\n"); | 
 | 1184 | 	fprintf(ofp, "\tprint \"in trace_end\"\n\n"); | 
 | 1185 |  | 
| Arnaldo Carvalho de Melo | da37896 | 2012-06-27 13:08:42 -0300 | [diff] [blame] | 1186 | 	while ((event = trace_find_next_event(pevent, event))) { | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1187 | 		fprintf(ofp, "def %s__%s(", event->system, event->name); | 
 | 1188 | 		fprintf(ofp, "event_name, "); | 
 | 1189 | 		fprintf(ofp, "context, "); | 
 | 1190 | 		fprintf(ofp, "common_cpu,\n"); | 
 | 1191 | 		fprintf(ofp, "\tcommon_secs, "); | 
 | 1192 | 		fprintf(ofp, "common_nsecs, "); | 
 | 1193 | 		fprintf(ofp, "common_pid, "); | 
 | 1194 | 		fprintf(ofp, "common_comm,\n\t"); | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 1195 | 		fprintf(ofp, "common_callchain, "); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1196 |  | 
 | 1197 | 		not_first = 0; | 
 | 1198 | 		count = 0; | 
 | 1199 |  | 
 | 1200 | 		for (f = event->format.fields; f; f = f->next) { | 
 | 1201 | 			if (not_first++) | 
 | 1202 | 				fprintf(ofp, ", "); | 
 | 1203 | 			if (++count % 5 == 0) | 
 | 1204 | 				fprintf(ofp, "\n\t"); | 
 | 1205 |  | 
 | 1206 | 			fprintf(ofp, "%s", f->name); | 
 | 1207 | 		} | 
 | 1208 | 		fprintf(ofp, "):\n"); | 
 | 1209 |  | 
 | 1210 | 		fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " | 
 | 1211 | 			"common_secs, common_nsecs,\n\t\t\t" | 
 | 1212 | 			"common_pid, common_comm)\n\n"); | 
 | 1213 |  | 
 | 1214 | 		fprintf(ofp, "\t\tprint \""); | 
 | 1215 |  | 
 | 1216 | 		not_first = 0; | 
 | 1217 | 		count = 0; | 
 | 1218 |  | 
 | 1219 | 		for (f = event->format.fields; f; f = f->next) { | 
 | 1220 | 			if (not_first++) | 
 | 1221 | 				fprintf(ofp, ", "); | 
 | 1222 | 			if (count && count % 3 == 0) { | 
 | 1223 | 				fprintf(ofp, "\" \\\n\t\t\""); | 
 | 1224 | 			} | 
 | 1225 | 			count++; | 
 | 1226 |  | 
 | 1227 | 			fprintf(ofp, "%s=", f->name); | 
 | 1228 | 			if (f->flags & FIELD_IS_STRING || | 
 | 1229 | 			    f->flags & FIELD_IS_FLAG || | 
| Namhyung Kim | e646fe7 | 2014-05-29 13:44:55 +0900 | [diff] [blame] | 1230 | 			    f->flags & FIELD_IS_ARRAY || | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1231 | 			    f->flags & FIELD_IS_SYMBOLIC) | 
 | 1232 | 				fprintf(ofp, "%%s"); | 
 | 1233 | 			else if (f->flags & FIELD_IS_SIGNED) | 
 | 1234 | 				fprintf(ofp, "%%d"); | 
 | 1235 | 			else | 
 | 1236 | 				fprintf(ofp, "%%u"); | 
 | 1237 | 		} | 
 | 1238 |  | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 1239 | 		fprintf(ofp, "\" %% \\\n\t\t("); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1240 |  | 
 | 1241 | 		not_first = 0; | 
 | 1242 | 		count = 0; | 
 | 1243 |  | 
 | 1244 | 		for (f = event->format.fields; f; f = f->next) { | 
 | 1245 | 			if (not_first++) | 
 | 1246 | 				fprintf(ofp, ", "); | 
 | 1247 |  | 
 | 1248 | 			if (++count % 5 == 0) | 
 | 1249 | 				fprintf(ofp, "\n\t\t"); | 
 | 1250 |  | 
 | 1251 | 			if (f->flags & FIELD_IS_FLAG) { | 
 | 1252 | 				if ((count - 1) % 5 != 0) { | 
 | 1253 | 					fprintf(ofp, "\n\t\t"); | 
 | 1254 | 					count = 4; | 
 | 1255 | 				} | 
 | 1256 | 				fprintf(ofp, "flag_str(\""); | 
 | 1257 | 				fprintf(ofp, "%s__%s\", ", event->system, | 
 | 1258 | 					event->name); | 
 | 1259 | 				fprintf(ofp, "\"%s\", %s)", f->name, | 
 | 1260 | 					f->name); | 
 | 1261 | 			} else if (f->flags & FIELD_IS_SYMBOLIC) { | 
 | 1262 | 				if ((count - 1) % 5 != 0) { | 
 | 1263 | 					fprintf(ofp, "\n\t\t"); | 
 | 1264 | 					count = 4; | 
 | 1265 | 				} | 
 | 1266 | 				fprintf(ofp, "symbol_str(\""); | 
 | 1267 | 				fprintf(ofp, "%s__%s\", ", event->system, | 
 | 1268 | 					event->name); | 
 | 1269 | 				fprintf(ofp, "\"%s\", %s)", f->name, | 
 | 1270 | 					f->name); | 
 | 1271 | 			} else | 
 | 1272 | 				fprintf(ofp, "%s", f->name); | 
 | 1273 | 		} | 
 | 1274 |  | 
| Joseph Schuchart | 0f5f5bc | 2014-07-10 13:50:51 +0200 | [diff] [blame] | 1275 | 		fprintf(ofp, ")\n\n"); | 
 | 1276 |  | 
 | 1277 | 		fprintf(ofp, "\t\tfor node in common_callchain:"); | 
 | 1278 | 		fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | 
 | 1279 | 		fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | 
 | 1280 | 		fprintf(ofp, "\n\t\t\telse:"); | 
 | 1281 | 		fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | 
 | 1282 | 		fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | 
 | 1283 |  | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1284 | 	} | 
 | 1285 |  | 
 | 1286 | 	fprintf(ofp, "def trace_unhandled(event_name, context, " | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 1287 | 		"event_fields_dict):\n"); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1288 |  | 
| Pierre Tardy | c025148 | 2010-05-31 23:12:09 +0200 | [diff] [blame] | 1289 | 	fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))" | 
 | 1290 | 		"for k,v in sorted(event_fields_dict.items())])\n\n"); | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1291 |  | 
 | 1292 | 	fprintf(ofp, "def print_header(" | 
 | 1293 | 		"event_name, cpu, secs, nsecs, pid, comm):\n" | 
 | 1294 | 		"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" | 
 | 1295 | 		"(event_name, cpu, secs, nsecs, pid, comm),\n"); | 
 | 1296 |  | 
 | 1297 | 	fclose(ofp); | 
 | 1298 |  | 
 | 1299 | 	fprintf(stderr, "generated Python script: %s\n", fname); | 
 | 1300 |  | 
 | 1301 | 	return 0; | 
 | 1302 | } | 
 | 1303 |  | 
 | 1304 | struct scripting_ops python_scripting_ops = { | 
| Jiri Olsa | aef9026 | 2016-01-05 22:09:11 +0100 | [diff] [blame] | 1305 | 	.name			= "Python", | 
 | 1306 | 	.start_script		= python_start_script, | 
 | 1307 | 	.flush_script		= python_flush_script, | 
 | 1308 | 	.stop_script		= python_stop_script, | 
 | 1309 | 	.process_event		= python_process_event, | 
 | 1310 | 	.process_stat		= python_process_stat, | 
 | 1311 | 	.process_stat_interval	= python_process_stat_interval, | 
 | 1312 | 	.generate_script	= python_generate_script, | 
| Tom Zanussi | 7e4b21b | 2010-01-27 02:27:57 -0600 | [diff] [blame] | 1313 | }; |