aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@kernel.org>2016-07-10 07:08:00 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-07-12 15:19:16 -0400
commitbae57e3825a3dded15f61cd20c6757d60ad6c712 (patch)
tree398fd3897e531743e28d0f90a22203066864b2bd /tools/perf
parent377f698db12150a1cf79987dca1d3990fa14a1f8 (diff)
perf python: Add support to resolve tracepoint fields
Adding tp_getattro callback for sample event. It resolves tracepoint fields in runtime. It's now possible to access tracepoint fields in normal fashion like hardcoded ones (see the example in the next patch). Reported-and-Tested-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: Jiri Olsa <jolsa@kernel.org> Cc: David Ahern <dsahern@gmail.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/1468148882-10362-9-git-send-email-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/python.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index dc7adaa3a02c..d32f97033718 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -290,6 +290,97 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
290 return ret; 290 return ret;
291} 291}
292 292
293static bool is_tracepoint(struct pyrf_event *pevent)
294{
295 return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT;
296}
297
298static int is_printable_array(char *p, unsigned int len)
299{
300 unsigned int i;
301
302 for (i = 0; i < len; i++) {
303 if (!isprint(p[i]) && !isspace(p[i]))
304 return 0;
305 }
306
307 return 1;
308}
309
310static PyObject*
311tracepoint_field(struct pyrf_event *pe, struct format_field *field)
312{
313 struct pevent *pevent = field->event->pevent;
314 void *data = pe->sample.raw_data;
315 PyObject *ret = NULL;
316 unsigned long long val;
317 unsigned int offset, len;
318
319 if (field->flags & FIELD_IS_ARRAY) {
320 offset = field->offset;
321 len = field->size;
322 if (field->flags & FIELD_IS_DYNAMIC) {
323 val = pevent_read_number(pevent, data + offset, len);
324 offset = val;
325 len = offset >> 16;
326 offset &= 0xffff;
327 }
328 if (field->flags & FIELD_IS_STRING &&
329 is_printable_array(data + offset, len)) {
330 ret = PyString_FromString((char *)data + offset);
331 } else {
332 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
333 field->flags &= ~FIELD_IS_STRING;
334 }
335 } else {
336 val = pevent_read_number(pevent, data + field->offset,
337 field->size);
338 if (field->flags & FIELD_IS_POINTER)
339 ret = PyLong_FromUnsignedLong((unsigned long) val);
340 else if (field->flags & FIELD_IS_SIGNED)
341 ret = PyLong_FromLong((long) val);
342 else
343 ret = PyLong_FromUnsignedLong((unsigned long) val);
344 }
345
346 return ret;
347}
348
349static PyObject*
350get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
351{
352 const char *str = PyString_AsString(PyObject_Str(attr_name));
353 struct perf_evsel *evsel = pevent->evsel;
354 struct format_field *field;
355
356 if (!evsel->tp_format) {
357 struct event_format *tp_format;
358
359 tp_format = trace_event__tp_format_id(evsel->attr.config);
360 if (!tp_format)
361 return NULL;
362
363 evsel->tp_format = tp_format;
364 }
365
366 field = pevent_find_any_field(evsel->tp_format, str);
367 if (!field)
368 return NULL;
369
370 return tracepoint_field(pevent, field);
371}
372
373static PyObject*
374pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
375{
376 PyObject *obj = NULL;
377
378 if (is_tracepoint(pevent))
379 obj = get_tracepoint_field(pevent, attr_name);
380
381 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
382}
383
293static PyTypeObject pyrf_sample_event__type = { 384static PyTypeObject pyrf_sample_event__type = {
294 PyVarObject_HEAD_INIT(NULL, 0) 385 PyVarObject_HEAD_INIT(NULL, 0)
295 .tp_name = "perf.sample_event", 386 .tp_name = "perf.sample_event",
@@ -298,6 +389,7 @@ static PyTypeObject pyrf_sample_event__type = {
298 .tp_doc = pyrf_sample_event__doc, 389 .tp_doc = pyrf_sample_event__doc,
299 .tp_members = pyrf_sample_event__members, 390 .tp_members = pyrf_sample_event__members,
300 .tp_repr = (reprfunc)pyrf_sample_event__repr, 391 .tp_repr = (reprfunc)pyrf_sample_event__repr,
392 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro,
301}; 393};
302 394
303static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); 395static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");