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