11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
27e4b21b8STom Zanussi /*
3133dc4c3SIngo Molnar * Context.c. Python interfaces for perf script.
47e4b21b8STom Zanussi *
57e4b21b8STom Zanussi * Copyright (C) 2010 Tom Zanussi <[email protected]>
67e4b21b8STom Zanussi */
77e4b21b8STom Zanussi
8e79457a5SAdrian Hunter /*
9e79457a5SAdrian Hunter * Use Py_ssize_t for '#' formats to avoid DeprecationWarning: PY_SSIZE_T_CLEAN
10e79457a5SAdrian Hunter * will be required for '#' formats.
11e79457a5SAdrian Hunter */
12e79457a5SAdrian Hunter #define PY_SSIZE_T_CLEAN
13e79457a5SAdrian Hunter
147e4b21b8STom Zanussi #include <Python.h>
159943581cSJames Clark #include "../../../util/config.h"
167e4b21b8STom Zanussi #include "../../../util/trace-event.h"
1713c71b92SAdrian Hunter #include "../../../util/event.h"
1813c71b92SAdrian Hunter #include "../../../util/symbol.h"
1913c71b92SAdrian Hunter #include "../../../util/thread.h"
20e79457a5SAdrian Hunter #include "../../../util/map.h"
2113c71b92SAdrian Hunter #include "../../../util/maps.h"
227d00540dSAdrian Hunter #include "../../../util/auxtrace.h"
237d00540dSAdrian Hunter #include "../../../util/session.h"
24e79457a5SAdrian Hunter #include "../../../util/srcline.h"
25e79457a5SAdrian Hunter #include "../../../util/srccode.h"
267e4b21b8STom Zanussi
2766dfdff0SJaroslav Škarvada #define _PyCapsule_GetPointer(arg1, arg2) \
2866dfdff0SJaroslav Škarvada PyCapsule_GetPointer((arg1), (arg2))
2913c71b92SAdrian Hunter #define _PyBytes_FromStringAndSize(arg1, arg2) \
3013c71b92SAdrian Hunter PyBytes_FromStringAndSize((arg1), (arg2))
317d00540dSAdrian Hunter #define _PyUnicode_AsUTF8(arg) \
327d00540dSAdrian Hunter PyUnicode_AsUTF8(arg)
3366dfdff0SJaroslav Škarvada
3466dfdff0SJaroslav Škarvada PyMODINIT_FUNC PyInit_perf_trace_context(void);
357e4b21b8STom Zanussi
get_args(PyObject * args,const char * name,PyObject ** arg2)367d00540dSAdrian Hunter static struct scripting_context *get_args(PyObject *args, const char *name, PyObject **arg2)
377e4b21b8STom Zanussi {
387d00540dSAdrian Hunter int cnt = 1 + !!arg2;
397e4b21b8STom Zanussi PyObject *context;
407e4b21b8STom Zanussi
417d00540dSAdrian Hunter if (!PyArg_UnpackTuple(args, name, 1, cnt, &context, arg2))
427e4b21b8STom Zanussi return NULL;
437e4b21b8STom Zanussi
446337bd0cSAdrian Hunter return _PyCapsule_GetPointer(context, NULL);
456337bd0cSAdrian Hunter }
467e4b21b8STom Zanussi
get_scripting_context(PyObject * args)477d00540dSAdrian Hunter static struct scripting_context *get_scripting_context(PyObject *args)
487d00540dSAdrian Hunter {
497d00540dSAdrian Hunter return get_args(args, "context", NULL);
507d00540dSAdrian Hunter }
517d00540dSAdrian Hunter
5280c3a7d9SAdrian Hunter #ifdef HAVE_LIBTRACEEVENT
perf_trace_context_common_pc(PyObject * obj,PyObject * args)536337bd0cSAdrian Hunter static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
546337bd0cSAdrian Hunter {
556337bd0cSAdrian Hunter struct scripting_context *c = get_scripting_context(args);
566337bd0cSAdrian Hunter
576337bd0cSAdrian Hunter if (!c)
586337bd0cSAdrian Hunter return NULL;
596337bd0cSAdrian Hunter
606337bd0cSAdrian Hunter return Py_BuildValue("i", common_pc(c));
617e4b21b8STom Zanussi }
627e4b21b8STom Zanussi
perf_trace_context_common_flags(PyObject * obj,PyObject * args)63316c7136SArnaldo Carvalho de Melo static PyObject *perf_trace_context_common_flags(PyObject *obj,
647e4b21b8STom Zanussi PyObject *args)
657e4b21b8STom Zanussi {
666337bd0cSAdrian Hunter struct scripting_context *c = get_scripting_context(args);
677e4b21b8STom Zanussi
686337bd0cSAdrian Hunter if (!c)
697e4b21b8STom Zanussi return NULL;
707e4b21b8STom Zanussi
716337bd0cSAdrian Hunter return Py_BuildValue("i", common_flags(c));
727e4b21b8STom Zanussi }
737e4b21b8STom Zanussi
perf_trace_context_common_lock_depth(PyObject * obj,PyObject * args)74316c7136SArnaldo Carvalho de Melo static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
757e4b21b8STom Zanussi PyObject *args)
767e4b21b8STom Zanussi {
776337bd0cSAdrian Hunter struct scripting_context *c = get_scripting_context(args);
787e4b21b8STom Zanussi
796337bd0cSAdrian Hunter if (!c)
807e4b21b8STom Zanussi return NULL;
817e4b21b8STom Zanussi
826337bd0cSAdrian Hunter return Py_BuildValue("i", common_lock_depth(c));
837e4b21b8STom Zanussi }
8480c3a7d9SAdrian Hunter #endif
857e4b21b8STom Zanussi
perf_sample_insn(PyObject * obj,PyObject * args)8613c71b92SAdrian Hunter static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
8713c71b92SAdrian Hunter {
8813c71b92SAdrian Hunter struct scripting_context *c = get_scripting_context(args);
8913c71b92SAdrian Hunter
9013c71b92SAdrian Hunter if (!c)
9113c71b92SAdrian Hunter return NULL;
9213c71b92SAdrian Hunter
93ee84a303SIan Rogers if (c->sample->ip && !c->sample->insn_len && thread__maps(c->al->thread)) {
94ee84a303SIan Rogers struct machine *machine = maps__machine(thread__maps(c->al->thread));
9513c71b92SAdrian Hunter
96*1ff2ca39SIan Rogers script_fetch_insn(c->sample, c->al->thread, machine, /*native_arch=*/true);
975ab6d715SIan Rogers }
9813c71b92SAdrian Hunter if (!c->sample->insn_len)
9913c71b92SAdrian Hunter Py_RETURN_NONE; /* N.B. This is a return statement */
10013c71b92SAdrian Hunter
10113c71b92SAdrian Hunter return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len);
10213c71b92SAdrian Hunter }
10313c71b92SAdrian Hunter
perf_set_itrace_options(PyObject * obj,PyObject * args)1047d00540dSAdrian Hunter static PyObject *perf_set_itrace_options(PyObject *obj, PyObject *args)
1057d00540dSAdrian Hunter {
1067d00540dSAdrian Hunter struct scripting_context *c;
1077d00540dSAdrian Hunter const char *itrace_options;
1087d00540dSAdrian Hunter int retval = -1;
1097d00540dSAdrian Hunter PyObject *str;
1107d00540dSAdrian Hunter
1117d00540dSAdrian Hunter c = get_args(args, "itrace_options", &str);
1127d00540dSAdrian Hunter if (!c)
1137d00540dSAdrian Hunter return NULL;
1147d00540dSAdrian Hunter
1157d00540dSAdrian Hunter if (!c->session || !c->session->itrace_synth_opts)
1167d00540dSAdrian Hunter goto out;
1177d00540dSAdrian Hunter
1187d00540dSAdrian Hunter if (c->session->itrace_synth_opts->set) {
1197d00540dSAdrian Hunter retval = 1;
1207d00540dSAdrian Hunter goto out;
1217d00540dSAdrian Hunter }
1227d00540dSAdrian Hunter
1237d00540dSAdrian Hunter itrace_options = _PyUnicode_AsUTF8(str);
1247d00540dSAdrian Hunter
1257d00540dSAdrian Hunter retval = itrace_do_parse_synth_opts(c->session->itrace_synth_opts, itrace_options, 0);
1267d00540dSAdrian Hunter out:
1277d00540dSAdrian Hunter return Py_BuildValue("i", retval);
1287d00540dSAdrian Hunter }
1297d00540dSAdrian Hunter
perf_sample_src(PyObject * obj,PyObject * args,bool get_srccode)130e79457a5SAdrian Hunter static PyObject *perf_sample_src(PyObject *obj, PyObject *args, bool get_srccode)
131e79457a5SAdrian Hunter {
132e79457a5SAdrian Hunter struct scripting_context *c = get_scripting_context(args);
133e79457a5SAdrian Hunter unsigned int line = 0;
134e79457a5SAdrian Hunter char *srcfile = NULL;
135e79457a5SAdrian Hunter char *srccode = NULL;
136e79457a5SAdrian Hunter PyObject *result;
137e79457a5SAdrian Hunter struct map *map;
13863df0e4bSIan Rogers struct dso *dso;
139e79457a5SAdrian Hunter int len = 0;
140e79457a5SAdrian Hunter u64 addr;
141e79457a5SAdrian Hunter
142e79457a5SAdrian Hunter if (!c)
143e79457a5SAdrian Hunter return NULL;
144e79457a5SAdrian Hunter
145e79457a5SAdrian Hunter map = c->al->map;
146e79457a5SAdrian Hunter addr = c->al->addr;
14763df0e4bSIan Rogers dso = map ? map__dso(map) : NULL;
148e79457a5SAdrian Hunter
14963df0e4bSIan Rogers if (dso)
15063df0e4bSIan Rogers srcfile = get_srcline_split(dso, map__rip_2objdump(map, addr), &line);
151e79457a5SAdrian Hunter
152e79457a5SAdrian Hunter if (get_srccode) {
153e79457a5SAdrian Hunter if (srcfile)
154e79457a5SAdrian Hunter srccode = find_sourceline(srcfile, line, &len);
155e79457a5SAdrian Hunter result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len);
156e79457a5SAdrian Hunter } else {
157e79457a5SAdrian Hunter result = Py_BuildValue("(sI)", srcfile, line);
158e79457a5SAdrian Hunter }
159e79457a5SAdrian Hunter
160e79457a5SAdrian Hunter free(srcfile);
161e79457a5SAdrian Hunter
162e79457a5SAdrian Hunter return result;
163e79457a5SAdrian Hunter }
164e79457a5SAdrian Hunter
perf_sample_srcline(PyObject * obj,PyObject * args)165e79457a5SAdrian Hunter static PyObject *perf_sample_srcline(PyObject *obj, PyObject *args)
166e79457a5SAdrian Hunter {
167e79457a5SAdrian Hunter return perf_sample_src(obj, args, false);
168e79457a5SAdrian Hunter }
169e79457a5SAdrian Hunter
perf_sample_srccode(PyObject * obj,PyObject * args)170e79457a5SAdrian Hunter static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args)
171e79457a5SAdrian Hunter {
172e79457a5SAdrian Hunter return perf_sample_src(obj, args, true);
173e79457a5SAdrian Hunter }
174e79457a5SAdrian Hunter
__perf_config_get(PyObject * obj,PyObject * args)1759943581cSJames Clark static PyObject *__perf_config_get(PyObject *obj, PyObject *args)
1769943581cSJames Clark {
1779943581cSJames Clark const char *config_name;
1789943581cSJames Clark
1799943581cSJames Clark if (!PyArg_ParseTuple(args, "s", &config_name))
1809943581cSJames Clark return NULL;
1819943581cSJames Clark return Py_BuildValue("s", perf_config_get(config_name));
1829943581cSJames Clark }
1839943581cSJames Clark
1847e4b21b8STom Zanussi static PyMethodDef ContextMethods[] = {
18580c3a7d9SAdrian Hunter #ifdef HAVE_LIBTRACEEVENT
1867e4b21b8STom Zanussi { "common_pc", perf_trace_context_common_pc, METH_VARARGS,
1877e4b21b8STom Zanussi "Get the common preempt count event field value."},
1887e4b21b8STom Zanussi { "common_flags", perf_trace_context_common_flags, METH_VARARGS,
1897e4b21b8STom Zanussi "Get the common flags event field value."},
1907e4b21b8STom Zanussi { "common_lock_depth", perf_trace_context_common_lock_depth,
1917e4b21b8STom Zanussi METH_VARARGS, "Get the common lock depth event field value."},
19280c3a7d9SAdrian Hunter #endif
19313c71b92SAdrian Hunter { "perf_sample_insn", perf_sample_insn,
19413c71b92SAdrian Hunter METH_VARARGS, "Get the machine code instruction."},
1957d00540dSAdrian Hunter { "perf_set_itrace_options", perf_set_itrace_options,
1967d00540dSAdrian Hunter METH_VARARGS, "Set --itrace options."},
197e79457a5SAdrian Hunter { "perf_sample_srcline", perf_sample_srcline,
198e79457a5SAdrian Hunter METH_VARARGS, "Get source file name and line number."},
199e79457a5SAdrian Hunter { "perf_sample_srccode", perf_sample_srccode,
200e79457a5SAdrian Hunter METH_VARARGS, "Get source file name, line number and line."},
2019943581cSJames Clark { "perf_config_get", __perf_config_get, METH_VARARGS, "Get perf config entry"},
2027e4b21b8STom Zanussi { NULL, NULL, 0, NULL}
2037e4b21b8STom Zanussi };
2047e4b21b8STom Zanussi
PyInit_perf_trace_context(void)20566dfdff0SJaroslav Škarvada PyMODINIT_FUNC PyInit_perf_trace_context(void)
20666dfdff0SJaroslav Škarvada {
20766dfdff0SJaroslav Škarvada static struct PyModuleDef moduledef = {
20866dfdff0SJaroslav Škarvada PyModuleDef_HEAD_INIT,
20966dfdff0SJaroslav Škarvada "perf_trace_context", /* m_name */
21066dfdff0SJaroslav Škarvada "", /* m_doc */
21166dfdff0SJaroslav Škarvada -1, /* m_size */
21266dfdff0SJaroslav Škarvada ContextMethods, /* m_methods */
21366dfdff0SJaroslav Škarvada NULL, /* m_reload */
21466dfdff0SJaroslav Škarvada NULL, /* m_traverse */
21566dfdff0SJaroslav Škarvada NULL, /* m_clear */
21666dfdff0SJaroslav Škarvada NULL, /* m_free */
21766dfdff0SJaroslav Škarvada };
218cf9bfa6cSAdrian Hunter PyObject *mod;
219cf9bfa6cSAdrian Hunter
220cf9bfa6cSAdrian Hunter mod = PyModule_Create(&moduledef);
221cf9bfa6cSAdrian Hunter /* Add perf_script_context to the module so it can be imported */
222cf9bfa6cSAdrian Hunter PyObject_SetAttrString(mod, "perf_script_context", Py_None);
223cf9bfa6cSAdrian Hunter
224cf9bfa6cSAdrian Hunter return mod;
22566dfdff0SJaroslav Škarvada }
226