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.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a45784c910..938b39f6ad31 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;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
499{ 527{
500 struct event_format *event = evsel->tp_format; 528 struct event_format *event = evsel->tp_format;
501 PyObject *handler, *context, *t, *obj = NULL, *callchain; 529 PyObject *handler, *context, *t, *obj = NULL, *callchain;
502 PyObject *dict = NULL; 530 PyObject *dict = NULL, *all_entries_dict = NULL;
503 static char handler_name[256]; 531 static char handler_name[256];
504 struct format_field *field; 532 struct format_field *field;
505 unsigned long s, ns; 533 unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
552 580
553 /* ip unwinding */ 581 /* ip unwinding */
554 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);
555 585
556 if (!dict) { 586 if (!dict) {
557 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 587 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample *sample,
602 if (dict) 632 if (dict)
603 PyTuple_SetItem(t, n++, dict); 633 PyTuple_SetItem(t, n++, dict);
604 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
605 if (_PyTuple_Resize(&t, n) == -1) 643 if (_PyTuple_Resize(&t, n) == -1)
606 Py_FatalError("error resizing Python tuple"); 644 Py_FatalError("error resizing Python tuple");
607 645
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
612 Py_DECREF(dict); 650 Py_DECREF(dict);
613 } 651 }
614 652
653 Py_XDECREF(all_entries_dict);
615 Py_DECREF(t); 654 Py_DECREF(t);
616} 655}
617 656