Skip to content

Commit 48a1f56

Browse files
Jin Yaoacmel
authored andcommitted
perf script python: Add more PMU fields to event handler dict
When doing pmu sampling and then running a script with perf script -s script.py, the process_event function gets dictionary with some fields from the perf ring buffer (like ip, sym, callchain etc). But we miss quite a few fields we report now, for example, LBRs, data source, weight, transaction, iregs, uregs, etc. This patch reports these fields for perf script python processing. New keys/items: --------------- key : brstack items: from, to, from_dsoname, to_dsoname, mispred, predicted, in_tx, abort, cycles. key : brstacksym items: from, to, pred, in_tx, abort (converted string) key : datasrc key : datasrc_decode (decoded string) key : iregs key : uregs key : weight key : transaction v2: --- Add new fields for dso. Use PyBool_FromLong() for mispred/predicted/in_tx/abort Committer notes: !sym->name isn't valid, as its not a pointer, its a [0] array, use !sym->name[0] instead, guaranteed to be the case by symbol__new. This was caught by just one of the containers: 52 54.22 ubuntu:17.04 : FAIL gcc (Ubuntu 6.3.0-12ubuntu2) 6.3.0 20170406 CC /tmp/build/perf/util/scripting-engines/trace-event-python.o util/scripting-engines/trace-event-python.c:534:20: error: address of array 'sym->name' will always evaluate to 'true' [-Werror,-Wpointer-bool-conversion] if (!sym || !sym->name) ~~~~~~^~~~ 1 error generated. mv: cannot stat '/tmp/build/perf/util/scripting-engines/.trace-event-python.o.tmp': No such file or directory /git/linux/tools/build/Makefile.build:96: recipe for target '/tmp/build/perf/util/scripting-engines/trace-event-python.o' failed make[5]: *** [/tmp/build/perf/util/scripting-engines/trace-event-python.o] Error 1 Signed-off-by: Jin Yao <[email protected]> Reviewed-by: Andi Kleen <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Jin Yao <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Peter Zijlstra <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 5f9e0f3 commit 48a1f56

File tree

1 file changed

+226
-1
lines changed

1 file changed

+226
-1
lines changed

tools/perf/util/scripting-engines/trace-event-python.c

Lines changed: 226 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "cpumap.h"
4949
#include "print_binary.h"
5050
#include "stat.h"
51+
#include "mem-events.h"
5152

5253
#if PY_MAJOR_VERSION < 3
5354
#define _PyUnicode_FromString(arg) \
@@ -455,6 +456,166 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
455456
return pylist;
456457
}
457458

