aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/scripting-engines/trace-event-python.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c246
1 files changed, 184 insertions, 62 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
116 return handler; 116 return handler;
117} 117}
118 118
119static int get_argument_count(PyObject *handler)
120{
121 int arg_count = 0;
122
123 /*
124 * The attribute for the code object is func_code in Python 2,
125 * whereas it is __code__ in Python 3.0+.
126 */
127 PyObject *code_obj = PyObject_GetAttrString(handler,
128 "func_code");
129 if (PyErr_Occurred()) {
130 PyErr_Clear();
131 code_obj = PyObject_GetAttrString(handler,
132 "__code__");
133 }
134 PyErr_Clear();
135 if (code_obj) {
136 PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
137 "co_argcount");
138 if (arg_count_obj) {
139 arg_count = (int) PyInt_AsLong(arg_count_obj);
140 Py_DECREF(arg_count_obj);
141 }
142 Py_DECREF(code_obj);
143 }
144 return arg_count;
145}
146
119static void call_object(PyObject *handler, PyObject *args, const char *die_msg) 147static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
120{ 148{
121 PyObject *retval; 149 PyObject *retval;
@@ -391,13 +419,115 @@ exit:
391 return pylist; 419 return pylist;
392} 420}
393 421
422static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
423{
424 PyObject *t;
425
426 t = PyTuple_New(2);
427 if (!t)
428 Py_FatalError("couldn't create Python tuple");
429 PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
430 PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
431 return t;
432}
433
434static void set_sample_read_in_dict(PyObject *dict_sample,
435 struct perf_sample *sample,
436 struct perf_evsel *evsel)
437{
438 u64 read_format = evsel->attr.read_format;
439 PyObject *values;
440 unsigned int i;
441
442 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
443 pydict_set_item_string_decref(dict_sample, "time_enabled",
444 PyLong_FromUnsignedLongLong(sample->read.time_enabled));
445 }
446
447 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
448 pydict_set_item_string_decref(dict_sample, "time_running",
449 PyLong_FromUnsignedLongLong(sample->read.time_running));
450 }
451
452 if (read_format & PERF_FORMAT_GROUP)
453 values = PyList_New(sample->read.group.nr);
454 else
455 values = PyList_New(1);
456
457 if (!values)
458 Py_FatalError("couldn't create Python list");
459
460 if (read_format & PERF_FORMAT_GROUP) {
461 for (i = 0; i < sample->read.group.nr; i++) {
462 PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
463 PyList_SET_ITEM(values, i, t);
464 }
465 } else {
466 PyObject *t = get_sample_value_as_tuple(&sample->read.one);
467 PyList_SET_ITEM(values, 0, t);
468 }
469 pydict_set_item_string_decref(dict_sample, "values", values);
470}
471
472static PyObject *get_perf_sample_dict(struct perf_sample *sample,
473 struct perf_evsel *evsel,
474 struct addr_location *al,
475 PyObject *callchain)
476{
477 PyObject *dict, *dict_sample;
478
479 dict = PyDict_New();
480 if (!dict)
481 Py_FatalError("couldn't create Python dictionary");
482
483 dict_sample = PyDict_New();
484 if (!dict_sample)
485 Py_FatalError("couldn't create Python dictionary");
486
487 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
488 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
489 (const char *)&evsel->attr, sizeof(evsel->attr)));
490
491 pydict_set_item_string_decref(dict_sample, "pid",
492 PyInt_FromLong(sample->pid));
493 pydict_set_item_string_decref(dict_sample, "tid",
494 PyInt_FromLong(sample->tid));
495 pydict_set_item_string_decref(dict_sample, "cpu",
496 PyInt_FromLong(sample->cpu));
497 pydict_set_item_string_decref(dict_sample, "ip",
498 PyLong_FromUnsignedLongLong(sample->ip));
499 pydict_set_item_string_decref(dict_sample, "time",
500 PyLong_FromUnsignedLongLong(sample->time));
501 pydict_set_item_string_decref(dict_sample, "period",
502 PyLong_FromUnsignedLongLong(sample->period));
503 set_sample_read_in_dict(dict_sample, sample, evsel);
504 pydict_set_item_string_decref(dict, "sample", dict_sample);
505
506 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
507 (const char *)sample->raw_data, sample->raw_size));
508 pydict_set_item_string_decref(dict, "comm",
509 PyString_FromString(thread__comm_str(al->thread)));
510 if (al->map) {
511 pydict_set_item_string_decref(dict, "dso",
512 PyString_FromString(al->map->dso->name));
513 }
514 if (al->sym) {
515 pydict_set_item_string_decref(dict, "symbol",
516 PyString_FromString(al->sym->name));
517 }
518
519 pydict_set_item_string_decref(dict, "callchain", callchain);
520
521 return dict;
522}
523
394static void python_process_tracepoint(struct perf_sample *sample, 524static void python_process_tracepoint(struct perf_sample *sample,
395 struct perf_evsel *evsel, 525 struct perf_evsel *evsel,
396 struct addr_location *al) 526 struct addr_location *al)
397{ 527{
398 struct event_format *event = evsel->tp_format; 528 struct event_format *event = evsel->tp_format;
399 PyObject *handler, *context, *t, *obj = NULL, *callchain; 529 PyObject *handler, *context, *t, *obj = NULL, *callchain;
400 PyObject *dict = NULL; 530 PyObject *dict = NULL, *all_entries_dict = NULL;
401 static char handler_name[256]; 531 static char handler_name[256];
402 struct format_field *field; 532 struct format_field *field;
403 unsigned long s, ns; 533 unsigned long s, ns;
@@ -407,10 +537,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
407 void *data = sample->raw_data; 537 void *data = sample->raw_data;
408 unsigned long long nsecs = sample->time; 538 unsigned long long nsecs = sample->time;
409 const char *comm = thread__comm_str(al->thread); 539 const char *comm = thread__comm_str(al->thread);
410 540 const char *default_handler_name = "trace_unhandled";
411 t = PyTuple_New(MAX_FIELDS);
412 if (!t)
413 Py_FatalError("couldn't create Python tuple");
414 541
415 if (!event) { 542 if (!event) {
416 snprintf(handler_name, sizeof(handler_name), 543 snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +554,19 @@ static void python_process_tracepoint(struct perf_sample *sample,
427 554
428 handler = get_handler(handler_name); 555 handler = get_handler(handler_name);
429 if (!handler) { 556 if (!handler) {
557 handler = get_handler(default_handler_name);
558 if (!handler)
559 return;
430 dict = PyDict_New(); 560 dict = PyDict_New();
431 if (!dict) 561 if (!dict)
432 Py_FatalError("couldn't create Python dict"); 562 Py_FatalError("couldn't create Python dict");
433 } 563 }
564
565 t = PyTuple_New(MAX_FIELDS);
566 if (!t)
567 Py_FatalError("couldn't create Python tuple");
568
569
434 s = nsecs / NSEC_PER_SEC; 570 s = nsecs / NSEC_PER_SEC;
435 ns = nsecs - s * NSEC_PER_SEC; 571 ns = nsecs - s * NSEC_PER_SEC;
436 572
@@ -444,8 +580,10 @@ static void python_process_tracepoint(struct perf_sample *sample,
444 580
445 /* ip unwinding */ 581 /* ip unwinding */
446 callchain = python_process_callchain(sample, evsel, al); 582 callchain = python_process_callchain(sample, evsel, al);
583 /* Need an additional reference for the perf_sample dict */
584 Py_INCREF(callchain);
447 585
448 if (handler) { 586 if (!dict) {
449 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 587 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
450 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 588 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
451 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 589 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,26 +622,35 @@ static void python_process_tracepoint(struct perf_sample *sample,
484 } else { /* FIELD_IS_NUMERIC */ 622 } else { /* FIELD_IS_NUMERIC */
485 obj = get_field_numeric_entry(event, field, data); 623 obj = get_field_numeric_entry(event, field, data);
486 } 624 }
487 if (handler) 625 if (!dict)
488 PyTuple_SetItem(t, n++, obj); 626 PyTuple_SetItem(t, n++, obj);
489 else 627 else
490 pydict_set_item_string_decref(dict, field->name, obj); 628 pydict_set_item_string_decref(dict, field->name, obj);
491 629
492 } 630 }
493 631
494 if (!handler) 632 if (dict)
495 PyTuple_SetItem(t, n++, dict); 633 PyTuple_SetItem(t, n++, dict);
496 634
635 if (get_argument_count(handler) == (int) n + 1) {
636 all_entries_dict = get_perf_sample_dict(sample, evsel, al,
637 callchain);
638 PyTuple_SetItem(t, n++, all_entries_dict);
639 } else {
640 Py_DECREF(callchain);
641 }
642
497 if (_PyTuple_Resize(&t, n) == -1) 643 if (_PyTuple_Resize(&t, n) == -1)
498 Py_FatalError("error resizing Python tuple"); 644 Py_FatalError("error resizing Python tuple");
499 645
500 if (handler) { 646 if (!dict) {
501 call_object(handler, t, handler_name); 647 call_object(handler, t, handler_name);
502 } else { 648 } else {
503 try_call_object("trace_unhandled", t); 649 call_object(handler, t, default_handler_name);
504 Py_DECREF(dict); 650 Py_DECREF(dict);
505 } 651 }
506 652
653 Py_XDECREF(all_entries_dict);
507 Py_DECREF(t); 654 Py_DECREF(t);
508} 655}
509 656
@@ -795,10 +942,16 @@ static void python_process_general_event(struct perf_sample *sample,
795 struct perf_evsel *evsel, 942 struct perf_evsel *evsel,
796 struct addr_location *al) 943 struct addr_location *al)
797{ 944{
798 PyObject *handler, *t, *dict, *callchain, *dict_sample; 945 PyObject *handler, *t, *dict, *callchain;
799 static char handler_name[64]; 946 static char handler_name[64];
800 unsigned n = 0; 947 unsigned n = 0;
801 948
949 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
950
951 handler = get_handler(handler_name);
952 if (!handler)
953 return;
954
802 /* 955 /*
803 * Use the MAX_FIELDS to make the function expandable, though 956 * Use the MAX_FIELDS to make the function expandable, though
804 * currently there is only one item for the tuple. 957 * currently there is only one item for the tuple.
@@ -807,61 +960,16 @@ static void python_process_general_event(struct perf_sample *sample,
807 if (!t) 960 if (!t)
808 Py_FatalError("couldn't create Python tuple"); 961 Py_FatalError("couldn't create Python tuple");
809 962
810 dict = PyDict_New();
811 if (!dict)
812 Py_FatalError("couldn't create Python dictionary");
813
814 dict_sample = PyDict_New();
815 if (!dict_sample)
816 Py_FatalError("couldn't create Python dictionary");
817
818 snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
819
820 handler = get_handler(handler_name);
821 if (!handler)
822 goto exit;
823
824 pydict_set_item_string_decref(dict, "ev_name", PyString_FromString(perf_evsel__name(evsel)));
825 pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
826 (const char *)&evsel->attr, sizeof(evsel->attr)));
827
828 pydict_set_item_string_decref(dict_sample, "pid",
829 PyInt_FromLong(sample->pid));
830 pydict_set_item_string_decref(dict_sample, "tid",
831 PyInt_FromLong(sample->tid));
832 pydict_set_item_string_decref(dict_sample, "cpu",
833 PyInt_FromLong(sample->cpu));
834 pydict_set_item_string_decref(dict_sample, "ip",
835 PyLong_FromUnsignedLongLong(sample->ip));
836 pydict_set_item_string_decref(dict_sample, "time",
837 PyLong_FromUnsignedLongLong(sample->time));
838 pydict_set_item_string_decref(dict_sample, "period",
839 PyLong_FromUnsignedLongLong(sample->period));
840 pydict_set_item_string_decref(dict, "sample", dict_sample);
841
842 pydict_set_item_string_decref(dict, "raw_buf", PyString_FromStringAndSize(
843 (const char *)sample->raw_data, sample->raw_size));
844 pydict_set_item_string_decref(dict, "comm",
845 PyString_FromString(thread__comm_str(al->thread)));
846 if (al->map) {
847 pydict_set_item_string_decref(dict, "dso",
848 PyString_FromString(al->map->dso->name));
849 }
850 if (al->sym) {
851 pydict_set_item_string_decref(dict, "symbol",
852 PyString_FromString(al->sym->name));
853 }
854
855 /* ip unwinding */ 963 /* ip unwinding */
856 callchain = python_process_callchain(sample, evsel, al); 964 callchain = python_process_callchain(sample, evsel, al);
857 pydict_set_item_string_decref(dict, "callchain", callchain); 965 dict = get_perf_sample_dict(sample, evsel, al, callchain);
858 966
859 PyTuple_SetItem(t, n++, dict); 967 PyTuple_SetItem(t, n++, dict);
860 if (_PyTuple_Resize(&t, n) == -1) 968 if (_PyTuple_Resize(&t, n) == -1)
861 Py_FatalError("error resizing Python tuple"); 969 Py_FatalError("error resizing Python tuple");
862 970
863 call_object(handler, t, handler_name); 971 call_object(handler, t, handler_name);
864exit: 972
865 Py_DECREF(dict); 973 Py_DECREF(dict);
866 Py_DECREF(t); 974 Py_DECREF(t);
867} 975}
@@ -1259,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1259 1367
1260 fprintf(ofp, "%s", f->name); 1368 fprintf(ofp, "%s", f->name);
1261 } 1369 }
1370 if (not_first++)
1371 fprintf(ofp, ", ");
1372 if (++count % 5 == 0)
1373 fprintf(ofp, "\n\t\t");
1374 fprintf(ofp, "perf_sample_dict");
1375
1262 fprintf(ofp, "):\n"); 1376 fprintf(ofp, "):\n");
1263 1377
1264 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, " 1378 fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1328,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1328 1442
1329 fprintf(ofp, ")\n\n"); 1443 fprintf(ofp, ")\n\n");
1330 1444
1445 fprintf(ofp, "\t\tprint 'Sample: {'+"
1446 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1447
1331 fprintf(ofp, "\t\tfor node in common_callchain:"); 1448 fprintf(ofp, "\t\tfor node in common_callchain:");
1332 fprintf(ofp, "\n\t\t\tif 'sym' in node:"); 1449 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
1333 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])"); 1450 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
@@ -1338,15 +1455,20 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
1338 } 1455 }
1339 1456
1340 fprintf(ofp, "def trace_unhandled(event_name, context, " 1457 fprintf(ofp, "def trace_unhandled(event_name, context, "
1341 "event_fields_dict):\n"); 1458 "event_fields_dict, perf_sample_dict):\n");
1342 1459
1343 fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))" 1460 fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
1344 "for k,v in sorted(event_fields_dict.items())])\n\n"); 1461 fprintf(ofp, "\t\tprint 'Sample: {'+"
1462 "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
1345 1463
1346 fprintf(ofp, "def print_header(" 1464 fprintf(ofp, "def print_header("
1347 "event_name, cpu, secs, nsecs, pid, comm):\n" 1465 "event_name, cpu, secs, nsecs, pid, comm):\n"
1348 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t" 1466 "\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
1349 "(event_name, cpu, secs, nsecs, pid, comm),\n"); 1467 "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
1468
1469 fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
1470 "\treturn delimiter.join"
1471 "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
1350 1472
1351 fclose(ofp); 1473 fclose(ofp);
1352 1474