diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-10-03 14:24:46 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-10-03 14:24:46 -0400 |
commit | 447a8b858e4bda41c394b1bc7fdbc9dc0bdf44f6 (patch) | |
tree | 676e741f2552c9cb301e1e49c557b92bf8940f55 /tools/perf/util/scripting-engines/trace-event-python.c | |
parent | 3049683eafdbbbd7350b0e5ca02a2d8c026a3362 (diff) | |
parent | 042e1c79166b9250edd8262bea84e1703f27ad2e (diff) |
Merge branch 'next' into for-linus
Prepare first round of input updates for 3.18.
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r-- | tools/perf/util/scripting-engines/trace-event-python.c | 197 |
1 files changed, 174 insertions, 23 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..cbce2545da45 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c | |||
@@ -27,11 +27,13 @@ | |||
27 | #include <errno.h> | 27 | #include <errno.h> |
28 | 28 | ||
29 | #include "../../perf.h" | 29 | #include "../../perf.h" |
30 | #include "../debug.h" | ||
30 | #include "../evsel.h" | 31 | #include "../evsel.h" |
31 | #include "../util.h" | 32 | #include "../util.h" |
32 | #include "../event.h" | 33 | #include "../event.h" |
33 | #include "../thread.h" | 34 | #include "../thread.h" |
34 | #include "../trace-event.h" | 35 | #include "../trace-event.h" |
36 | #include "../machine.h" | ||
35 | 37 | ||
36 | PyMODINIT_FUNC initperf_trace_context(void); | 38 | PyMODINIT_FUNC initperf_trace_context(void); |
37 | 39 | ||
@@ -50,10 +52,14 @@ static int zero_flag_atom; | |||
50 | 52 | ||
51 | static PyObject *main_module, *main_dict; | 53 | static PyObject *main_module, *main_dict; |
52 | 54 | ||
55 | static void handler_call_die(const char *handler_name) NORETURN; | ||
53 | static void handler_call_die(const char *handler_name) | 56 | static void handler_call_die(const char *handler_name) |
54 | { | 57 | { |
55 | PyErr_Print(); | 58 | PyErr_Print(); |
56 | Py_FatalError("problem in Python trace event handler"); | 59 | Py_FatalError("problem in Python trace event handler"); |
60 | // Py_FatalError does not return | ||
61 | // but we have to make the compiler happy | ||
62 | abort(); | ||
57 | } | 63 | } |
58 | 64 | ||
59 | /* | 65 | /* |
@@ -97,6 +103,7 @@ static void define_value(enum print_arg_type field_type, | |||
97 | retval = PyObject_CallObject(handler, t); | 103 | retval = PyObject_CallObject(handler, t); |
98 | if (retval == NULL) | 104 | if (retval == NULL) |
99 | handler_call_die(handler_name); | 105 | handler_call_die(handler_name); |
106 | Py_DECREF(retval); | ||
100 | } | 107 | } |
101 | 108 | ||
102 | Py_DECREF(t); | 109 | Py_DECREF(t); |
@@ -143,6 +150,7 @@ static void define_field(enum print_arg_type field_type, | |||
143 | retval = PyObject_CallObject(handler, t); | 150 | retval = PyObject_CallObject(handler, t); |
144 | if (retval == NULL) | 151 | if (retval == NULL) |
145 | handler_call_die(handler_name); | 152 | handler_call_die(handler_name); |
153 | Py_DECREF(retval); | ||
146 | } | 154 | } |
147 | 155 | ||
148 | Py_DECREF(t); | 156 | Py_DECREF(t); |
@@ -231,15 +239,133 @@ static inline struct event_format *find_cache_event(struct perf_evsel *evsel) | |||
231 | return event; | 239 | return event; |
232 | } | 240 | } |
233 | 241 | ||
242 | static PyObject *get_field_numeric_entry(struct event_format *event, | ||
243 | struct format_field *field, void *data) | ||
244 | { | ||
245 | bool is_array = field->flags & FIELD_IS_ARRAY; | ||
246 | PyObject *obj, *list = NULL; | ||
247 | unsigned long long val; | ||
248 | unsigned int item_size, n_items, i; | ||
249 | |||
250 | if (is_array) { | ||
251 | list = PyList_New(field->arraylen); | ||
252 | item_size = field->size / field->arraylen; | ||
253 | n_items = field->arraylen; | ||
254 | } else { | ||
255 | item_size = field->size; | ||
256 | n_items = 1; | ||
257 | } | ||
258 | |||
259 | for (i = 0; i < n_items; i++) { | ||
260 | |||
261 | val = read_size(event, data + field->offset + i * item_size, | ||
262 | item_size); | ||
263 | if (field->flags & FIELD_IS_SIGNED) { | ||
264 | if ((long long)val >= LONG_MIN && | ||
265 | (long long)val <= LONG_MAX) | ||
266 | obj = PyInt_FromLong(val); | ||
267 | else | ||
268 | obj = PyLong_FromLongLong(val); | ||
269 | } else { | ||
270 | if (val <= LONG_MAX) | ||
271 | obj = PyInt_FromLong(val); | ||
272 | else | ||
273 | obj = PyLong_FromUnsignedLongLong(val); | ||
274 | } | ||
275 | if (is_array) | ||
276 | PyList_SET_ITEM(list, i, obj); | ||
277 | } | ||
278 | if (is_array) | ||
279 | obj = list; | ||
280 | return obj; | ||
281 | } | ||
282 | |||
283 | |||
284 | static PyObject *python_process_callchain(struct perf_sample *sample, | ||
285 | struct perf_evsel *evsel, | ||
286 | struct addr_location *al) | ||
287 | { | ||
288 | PyObject *pylist; | ||
289 | |||
290 | pylist = PyList_New(0); | ||
291 | if (!pylist) | ||
292 | Py_FatalError("couldn't create Python list"); | ||
293 | |||
294 | if (!symbol_conf.use_callchain || !sample->callchain) | ||
295 | goto exit; | ||
296 | |||
297 | if (machine__resolve_callchain(al->machine, evsel, al->thread, | ||
298 | sample, NULL, NULL, | ||
299 | PERF_MAX_STACK_DEPTH) != 0) { | ||
300 | pr_err("Failed to resolve callchain. Skipping\n"); | ||
301 | goto exit; | ||
302 | } | ||
303 | callchain_cursor_commit(&callchain_cursor); | ||
304 | |||
305 | |||
306 | while (1) { | ||
307 | PyObject *pyelem; | ||
308 | struct callchain_cursor_node *node; | ||
309 | node = callchain_cursor_current(&callchain_cursor); | ||
310 | if (!node) | ||
311 | break; | ||
312 | |||
313 | pyelem = PyDict_New(); | ||
314 | if (!pyelem) | ||
315 | Py_FatalError("couldn't create Python dictionary"); | ||
316 | |||
317 | |||
318 | pydict_set_item_string_decref(pyelem, "ip", | ||
319 | PyLong_FromUnsignedLongLong(node->ip)); | ||
320 | |||
321 | if (node->sym) { | ||
322 | PyObject *pysym = PyDict_New(); | ||
323 | if (!pysym) | ||
324 | Py_FatalError("couldn't create Python dictionary"); | ||
325 | pydict_set_item_string_decref(pysym, "start", | ||
326 | PyLong_FromUnsignedLongLong(node->sym->start)); | ||
327 | pydict_set_item_string_decref(pysym, "end", | ||
328 | PyLong_FromUnsignedLongLong(node->sym->end)); | ||
329 | pydict_set_item_string_decref(pysym, "binding", | ||
330 | PyInt_FromLong(node->sym->binding)); | ||
331 | pydict_set_item_string_decref(pysym, "name", | ||
332 | PyString_FromStringAndSize(node->sym->name, | ||
333 | node->sym->namelen)); | ||
334 | pydict_set_item_string_decref(pyelem, "sym", pysym); | ||
335 | } | ||
336 | |||
337 | if (node->map) { | ||
338 | struct map *map = node->map; | ||
339 | const char *dsoname = "[unknown]"; | ||
340 | if (map && map->dso && (map->dso->name || map->dso->long_name)) { | ||
341 | if (symbol_conf.show_kernel_path && map->dso->long_name) | ||
342 | dsoname = map->dso->long_name; | ||
343 | else if (map->dso->name) | ||
344 | dsoname = map->dso->name; | ||
345 | } | ||
346 | pydict_set_item_string_decref(pyelem, "dso", | ||
347 | PyString_FromString(dsoname)); | ||
348 | } | ||
349 | |||
350 | callchain_cursor_advance(&callchain_cursor); | ||
351 | PyList_Append(pylist, pyelem); | ||
352 | Py_DECREF(pyelem); | ||
353 | } | ||
354 | |||
355 | exit: | ||
356 | return pylist; | ||
357 | } | ||
358 | |||
359 | |||
234 | static void python_process_tracepoint(struct perf_sample *sample, | 360 | static void python_process_tracepoint(struct perf_sample *sample, |
235 | struct perf_evsel *evsel, | 361 | struct perf_evsel *evsel, |
236 | struct thread *thread, | 362 | struct thread *thread, |
237 | struct addr_location *al) | 363 | struct addr_location *al) |
238 | { | 364 | { |
239 | PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; | 365 | PyObject *handler, *retval, *context, *t, *obj, *callchain; |
366 | PyObject *dict = NULL; | ||
240 | static char handler_name[256]; | 367 | static char handler_name[256]; |
241 | struct format_field *field; | 368 | struct format_field *field; |
242 | unsigned long long val; | ||
243 | unsigned long s, ns; | 369 | unsigned long s, ns; |
244 | struct event_format *event; | 370 | struct event_format *event; |
245 | unsigned n = 0; | 371 | unsigned n = 0; |
@@ -280,18 +406,23 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
280 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); | 406 | PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); |
281 | PyTuple_SetItem(t, n++, context); | 407 | PyTuple_SetItem(t, n++, context); |
282 | 408 | ||
409 | /* ip unwinding */ | ||
410 | callchain = python_process_callchain(sample, evsel, al); | ||
411 | |||
283 | if (handler) { | 412 | if (handler) { |
284 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); | 413 | PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); |
285 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); | 414 | PyTuple_SetItem(t, n++, PyInt_FromLong(s)); |
286 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); | 415 | PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); |
287 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); | 416 | PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); |
288 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); | 417 | PyTuple_SetItem(t, n++, PyString_FromString(comm)); |
418 | PyTuple_SetItem(t, n++, callchain); | ||
289 | } else { | 419 | } else { |
290 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); | 420 | pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); |
291 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); | 421 | pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); |
292 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); | 422 | pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); |
293 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); | 423 | pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); |
294 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); | 424 | pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); |
425 | pydict_set_item_string_decref(dict, "common_callchain", callchain); | ||
295 | } | 426 | } |
296 | for (field = event->format.fields; field; field = field->next) { | 427 | for (field = event->format.fields; field; field = field->next) { |
297 | if (field->flags & FIELD_IS_STRING) { | 428 | if (field->flags & FIELD_IS_STRING) { |
@@ -303,20 +434,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
303 | offset = field->offset; | 434 | offset = field->offset; |
304 | obj = PyString_FromString((char *)data + offset); | 435 | obj = PyString_FromString((char *)data + offset); |
305 | } else { /* FIELD_IS_NUMERIC */ | 436 | } else { /* FIELD_IS_NUMERIC */ |
306 | val = read_size(event, data + field->offset, | 437 | 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 | } | 438 | } |
321 | if (handler) | 439 | if (handler) |
322 | PyTuple_SetItem(t, n++, obj); | 440 | PyTuple_SetItem(t, n++, obj); |
@@ -324,6 +442,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
324 | pydict_set_item_string_decref(dict, field->name, obj); | 442 | pydict_set_item_string_decref(dict, field->name, obj); |
325 | 443 | ||
326 | } | 444 | } |
445 | |||
327 | if (!handler) | 446 | if (!handler) |
328 | PyTuple_SetItem(t, n++, dict); | 447 | PyTuple_SetItem(t, n++, dict); |
329 | 448 | ||
@@ -334,6 +453,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
334 | retval = PyObject_CallObject(handler, t); | 453 | retval = PyObject_CallObject(handler, t); |
335 | if (retval == NULL) | 454 | if (retval == NULL) |
336 | handler_call_die(handler_name); | 455 | handler_call_die(handler_name); |
456 | Py_DECREF(retval); | ||
337 | } else { | 457 | } else { |
338 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); | 458 | handler = PyDict_GetItemString(main_dict, "trace_unhandled"); |
339 | if (handler && PyCallable_Check(handler)) { | 459 | if (handler && PyCallable_Check(handler)) { |
@@ -341,6 +461,7 @@ static void python_process_tracepoint(struct perf_sample *sample, | |||
341 | retval = PyObject_CallObject(handler, t); | 461 | retval = PyObject_CallObject(handler, t); |
342 | if (retval == NULL) | 462 | if (retval == NULL) |
343 | handler_call_die("trace_unhandled"); | 463 | handler_call_die("trace_unhandled"); |
464 | Py_DECREF(retval); | ||
344 | } | 465 | } |
345 | Py_DECREF(dict); | 466 | Py_DECREF(dict); |
346 | } | 467 | } |
@@ -353,7 +474,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
353 | struct thread *thread, | 474 | struct thread *thread, |
354 | struct addr_location *al) | 475 | struct addr_location *al) |
355 | { | 476 | { |
356 | PyObject *handler, *retval, *t, *dict; | 477 | PyObject *handler, *retval, *t, *dict, *callchain, *dict_sample; |
357 | static char handler_name[64]; | 478 | static char handler_name[64]; |
358 | unsigned n = 0; | 479 | unsigned n = 0; |
359 | 480 | ||
@@ -369,6 +490,10 @@ static void python_process_general_event(struct perf_sample *sample, | |||
369 | if (!dict) | 490 | if (!dict) |
370 | Py_FatalError("couldn't create Python dictionary"); | 491 | Py_FatalError("couldn't create Python dictionary"); |
371 | 492 | ||
493 | dict_sample = PyDict_New(); | ||
494 | if (!dict_sample) | ||
495 | Py_FatalError("couldn't create Python dictionary"); | ||
496 | |||
372 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); | 497 | snprintf(handler_name, sizeof(handler_name), "%s", "process_event"); |
373 | 498 | ||
374 | handler = PyDict_GetItemString(main_dict, handler_name); | 499 | handler = PyDict_GetItemString(main_dict, handler_name); |
@@ -378,8 +503,21 @@ static void python_process_general_event(struct perf_sample *sample, | |||
378 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); | 503 | pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel))); |
379 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( | 504 | pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize( |
380 | (const char *)&evsel->attr, sizeof(evsel->attr))); | 505 | (const char *)&evsel->attr, sizeof(evsel->attr))); |
381 | pydict_set_item_string_decref(dict, "sample", PyString_FromStringAndSize( | 506 | |
382 | (const char *)sample, sizeof(*sample))); | 507 | pydict_set_item_string_decref(dict_sample, "pid", |
508 | PyInt_FromLong(sample->pid)); | ||
509 | pydict_set_item_string_decref(dict_sample, "tid", | ||
510 | PyInt_FromLong(sample->tid)); | ||
511 | pydict_set_item_string_decref(dict_sample, "cpu", | ||
512 | PyInt_FromLong(sample->cpu)); | ||
513 | pydict_set_item_string_decref(dict_sample, "ip", | ||
514 | PyLong_FromUnsignedLongLong(sample->ip)); | ||
515 | pydict_set_item_string_decref(dict_sample, "time", | ||
516 | PyLong_FromUnsignedLongLong(sample->time)); | ||
517 | pydict_set_item_string_decref(dict_sample, "period", | ||
518 | PyLong_FromUnsignedLongLong(sample->period)); | ||
519 | pydict_set_item_string_decref(dict, "sample", dict_sample); | ||
520 | |||
383 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( | 521 | pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize( |
384 | (const char *)sample->raw_data, sample->raw_size)); | 522 | (const char *)sample->raw_data, sample->raw_size)); |
385 | pydict_set_item_string_decref(dict, "comm", | 523 | pydict_set_item_string_decref(dict, "comm", |
@@ -393,6 +531,10 @@ static void python_process_general_event(struct perf_sample *sample, | |||
393 | PyString_FromString(al->sym->name)); | 531 | PyString_FromString(al->sym->name)); |
394 | } | 532 | } |
395 | 533 | ||
534 | /* ip unwinding */ | ||
535 | callchain = python_process_callchain(sample, evsel, al); | ||
536 | pydict_set_item_string_decref(dict, "callchain", callchain); | ||
537 | |||
396 | PyTuple_SetItem(t, n++, dict); | 538 | PyTuple_SetItem(t, n++, dict); |
397 | if (_PyTuple_Resize(&t, n) == -1) | 539 | if (_PyTuple_Resize(&t, n) == -1) |
398 | Py_FatalError("error resizing Python tuple"); | 540 | Py_FatalError("error resizing Python tuple"); |
@@ -400,6 +542,7 @@ static void python_process_general_event(struct perf_sample *sample, | |||
400 | retval = PyObject_CallObject(handler, t); | 542 | retval = PyObject_CallObject(handler, t); |
401 | if (retval == NULL) | 543 | if (retval == NULL) |
402 | handler_call_die(handler_name); | 544 | handler_call_die(handler_name); |
545 | Py_DECREF(retval); | ||
403 | exit: | 546 | exit: |
404 | Py_DECREF(dict); | 547 | Py_DECREF(dict); |
405 | Py_DECREF(t); | 548 | Py_DECREF(t); |
@@ -521,8 +664,7 @@ static int python_stop_script(void) | |||
521 | retval = PyObject_CallObject(handler, NULL); | 664 | retval = PyObject_CallObject(handler, NULL); |
522 | if (retval == NULL) | 665 | if (retval == NULL) |
523 | handler_call_die("trace_end"); | 666 | handler_call_die("trace_end"); |
524 | else | 667 | Py_DECREF(retval); |
525 | Py_DECREF(retval); | ||
526 | out: | 668 | out: |
527 | Py_XDECREF(main_dict); | 669 | Py_XDECREF(main_dict); |
528 | Py_XDECREF(main_module); | 670 | Py_XDECREF(main_module); |
@@ -589,6 +731,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
589 | fprintf(ofp, "common_nsecs, "); | 731 | fprintf(ofp, "common_nsecs, "); |
590 | fprintf(ofp, "common_pid, "); | 732 | fprintf(ofp, "common_pid, "); |
591 | fprintf(ofp, "common_comm,\n\t"); | 733 | fprintf(ofp, "common_comm,\n\t"); |
734 | fprintf(ofp, "common_callchain, "); | ||
592 | 735 | ||
593 | not_first = 0; | 736 | not_first = 0; |
594 | count = 0; | 737 | count = 0; |
@@ -632,7 +775,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
632 | fprintf(ofp, "%%u"); | 775 | fprintf(ofp, "%%u"); |
633 | } | 776 | } |
634 | 777 | ||
635 | fprintf(ofp, "\\n\" %% \\\n\t\t("); | 778 | fprintf(ofp, "\" %% \\\n\t\t("); |
636 | 779 | ||
637 | not_first = 0; | 780 | not_first = 0; |
638 | count = 0; | 781 | count = 0; |
@@ -668,7 +811,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) | |||
668 | fprintf(ofp, "%s", f->name); | 811 | fprintf(ofp, "%s", f->name); |
669 | } | 812 | } |
670 | 813 | ||
671 | fprintf(ofp, "),\n\n"); | 814 | fprintf(ofp, ")\n\n"); |
815 | |||
816 | fprintf(ofp, "\t\tfor node in common_callchain:"); | ||
817 | fprintf(ofp, "\n\t\t\tif 'sym' in node:"); | ||
818 | fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); | ||
819 | fprintf(ofp, "\n\t\t\telse:"); | ||
820 | fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n"); | ||
821 | fprintf(ofp, "\t\tprint \"\\n\"\n\n"); | ||
822 | |||
672 | } | 823 | } |
673 | 824 | ||
674 | fprintf(ofp, "def trace_unhandled(event_name, context, " | 825 | fprintf(ofp, "def trace_unhandled(event_name, context, " |