diff options
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 302 |
1 files changed, 220 insertions, 82 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index 1c419321f707..496f21cadd97 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -27,11 +27,14 @@ | |||
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | 28 | ||
29 | #include "../../perf.h" | 29 | #include "../../perf.h" |
30 | #include "../debug.h" | ||
31 | #include "../callchain.h" | ||
30 | #include "../evsel.h" | 32 | #include "../evsel.h" |
31 | #include "../util.h" | 33 | #include "../util.h" |
32 | #include "../event.h" | 34 | #include "../event.h" |
33 | #include "../thread.h" | 35 | #include "../thread.h" |
34 | #include "../trace-event.h" | 36 | #include "../trace-event.h" |
37 | #include "../machine.h" | ||
35 | 38 | ||
36 | PyMODINIT_FUNC initperf_trace_context(void); | 39 | PyMODINIT_FUNC initperf_trace_context(void); |
37 | 40 | ||
@@ -50,10 +53,14 @@ static int zero_flag_atom; | |||
50 | 53 | ||
51 | static PyObject *main_module, *main_dict; | 54 | static PyObject *main_module, *main_dict; |
52 | 55 | ||
56 | static void handler_call_die(const char *handler_name) NORETURN; | ||
53 | static void handler_call_die(const char *handler_name) | 57 | static void handler_call_die(const char *handler_name) |
54 | { | 58 | { |
55 | PyErr_Print(); | 59 | PyErr_Print(); |
56 | Py_FatalError("problem in Python trace event handler"); | 60 | Py_FatalError("problem in Python trace event handler"); |
61 | // Py_FatalError does not return | ||
62 | // but we have to make the compiler happy | ||
63 | abort(); | ||
57 | } | 64 | } |
58 | 65 | ||
59 | /* | 66 | /* |
@@ -67,6 +74,35 @@ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObj | |||
67 | Py_DECREF(val); | 74 | Py_DECREF(val); |
68 | } | 75 | } |
69 | 76 | ||
77 | static PyObject *get_handler(const char *handler_name) | ||
78 | { | ||
79 | PyObject *handler; | ||
80 | |||
81 | handler = PyDict_GetItemString(main_dict, handler_name); | ||
82 | if (handler && !PyCallable_Check(handler)) | ||
83 | return NULL; | ||
84 | return handler; | ||
85 | } | ||
86 | |||
87 | static void call_object(PyObject *handler, PyObject *args, const char *die_msg) | ||
88 | { | ||
89 | PyObject *retval; | ||
90 | |||
91 | retval = PyObject_CallObject(handler, args); | ||
92 | if (retval == NULL) | ||
93 | handler_call_die(die_msg); | ||
94 | Py_DECREF(retval); | ||
95 | } | ||
96 | |||
97 | static void try_call_object(const char *handler_name, PyObject *args) | ||
98 | { | ||
99 | PyObject *handler; | ||
100 | |||
101 | handler = get_handler(handler_name); | ||
102 | if (handler) | ||
103 | call_object(handler, args, handler_name); | ||
104 | } | ||
105 | |||
70 | static void define_value(enum print_arg_type field_type, | 106 | static void define_value(enum print_arg_type field_type, |
71 | const char *ev_name, | 107 | const char *ev_name, |
72 | const char *field_name, | 108 | const char *field_name, |
@@ -74,7 +110,7 @@ static void define_value(enum print_arg_type field_type, | |||
74 | const char *field_str) | 110 | const char *field_str) |
75 | { | 111 | { |
76 | const char *handler_name = "define_flag_value"; | 112 | const char *handler_name = "define_flag_value"; |
77 | PyObject *handler, *t, *retval; | 113 | PyObject *t; |
78 | unsigned long long value; | 114 | unsigned long long value; |
79 | unsigned n = 0; | 115 | unsigned n = 0; |
80 | 116 | ||
@@ -92,12 +128,7 @@ static void define_value(enum print_arg_type field_type, | |||
92 | PyTuple_SetItem(t, n++, PyInt_FromLong(value)); | 128 | PyTuple_SetItem(t, n++, PyInt_FromLong(value)); |
93 | PyTuple_SetItem(t, n++, PyString_FromString(field_str)); | 129 | PyTuple_SetItem(t, n++, PyString_FromString(field_str)); |
94 | 130 | ||
95 | handler = PyDict_GetItemString(main_dict, handler_name); | 131 | try_call_object(handler_name, t); |
96 | if (handler && PyCallable_Check(handler)) { | ||
97 | retval = PyObject_CallObject(handler, t); | ||
98 | if (retval == NULL) | ||
99 | handler_call_die(handler_name); | ||
100 | } | ||
101 | 132 | ||
102 | Py_DECREF(t); | 133 | Py_DECREF(t); |
103 | } | 134 | } |
@@ -120,7 +151,7 @@ static void define_field(enum print_arg_type field_type, | |||
120 | const char *delim) | 151 | const char *delim) |
121 | { | 152 | { |
122 | const char *handler_name = "define_flag_field"; | 153 | const char *handler_name = "define_flag_field"; |
123 | PyObject *handler, *t, *retval; | 154 | PyObject *t; |
124 | unsigned n = 0; | 155 | unsigned n = 0; |
125 | 156 | ||
126 | if (field_type == PRINT_SYMBOL) | 157 | if (field_type == PRINT_SYMBOL) |
@@ -138,12 +169,7 @@ static void define_field(enum print_arg_type field_type, | |||
138 | if (field_type == PRINT_FLAGS) | 169 | if (field_type == PRINT_FLAGS) |
139 | PyTuple_SetItem(t, n++, PyString_FromString(delim)); | 170 | PyTuple_SetItem(t, n++, PyString_FromString(delim)); |
140 | 171 | ||
141 | handler = PyDict_GetItemString(main_dict, handler_name); | 172 | try_call_object(handler_name, t); |
142 | if (handler && PyCallable_Check(handler)) { | ||
143 | retval = PyObject_CallObject(handler, t); | ||
144 | if (retval == NULL) | ||
145 | handler_call_die(handler_name); | ||
146 | } | ||
147 | 173 | ||
148 | Py_DECREF(t); | 174 | Py_DECREF(t); |
149 | } | 175 | } |
@@ -231,15 +257,133 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
231 | return event; | 257 | return event; |
232 | } | 258 | } |
233 | 259 | ||
260 | static PyObject *get_field_numeric_entry(struct event_format *event, | ||
261 | struct format_field *field, void *data) | ||
262 | { | ||
263 | bool is_array = field->flags & FIELD_IS_ARRAY; | ||
264 | PyObject *obj, *list = NULL; | ||
265 | unsigned long long val; | ||
266 | unsigned int item_size, n_items, i; | ||
267 | |||
268 | if (is_array) { | ||
269 | list = PyList_New(field->arraylen); | ||
270 | item_size = field->size / field->arraylen; | ||
271 | n_items = field->arraylen; | ||
272 | } else { | ||
273 | item_size = field->size; | ||
274 | n_items = 1; | ||
275 | } | ||
276 | |||
277 | for (i = 0; i < n_items; i++) { | ||
278 | |||
279 | val = read_size(event, data + field->offset + i * item_size, | ||
280 | item_size); | ||
281 | if (field->flags & FIELD_IS_SIGNED) { | ||
282 | if ((long long)val >= LONG_MIN && | ||
283 | (long long)val <= LONG_MAX) | ||
284 | obj = PyInt_FromLong(val); | ||
285 | else | ||
286 | obj = PyLong_FromLongLong(val); | ||
287 | } else { | ||
288 | if (val <= LONG_MAX) | ||
289 | obj = PyInt_FromLong(val); | ||
290 | else | ||
291 | obj = PyLong_FromUnsignedLongLong(val); | ||
292 | } | ||
293 | if (is_array) | ||
294 | PyList_SET_ITEM(list, i, obj); | ||
295 | } | ||
296 | if (is_array) | ||
297 | obj = list; | ||
298 | return obj; | ||
299 | } | ||
300 | |||
301 | |||
302 | static PyObject *python_process_callchain(struct perf_sample *sample, | ||
303 | struct perf_evsel *evsel, | ||
304 | struct addr_location *al) | ||
305 | { | ||
306 | PyObject *pylist; | ||
307 | |||
308 | pylist = PyList_New(0); | ||
309 | if (!pylist) | ||
310 | Py_FatalError("couldn't create Python list"); | ||
311 | |||
312 | if (!symbol_conf.use_callchain || !sample->callchain) | ||
313 | goto exit; | ||
314 | |||
315 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | ||
316 | sample, NULL, NULL, | ||
317 | PERF_MAX_STACK_DEPTH) != 0) { | ||
318 | pr_err("Failed to resolve callchain. Skipping\n"); | ||
319 | goto exit; | ||
320 | } | ||
321 | callchain_cursor_commit(&callchain_cursor); | ||
322 | |||
323 | |||
324 | while (1) { | ||
325 | PyObject *pyelem; | ||
326 | struct callchain_cursor_node *node; | ||
327 | node = callchain_cursor_current(&callchain_cursor); | ||
328 | if (!node) | ||
329 | break; | ||
330 | |||
331 | pyelem = PyDict_New(); | ||
332 | if (!pyelem) | ||
333 | Py_FatalError("couldn't create Python dictionary"); | ||
334 | |||
335 | |||
336 | pydict_set_item_string_decref(pyelem, "ip", | ||
337 | PyLong_FromUnsignedLongLong(node->ip)); | ||
338 | |||
339 | if (node->sym) { | ||
340 | PyObject *pysym = PyDict_New(); | ||
341 | if (!pysym) | ||
342 | Py_FatalError("couldn't create Python dictionary"); | ||
343 | pydict_set_item_string_decref(pysym, "start", | ||
344 | PyLong_FromUnsignedLongLong(node->sym->start)); | ||
345 | pydict_set_item_string_decref(pysym, "end", | ||
346 | PyLong_FromUnsignedLongLong(node->sym->end)); | ||
347 | pydict_set_item_string_decref(pysym, "binding", | ||
348 | PyInt_FromLong(node->sym->binding)); | ||
349 | pydict_set_item_string_decref(pysym, "name", | ||
350 | PyString_FromStringAndSize(node->sym->name, | ||
351 | node->sym->namelen)); | ||
352 | pydict_set_item_string_decref(pyelem, "sym", pysym); | ||
353 | } | ||
354 | |||
355 | if (node->map) { | ||
356 | struct map *map = node->map; | ||
357 | const char *dsoname = "[unknown]"; | ||
358 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { | ||
359 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
360 | dsoname = map->dso->long_name; | ||
361 | else if (map->dso->name) | ||
362 | dsoname = map->dso->name; | ||
363 | } | ||
364 | pydict_set_item_string_decref(pyelem, "dso", | ||
365 | PyString_FromString(dsoname)); | ||
366 | } | ||
367 | |||
368 | callchain_cursor_advance(&callchain_cursor); | ||
369 | PyList_Append(pylist, pyelem); | ||
370 | Py_DECREF(pyelem); | ||
371 | } | ||
372 | |||
373 | exit: | ||
374 | return pylist; | ||
375 | } | ||
376 | |||
377 | |||
234 | static void python_process_tracepoint(struct perf_sample *sample, | 378 | static void python_process_tracepoint(struct perf_sample *sample, |
235 | struct perf_evsel *evsel, | 379 | struct perf_evsel *evsel, |
236 | struct thread *thread, | 380 | struct thread *thread, |
237 | struct addr_location *al) | 381 | struct addr_location *al) |
238 | { | 382 | { |
239 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 383 | PyObject *handler, *context, *t, *obj, *callchain; |
384 | PyObject *dict = NULL; | ||
240 | static char handler_name[256]; | 385 | static char handler_name[256]; |
241 | struct format_field *field; | 386 | struct format_field *field; |
242 | unsigned long long val; | ||
243 | unsigned long s, ns; | 387 | unsigned long s, ns; |
244 | struct event_format *event; | 388 | struct event_format *event; |
245 | unsigned n = 0; | 389 | unsigned n = 0; |
@@ -261,9 +405,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
261 | 405 | ||
262 | sprintf(handler_name, "%s__%s", event->system, event->name); | 406 | sprintf(handler_name, "%s__%s", event->system, event->name); |
263 | 407 | ||
264 | handler = PyDict_GetItemString(main_dict, handler_name); | 408 | handler = get_handler(handler_name); |
265 | if (handler && !PyCallable_Check(handler)) | ||
266 | handler = NULL; | ||
267 | if (!handler) { | 409 | if (!handler) { |
268 | dict = PyDict_New(); | 410 | dict = PyDict_New(); |
269 | if (!dict) | 411 | if (!dict) |
@@ -280,18 +422,23 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
280 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); | 422 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); |
281 | PyTuple_SetItem(t, n++, context); | 423 | PyTuple_SetItem(t, n++, context); |
282 | 424 | ||
425 | /* ip unwinding */ | ||
426 | callchain = python_process_callchain(sample, evsel, al); | ||
427 | |||
283 | if (handler) { | 428 | if (handler) { |
284 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 429 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); |
285 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); | 430 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); |
286 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); | 431 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); |
287 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); | 432 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); |
288 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); | 433 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); |
434 | PyTuple_SetItem(t, n++, callchain); | ||
289 | } else { | 435 | } else { |
290 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); | 436 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); |
291 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); | 437 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); |
292 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); | 438 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); |
293 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); | 439 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); |
294 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); | 440 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); |
441 | pydict_set_item_string_decref(dict, "common_callchain", callchain); | ||
295 | } | 442 | } |
296 | for (field = event->format.fields; field; field = field->next) { | 443 | for (field = event->format.fields; field; field = field->next) { |
297 | if (field->flags & FIELD_IS_STRING) { | 444 | if (field->flags & FIELD_IS_STRING) { |
@@ -303,20 +450,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
303 | offset = field->offset; | 450 | offset = field->offset; |
304 | obj = PyString_FromString((char *)data + offset); | 451 | obj = PyString_FromString((char *)data + offset); |
305 | } else { /* FIELD_IS_NUMERIC */ | 452 | } else { /* FIELD_IS_NUMERIC */ |
306 | val = read_size(event, data + field->offset, | 453 | obj = get_field_numeric_entry(event, field, data); |
307 | field->size); | ||
308 | if (field->flags & FIELD_IS_SIGNED) { | ||
309 | if ((long long)val >= LONG_MIN && | ||
310 | (long long)val <= LONG_MAX) | ||
311 | obj = PyInt_FromLong(val); | ||
312 | else | ||
313 | obj = PyLong_FromLongLong(val); | ||
314 | } else { | ||
315 | if (val <= LONG_MAX) | ||
316 | obj = PyInt_FromLong(val); | ||
317 | else | ||
318 | obj = PyLong_FromUnsignedLongLong(val); | ||
319 | } | ||
320 | } | 454 | } |
321 | if (handler) | 455 | if (handler) |
322 | PyTuple_SetItem(t, n++, obj); | 456 | PyTuple_SetItem(t, n++, obj); |
@@ -324,6 +458,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
324 | pydict_set_item_string_decref(dict, field->name, obj); | 458 | pydict_set_item_string_decref(dict, field->name, obj); |
325 | 459 | ||
326 | } | 460 | } |
461 | |||
327 | if (!handler) | 462 | if (!handler) |
328 | PyTuple_SetItem(t, n++, dict); | 463 | PyTuple_SetItem(t, n++, dict); |
329 | 464 | ||
@@ -331,17 +466,9 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
331 | Py_FatalError("error resizing Python tuple"); | 466 | Py_FatalError("error resizing Python tuple"); |
332 | 467 | ||
333 | if (handler) { | 468 | if (handler) { |
334 | retval = PyObject_CallObject(handler, t); | 469 | call_object(handler, t, handler_name); |
335 | if (retval == NULL) | ||
336 | handler_call_die(handler_name); | ||
337 | } else { | 470 | } else { |
338 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); | 471 | try_call_object("trace_unhandled", t); |
339 | if (handler && PyCallable_Check(handler)) { | ||
340 | |||
341 | retval = PyObject_CallObject(handler, t); | ||
342 | if (retval == NULL) | ||
343 | handler_call_die("trace_unhandled"); | ||
344 | } | ||
345 | Py_DECREF(dict); | 472 | Py_DECREF(dict); |
346 | } | 473 | } |
347 | 474 | ||
@@ -353,7 +480,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
353 | struct thread *thread, | 480 | struct thread *thread, |
354 | struct addr_location *al) | 481 | struct addr_location *al) |
355 | { | 482 | { |
356 | PyObject *handler, *retval, *t, *dict; | 483 | PyObject *handler, *t, *dict, *callchain, *dict_sample; |
357 | static char handler_name[64]; | 484 | static char handler_name[64]; |
358 | unsigned n = 0; | 485 | unsigned n = 0; |
359 | 486 | ||
@@ -369,17 +496,34 @@ static void python_process_general_event(struct perf_sample *sample, | |||
369 | if (!dict) | 496 | if (!dict) |
370 | Py_FatalError("couldn't create Python dictionary"); | 497 | Py_FatalError("couldn't create Python dictionary"); |
371 | 498 | ||
499 | dict_sample = PyDict_New(); | ||
500 | if (!dict_sample) | ||
501 | Py_FatalError("couldn't create Python dictionary"); | ||
502 | |||
372 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | 503 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); |
373 | 504 | ||
374 | handler = PyDict_GetItemString(main_dict, handler_name); | 505 | handler = get_handler(handler_name); |
375 | if (!handler || !PyCallable_Check(handler)) | 506 | if (!handler) |
376 | goto exit; | 507 | goto exit; |
377 | 508 | ||
378 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | 509 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); |
379 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( | 510 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( |
380 | (const char *)&evsel->attr, sizeof(evsel->attr))); | 511 | (const char *)&evsel->attr, sizeof(evsel->attr))); |
381 | pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( | 512 | |
382 | (const char *)sample, sizeof(*sample))); | 513 | pydict_set_item_string_decref(dict_sample, "pid", |
514 | PyInt_FromLong(sample->pid)); | ||
515 | pydict_set_item_string_decref(dict_sample, "tid", | ||
516 | PyInt_FromLong(sample->tid)); | ||
517 | pydict_set_item_string_decref(dict_sample, "cpu", | ||
518 | PyInt_FromLong(sample->cpu)); | ||
519 | pydict_set_item_string_decref(dict_sample, "ip", | ||
520 | PyLong_FromUnsignedLongLong(sample->ip)); | ||
521 | pydict_set_item_string_decref(dict_sample, "time", | ||
522 | PyLong_FromUnsignedLongLong(sample->time)); | ||
523 | pydict_set_item_string_decref(dict_sample, "period", | ||
524 | PyLong_FromUnsignedLongLong(sample->period)); | ||
525 | pydict_set_item_string_decref(dict, "sample", dict_sample); | ||
526 | |||
383 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( | 527 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( |
384 | (const char *)sample->raw_data, sample->raw_size)); | 528 | (const char *)sample->raw_data, sample->raw_size)); |
385 | pydict_set_item_string_decref(dict, "comm", | 529 | pydict_set_item_string_decref(dict, "comm", |
@@ -393,13 +537,15 @@ static void python_process_general_event(struct perf_sample *sample, | |||
393 | PyString_FromString(al->sym->name)); | 537 | PyString_FromString(al->sym->name)); |
394 | } | 538 | } |
395 | 539 | ||
540 | /* ip unwinding */ | ||
541 | callchain = python_process_callchain(sample, evsel, al); | ||
542 | pydict_set_item_string_decref(dict, "callchain", callchain); | ||
543 | |||
396 | PyTuple_SetItem(t, n++, dict); | 544 | PyTuple_SetItem(t, n++, dict); |
397 | if (_PyTuple_Resize(&t, n) == -1) | 545 | if (_PyTuple_Resize(&t, n) == -1) |
398 | Py_FatalError("error resizing Python tuple"); | 546 | Py_FatalError("error resizing Python tuple"); |
399 | 547 | ||
400 | retval = PyObject_CallObject(handler, t); | 548 | call_object(handler, t, handler_name); |
401 | if (retval == NULL) | ||
402 | handler_call_die(handler_name); | ||
403 | exit: | 549 | exit: |
404 | Py_DECREF(dict); | 550 | Py_DECREF(dict); |
405 | Py_DECREF(t); | 551 | Py_DECREF(t); |
@@ -423,36 +569,24 @@ static void python_process_event(union perf_event *event __maybe_unused, | |||
423 | 569 | ||
424 | static int run_start_sub(void) | 570 | static int run_start_sub(void) |
425 | { | 571 | { |
426 | PyObject *handler, *retval; | ||
427 | int err = 0; | ||
428 | |||
429 | main_module = PyImport_AddModule("__main__"); | 572 | main_module = PyImport_AddModule("__main__"); |
430 | if (main_module == NULL) | 573 | if (main_module == NULL) |
431 | return -1; | 574 | return -1; |
432 | Py_INCREF(main_module); | 575 | Py_INCREF(main_module); |
433 | 576 | ||
434 | main_dict = PyModule_GetDict(main_module); | 577 | main_dict = PyModule_GetDict(main_module); |
435 | if (main_dict == NULL) { | 578 | if (main_dict == NULL) |
436 | err = -1; | ||
437 | goto error; | 579 | goto error; |
438 | } | ||
439 | Py_INCREF(main_dict); | 580 | Py_INCREF(main_dict); |
440 | 581 | ||
441 | handler = PyDict_GetItemString(main_dict, "trace_begin"); | 582 | try_call_object("trace_begin", NULL); |
442 | if (handler == NULL || !PyCallable_Check(handler)) | ||
443 | goto out; | ||
444 | 583 | ||
445 | retval = PyObject_CallObject(handler, NULL); | 584 | return 0; |
446 | if (retval == NULL) | ||
447 | handler_call_die("trace_begin"); | ||
448 | 585 | ||
449 | Py_DECREF(retval); | ||
450 | return err; | ||
451 | error: | 586 | error: |
452 | Py_XDECREF(main_dict); | 587 | Py_XDECREF(main_dict); |
453 | Py_XDECREF(main_module); | 588 | Py_XDECREF(main_module); |
454 | out: | 589 | return -1; |
455 | return err; | ||
456 | } | 590 | } |
457 | 591 | ||
458 | /* | 592 | /* |
@@ -506,29 +640,23 @@ error: | |||
506 | return err; | 640 | return err; |
507 | } | 641 | } |
508 | 642 | ||
643 | static int python_flush_script(void) | ||
644 | { | ||
645 | return 0; | ||
646 | } | ||
647 | |||
509 | /* | 648 | /* |
510 | * Stop trace script | 649 | * Stop trace script |
511 | */ | 650 | */ |
512 | static int python_stop_script(void) | 651 | static int python_stop_script(void) |
513 | { | 652 | { |
514 | PyObject *handler, *retval; | 653 | try_call_object("trace_end", NULL); |
515 | int err = 0; | ||
516 | |||
517 | handler = PyDict_GetItemString(main_dict, "trace_end"); | ||
518 | if (handler == NULL || !PyCallable_Check(handler)) | ||
519 | goto out; | ||
520 | 654 | ||
521 | retval = PyObject_CallObject(handler, NULL); | ||
522 | if (retval == NULL) | ||
523 | handler_call_die("trace_end"); | ||
524 | else | ||
525 | Py_DECREF(retval); | ||
526 | out: | ||
527 | Py_XDECREF(main_dict); | 655 | Py_XDECREF(main_dict); |
528 | Py_XDECREF(main_module); | 656 | Py_XDECREF(main_module); |
529 | Py_Finalize(); | 657 | Py_Finalize(); |
530 | 658 | ||
531 | return err; | 659 | return 0; |
532 | } | 660 | } |
533 | 661 | ||
534 | static int python_generate_script(struct pevent *pevent, const char *outfile) | 662 | static int python_generate_script(struct pevent *pevent, const char *outfile) |
@@ -589,6 +717,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
589 | fprintf(ofp, "common_nsecs, "); | 717 | fprintf(ofp, "common_nsecs, "); |
590 | fprintf(ofp, "common_pid, "); | 718 | fprintf(ofp, "common_pid, "); |
591 | fprintf(ofp, "common_comm,\n\t"); | 719 | fprintf(ofp, "common_comm,\n\t"); |
720 | fprintf(ofp, "common_callchain, "); | ||
592 | 721 | ||
593 | not_first = 0; | 722 | not_first = 0; |
594 | count = 0; | 723 | count = 0; |
@@ -632,7 +761,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
632 | fprintf(ofp, "%%u"); | 761 | fprintf(ofp, "%%u"); |
633 | } | 762 | } |
634 | 763 | ||
635 | fprintf(ofp, "\\n\" %% \\\n\t\t("); | 764 | fprintf(ofp, "\" %% \\\n\t\t("); |
636 | 765 | ||
637 | not_first = 0; | 766 | not_first = 0; |
638 | count = 0; | 767 | count = 0; |
@@ -668,7 +797,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
668 | fprintf(ofp, "%s", f->name); | 797 | fprintf(ofp, "%s", f->name); |
669 | } | 798 | } |
670 | 799 | ||
671 | fprintf(ofp, "),\n\n"); | 800 | fprintf(ofp, ")\n\n"); |
801 | |||
802 | fprintf(ofp, "\t\tfor node in common_callchain:"); | ||
803 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | ||
804 | fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | ||
805 | fprintf(ofp, "\n\t\t\telse:"); | ||
806 | fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | ||
807 | fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | ||
808 | |||
672 | } | 809 | } |
673 | 810 | ||
674 | fprintf(ofp, "def trace_unhandled(event_name, context, " | 811 | fprintf(ofp, "def trace_unhandled(event_name, context, " |
@@ -692,6 +829,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
692 | struct scripting_ops python_scripting_ops = { | 829 | struct scripting_ops python_scripting_ops = { |
693 | .name = "Python", | 830 | .name = "Python", |
694 | .start_script = python_start_script, | 831 | .start_script = python_start_script, |
832 | .flush_script = python_flush_script, | ||
695 | .stop_script = python_stop_script, | 833 | .stop_script = python_stop_script, |
696 | .process_event = python_process_event, | 834 | .process_event = python_process_event, |
697 | .generate_script = python_generate_script, | 835 | .generate_script = python_generate_script, |