xref: /linux/tools/perf/scripts/python/Perf-Trace-Util/Context.c (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Context.c.  Python interfaces for perf script.
4  *
5  * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com>
6  */
7 
8 /*
9  * Use Py_ssize_t for '#' formats to avoid DeprecationWarning: PY_SSIZE_T_CLEAN
10  * will be required for '#' formats.
11  */
12 #define PY_SSIZE_T_CLEAN
13 
14 #include <Python.h>
15 #include "../../../util/config.h"
16 #include "../../../util/trace-event.h"
17 #include "../../../util/event.h"
18 #include "../../../util/symbol.h"
19 #include "../../../util/thread.h"
20 #include "../../../util/map.h"
21 #include "../../../util/maps.h"
22 #include "../../../util/auxtrace.h"
23 #include "../../../util/session.h"
24 #include "../../../util/srcline.h"
25 #include "../../../util/srccode.h"
26 
27 #if PY_MAJOR_VERSION < 3
28 #define _PyCapsule_GetPointer(arg1, arg2) \
29   PyCObject_AsVoidPtr(arg1)
30 #define _PyBytes_FromStringAndSize(arg1, arg2) \
31   PyString_FromStringAndSize((arg1), (arg2))
32 #define _PyUnicode_AsUTF8(arg) \
33   PyString_AsString(arg)
34 
35 PyMODINIT_FUNC initperf_trace_context(void);
36 #else
37 #define _PyCapsule_GetPointer(arg1, arg2) \
38   PyCapsule_GetPointer((arg1), (arg2))
39 #define _PyBytes_FromStringAndSize(arg1, arg2) \
40   PyBytes_FromStringAndSize((arg1), (arg2))
41 #define _PyUnicode_AsUTF8(arg) \
42   PyUnicode_AsUTF8(arg)
43 
44 PyMODINIT_FUNC PyInit_perf_trace_context(void);
45 #endif
46 
47 static struct scripting_context *get_args(PyObject *args, const char *name, PyObject **arg2)
48 {
49 	int cnt = 1 + !!arg2;
50 	PyObject *context;
51 
52 	if (!PyArg_UnpackTuple(args, name, 1, cnt, &context, arg2))
53 		return NULL;
54 
55 	return _PyCapsule_GetPointer(context, NULL);
56 }
57 
58 static struct scripting_context *get_scripting_context(PyObject *args)
59 {
60 	return get_args(args, "context", NULL);
61 }
62 
63 #ifdef HAVE_LIBTRACEEVENT
64 static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
65 {
66 	struct scripting_context *c = get_scripting_context(args);
67 
68 	if (!c)
69 		return NULL;
70 
71 	return Py_BuildValue("i", common_pc(c));
72 }
73 
74 static PyObject *perf_trace_context_common_flags(PyObject *obj,
75 						 PyObject *args)
76 {
77 	struct scripting_context *c = get_scripting_context(args);
78 
79 	if (!c)
80 		return NULL;
81 
82 	return Py_BuildValue("i", common_flags(c));
83 }
84 
85 static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
86 						      PyObject *args)
87 {
88 	struct scripting_context *c = get_scripting_context(args);
89 
90 	if (!c)
91 		return NULL;
92 
93 	return Py_BuildValue("i", common_lock_depth(c));
94 }
95 #endif
96 
97 static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
98 {
99 	struct scripting_context *c = get_scripting_context(args);
100 
101 	if (!c)
102 		return NULL;
103 
104 	if (c->sample->ip && !c->sample->insn_len && thread__maps(c->al->thread)) {
105 		struct machine *machine =  maps__machine(thread__maps(c->al->thread));
106 
107 		script_fetch_insn(c->sample, c->al->thread, machine);
108 	}
109 	if (!c->sample->insn_len)
110 		Py_RETURN_NONE; /* N.B. This is a return statement */
111 
112 	return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len);
113 }
114 
115 static PyObject *perf_set_itrace_options(PyObject *obj, PyObject *args)
116 {
117 	struct scripting_context *c;
118 	const char *itrace_options;
119 	int retval = -1;
120 	PyObject *str;
121 
122 	c = get_args(args, "itrace_options", &str);
123 	if (!c)
124 		return NULL;
125 
126 	if (!c->session || !c->session->itrace_synth_opts)
127 		goto out;
128 
129 	if (c->session->itrace_synth_opts->set) {
130 		retval = 1;
131 		goto out;
132 	}
133 
134 	itrace_options = _PyUnicode_AsUTF8(str);
135 
136 	retval = itrace_do_parse_synth_opts(c->session->itrace_synth_opts, itrace_options, 0);
137 out:
138 	return Py_BuildValue("i", retval);
139 }
140 
141 static PyObject *perf_sample_src(PyObject *obj, PyObject *args, bool get_srccode)
142 {
143 	struct scripting_context *c = get_scripting_context(args);
144 	unsigned int line = 0;
145 	char *srcfile = NULL;
146 	char *srccode = NULL;
147 	PyObject *result;
148 	struct map *map;
149 	struct dso *dso;
150 	int len = 0;
151 	u64 addr;
152 
153 	if (!c)
154 		return NULL;
155 
156 	map = c->al->map;
157 	addr = c->al->addr;
158 	dso = map ? map__dso(map) : NULL;
159 
160 	if (dso)
161 		srcfile = get_srcline_split(dso, map__rip_2objdump(map, addr), &line);
162 
163 	if (get_srccode) {
164 		if (srcfile)
165 			srccode = find_sourceline(srcfile, line, &len);
166 		result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len);
167 	} else {
168 		result = Py_BuildValue("(sI)", srcfile, line);
169 	}
170 
171 	free(srcfile);
172 
173 	return result;
174 }
175 
176 static PyObject *perf_sample_srcline(PyObject *obj, PyObject *args)
177 {
178 	return perf_sample_src(obj, args, false);
179 }
180 
181 static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args)
182 {
183 	return perf_sample_src(obj, args, true);
184 }
185 
186 static PyObject *__perf_config_get(PyObject *obj, PyObject *args)
187 {
188 	const char *config_name;
189 
190 	if (!PyArg_ParseTuple(args, "s", &config_name))
191 		return NULL;
192 	return Py_BuildValue("s", perf_config_get(config_name));
193 }
194 
195 static PyMethodDef ContextMethods[] = {
196 #ifdef HAVE_LIBTRACEEVENT
197 	{ "common_pc", perf_trace_context_common_pc, METH_VARARGS,
198 	  "Get the common preempt count event field value."},
199 	{ "common_flags", perf_trace_context_common_flags, METH_VARARGS,
200 	  "Get the common flags event field value."},
201 	{ "common_lock_depth", perf_trace_context_common_lock_depth,
202 	  METH_VARARGS,	"Get the common lock depth event field value."},
203 #endif
204 	{ "perf_sample_insn", perf_sample_insn,
205 	  METH_VARARGS,	"Get the machine code instruction."},
206 	{ "perf_set_itrace_options", perf_set_itrace_options,
207 	  METH_VARARGS,	"Set --itrace options."},
208 	{ "perf_sample_srcline", perf_sample_srcline,
209 	  METH_VARARGS,	"Get source file name and line number."},
210 	{ "perf_sample_srccode", perf_sample_srccode,
211 	  METH_VARARGS,	"Get source file name, line number and line."},
212 	{ "perf_config_get", __perf_config_get, METH_VARARGS, "Get perf config entry"},
213 	{ NULL, NULL, 0, NULL}
214 };
215 
216 #if PY_MAJOR_VERSION < 3
217 PyMODINIT_FUNC initperf_trace_context(void)
218 {
219 	(void) Py_InitModule("perf_trace_context", ContextMethods);
220 }
221 #else
222 PyMODINIT_FUNC PyInit_perf_trace_context(void)
223 {
224 	static struct PyModuleDef moduledef = {
225 		PyModuleDef_HEAD_INIT,
226 		"perf_trace_context",	/* m_name */
227 		"",			/* m_doc */
228 		-1,			/* m_size */
229 		ContextMethods,		/* m_methods */
230 		NULL,			/* m_reload */
231 		NULL,			/* m_traverse */
232 		NULL,			/* m_clear */
233 		NULL,			/* m_free */
234 	};
235 	PyObject *mod;
236 
237 	mod = PyModule_Create(&moduledef);
238 	/* Add perf_script_context to the module so it can be imported */
239 	PyObject_SetAttrString(mod, "perf_script_context", Py_None);
240 
241 	return mod;
242 }
243 #endif
244