459+
static PyObject *python_process_brstack(struct perf_sample *sample,
460+
struct thread *thread)
461+
{
462+
struct branch_stack *br = sample->branch_stack;
463+
PyObject *pylist;
464+
u64 i;
465+
466+
pylist = PyList_New(0);
467+
if (!pylist)
468+
Py_FatalError("couldn't create Python list");
469+
470+
if (!(br && br->nr))
471+
goto exit;
472+
473+
for (i = 0; i < br->nr; i++) {
474+
PyObject *pyelem;
475+
struct addr_location al;
476+
const char *dsoname;
477+
478+
pyelem = PyDict_New();
479+
if (!pyelem)
480+
Py_FatalError("couldn't create Python dictionary");
481+
482+
pydict_set_item_string_decref(pyelem, "from",
483+
PyLong_FromUnsignedLongLong(br->entries[i].from));
484+
pydict_set_item_string_decref(pyelem, "to",
485+
PyLong_FromUnsignedLongLong(br->entries[i].to));
486+
pydict_set_item_string_decref(pyelem, "mispred",
487+
PyBool_FromLong(br->entries[i].flags.mispred));
488+
pydict_set_item_string_decref(pyelem, "predicted",
489+
PyBool_FromLong(br->entries[i].flags.predicted));
490+
pydict_set_item_string_decref(pyelem, "in_tx",
491+
PyBool_FromLong(br->entries[i].flags.in_tx));
492+
pydict_set_item_string_decref(pyelem, "abort",
493+
PyBool_FromLong(br->entries[i].flags.abort));
494+
pydict_set_item_string_decref(pyelem, "cycles",
495+
PyLong_FromUnsignedLongLong(br->entries[i].flags.cycles));
496+
497+
thread__find_map(thread, sample->cpumode,
498+
br->entries[i].from, &al);
499+
dsoname = get_dsoname(al.map);
500+
pydict_set_item_string_decref(pyelem, "from_dsoname",
501+
_PyUnicode_FromString(dsoname));
502+
503+
thread__find_map(thread, sample->cpumode,
504+
br->entries[i].to, &al);
505+
dsoname = get_dsoname(al.map);
506+
pydict_set_item_string_decref(pyelem, "to_dsoname",
507+
_PyUnicode_FromString(dsoname));
508+
509+
PyList_Append(pylist, pyelem);
510+
Py_DECREF(pyelem);
511+
}
512+
513+
exit:
514+
return pylist;
515+
}
516+
517+
static unsigned long get_offset(struct symbol *sym, struct addr_location *al)
518+
{
519+
unsigned long offset;
520+
521+
if (al->addr < sym->end)
522+
offset = al->addr - sym->start;
523+
else
524+
offset = al->addr - al->map->start - sym->start;
525+
526+
return offset;
527+
}
528+
529+
static int get_symoff(struct symbol *sym, struct addr_location *al,
530+
bool print_off, char *bf, int size)
531+
{
532+
unsigned long offset;
533+
534+
if (!sym || !sym->name[0])
535+
return scnprintf(bf, size, "%s", "[unknown]");
536+
537+
if (!print_off)
538+
return scnprintf(bf, size, "%s", sym->name);
539+
540+
offset = get_offset(sym, al);
541+
542+
return scnprintf(bf, size, "%s+0x%x", sym->name, offset);
543+
}
544+
545+
static int get_br_mspred(struct branch_flags *flags, char *bf, int size)
546+
{
547+
if (!flags->mispred && !flags->predicted)
548+
return scnprintf(bf, size, "%s", "-");
549+
550+
if (flags->mispred)
551+
return scnprintf(bf, size, "%s", "M");
552+
553+
return scnprintf(bf, size, "%s", "P");
554+
}
555+
556+
static PyObject *python_process_brstacksym(struct perf_sample *sample,
557+
struct thread *thread)
558+
{
559+
struct branch_stack *br = sample->branch_stack;
560+
PyObject *pylist;
561+
u64 i;
562+
char bf[512];
563+
struct addr_location al;
564+
565+
pylist = PyList_New(0);
566+
if (!pylist)
567+
Py_FatalError("couldn't create Python list");
568+
569+
if (!(br && br->nr))
570+
goto exit;
571+
572+
for (i = 0; i < br->nr; i++) {
573+
PyObject *pyelem;
574+
575+
pyelem = PyDict_New();
576+
if (!pyelem)
577+
Py_FatalError("couldn't create Python dictionary");
578+
579+
thread__find_symbol(thread, sample->cpumode,
580+
br->entries[i].from, &al);
581+
get_symoff(al.sym, &al, true, bf, sizeof(bf));
582+
pydict_set_item_string_decref(pyelem, "from",
583+
_PyUnicode_FromString(bf));
584+
585+
thread__find_symbol(thread, sample->cpumode,
586+
br->entries[i].to, &al);
587+
get_symoff(al.sym, &al, true, bf, sizeof(bf));
588+
pydict_set_item_string_decref(pyelem, "to",
589+
_PyUnicode_FromString(bf));
590+
591+
get_br_mspred(&br->entries[i].flags, bf, sizeof(bf));
592+
pydict_set_item_string_decref(pyelem, "pred",
593+
_PyUnicode_FromString(bf));
594+
595+
if (br->entries[i].flags.in_tx) {
596+
pydict_set_item_string_decref(pyelem, "in_tx",
597+
_PyUnicode_FromString("X"));
598+
} else {
599+
pydict_set_item_string_decref(pyelem, "in_tx",
600+
_PyUnicode_FromString("-"));
601+
}
602+
603+
if (br->entries[i].flags.abort) {
604+
pydict_set_item_string_decref(pyelem, "abort",
605+
_PyUnicode_FromString("A"));
606+
} else {
607+
pydict_set_item_string_decref(pyelem, "abort",
608+
_PyUnicode_FromString("-"));
609+
}
610+
611+
PyList_Append(pylist, pyelem);
612+
Py_DECREF(pyelem);
613+
}
614+
615+
exit:
616+
return pylist;
617+
}
618+
458619
static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
459620
{
460621
PyObject *t;
@@ -505,12 +666,63 @@ static void set_sample_read_in_dict(PyObject *dict_sample,
505666
pydict_set_item_string_decref(dict_sample, "values", values);
506667
}
507668

669+
static void set_sample_datasrc_in_dict(PyObject *dict,
670+
struct perf_sample *sample)
671+
{
672+
struct mem_info mi = { .data_src.val = sample->data_src };
673+
char decode[100];
674+
675+
pydict_set_item_string_decref(dict, "datasrc",
676+
PyLong_FromUnsignedLongLong(sample->data_src));
677+
678+
perf_script__meminfo_scnprintf(decode, 100, &mi);
679+
680+
pydict_set_item_string_decref(dict, "datasrc_decode",
681+
_PyUnicode_FromString(decode));
682+
}
683+
684+
static int regs_map(struct regs_dump *regs, uint64_t mask, char *bf, int size)
685+
{
686+
unsigned int i = 0, r;
687+
int printed = 0;
688+
689+
bf[0] = 0;
690+
691+
for_each_set_bit(r, (unsigned long *) &mask, sizeof(mask) * 8) {
692+
u64 val = regs->regs[i++];
693+
694+
printed += scnprintf(bf + printed, size - printed,
695+
"%5s:0x%" PRIx64 " ",
696+
perf_reg_name(r), val);
697+
}
698+
699+
return printed;
700+
}
701+
702+
static void set_regs_in_dict(PyObject *dict,
703+
struct perf_sample *sample,
704+
struct perf_evsel *evsel)
705+
{
706+
struct perf_event_attr *attr = &evsel->attr;
707+
char bf[512];
708+
709+
regs_map(&sample->intr_regs, attr->sample_regs_intr, bf, sizeof(bf));
710+
711+
pydict_set_item_string_decref(dict, "iregs",
712+
_PyUnicode_FromString(bf));
713+
714+
regs_map(&sample->user_regs, attr->sample_regs_user, bf, sizeof(bf));
715+
716+
pydict_set_item_string_decref(dict, "uregs",
717+
_PyUnicode_FromString(bf));
718+
}
719+
508720
static PyObject *get_perf_sample_dict(struct perf_sample *sample,
509721
struct perf_evsel *evsel,
510722
struct addr_location *al,
511723
PyObject *callchain)
512724
{
513-
PyObject *dict, *dict_sample;
725+
PyObject *dict, *dict_sample, *brstack, *brstacksym;
514726

515727
dict = PyDict_New();
516728
if (!dict)
@@ -541,6 +753,11 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
541753
pydict_set_item_string_decref(dict_sample, "addr",
542754
PyLong_FromUnsignedLongLong(sample->addr));
543755
set_sample_read_in_dict(dict_sample, sample, evsel);
756+
pydict_set_item_string_decref(dict_sample, "weight",
757+
PyLong_FromUnsignedLongLong(sample->weight));
758+
pydict_set_item_string_decref(dict_sample, "transaction",
759+
PyLong_FromUnsignedLongLong(sample->transaction));
760+
set_sample_datasrc_in_dict(dict_sample, sample);
544761
pydict_set_item_string_decref(dict, "sample", dict_sample);
545762

546763
pydict_set_item_string_decref(dict, "raw_buf", _PyBytes_FromStringAndSize(
@@ -558,6 +775,14 @@ static PyObject *get_perf_sample_dict(struct perf_sample *sample,
558775

559776
pydict_set_item_string_decref(dict, "callchain", callchain);
560777

778+
brstack = python_process_brstack(sample, al->thread);
779+
pydict_set_item_string_decref(dict, "brstack", brstack);
780+
781+
brstacksym = python_process_brstacksym(sample, al->thread);
782+
pydict_set_item_string_decref(dict, "brstacksym", brstacksym);
783+
784+
set_regs_in_dict(dict, sample, evsel);
785+
561786
return dict;
562787
}
563788

0 commit comments

Comments
 (0)