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 <[email protected]>
6  */
7 
8 #include <Python.h>
9 #include "../../../util/trace-event.h"
10 #include "../../../util/event.h"
11 #include "../../../util/symbol.h"
12 #include "../../../util/thread.h"
13 #include "../../../util/maps.h"
14 #include "../../../util/auxtrace.h"
15 #include "../../../util/session.h"
16 
17 #if PY_MAJOR_VERSION < 3
18 #define _PyCapsule_GetPointer(arg1, arg2) \
19   PyCObject_AsVoidPtr(arg1)
20 #define _PyBytes_FromStringAndSize(arg1, arg2) \
21   PyString_FromStringAndSize((arg1), (arg2))
22 #define _PyUnicode_AsUTF8(arg) \
23   PyString_AsString(arg)
24 
25 PyMODINIT_FUNC initperf_trace_context(void);
26 #else
27 #define _PyCapsule_GetPointer(arg1, arg2) \
28   PyCapsule_GetPointer((arg1), (arg2))
29 #define _PyBytes_FromStringAndSize(arg1, arg2) \
30   PyBytes_FromStringAndSize((arg1), (arg2))
31 #define _PyUnicode_AsUTF8(arg) \
32   PyUnicode_AsUTF8(arg)
33 
34 PyMODINIT_FUNC PyInit_perf_trace_context(void);
35 #endif
36 
37 static struct scripting_context *get_args(PyObject *args, const char *name, PyObject **arg2)
38 {
39 	int cnt = 1 + !!arg2;
40 	PyObject *context;
41 
42 	if (!PyArg_UnpackTuple(args, name, 1, cnt, &context, arg2))
43 		return NULL;
44 
45 	return _PyCapsule_GetPointer(context, NULL);
46 }
47 
48 static struct scripting_context *get_scripting_context(PyObject *args)
49 {
50 	return get_args(args, "context", NULL);
51 }
52 
53 static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
54 {
55 	struct scripting_context *c = get_scripting_context(args);
56 
57 	if (!c)
58 		return NULL;
59 
60 	return Py_BuildValue("i", common_pc(c));
61 }
62 
63 static PyObject *perf_trace_context_common_flags(PyObject *obj,
64 						 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_flags(c));
72 }
73 
74 static PyObject *perf_trace_context_common_lock_depth(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_lock_depth(c));
83 }
84 
85 static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
86 {
87 	struct scripting_context *c = get_scripting_context(args);
88 
89 	if (!c)
90 		return NULL;
91 
92 	if (c->sample->ip && !c->sample->insn_len &&
93 	    c->al->thread->maps && c->al->thread->maps->machine)
94 		script_fetch_insn(c->sample, c->al->thread, c->al->thread->maps->machine);
95 
96 	if (!c->sample->insn_len)
97 		Py_RETURN_NONE; /* N.B. This is a return statement */
98 
99 	return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len);
100 }
101 
102 static PyObject *perf_set_itrace_options(PyObject *obj, PyObject *args)
103 {
104 	struct scripting_context *c;
105 	const char *itrace_options;
106 	int retval = -1;
107 	PyObject *str;
108 
109 	c = get_args(args, "itrace_options", &str);
110 	if (!c)
111 		return NULL;
112 
113 	if (!c->session || !c->session->itrace_synth_opts)
114 		goto out;
115 
116 	if (c->session->itrace_synth_opts->set) {
117 		retval = 1;
118 		goto out;
119 	}
120 
121 	itrace_options = _PyUnicode_AsUTF8(str);
122 
123 	retval = itrace_do_parse_synth_opts(c->session->itrace_synth_opts, itrace_options, 0);
124 out:
125 	return Py_BuildValue("i", retval);
126 }
127 
128 static PyMethodDef ContextMethods[] = {
129 	{ "common_pc", perf_trace_context_common_pc, METH_VARARGS,
130 	  "Get the common preempt count event field value."},
131 	{ "common_flags", perf_trace_context_common_flags, METH_VARARGS,
132 	  "Get the common flags event field value."},
133 	{ "common_lock_depth", perf_trace_context_common_lock_depth,
134 	  METH_VARARGS,	"Get the common lock depth event field value."},
135 	{ "perf_sample_insn", perf_sample_insn,
136 	  METH_VARARGS,	"Get the machine code instruction."},
137 	{ "perf_set_itrace_options", perf_set_itrace_options,
138 	  METH_VARARGS,	"Set --itrace options."},
139 	{ NULL, NULL, 0, NULL}
140 };
141 
142 #if PY_MAJOR_VERSION < 3
143 PyMODINIT_FUNC initperf_trace_context(void)
144 {
145 	(void) Py_InitModule("perf_trace_context", ContextMethods);
146 }
147 #else
148 PyMODINIT_FUNC PyInit_perf_trace_context(void)
149 {
150 	static struct PyModuleDef moduledef = {
151 		PyModuleDef_HEAD_INIT,
152 		"perf_trace_context",	/* m_name */
153 		"",			/* m_doc */
154 		-1,			/* m_size */
155 		ContextMethods,		/* m_methods */
156 		NULL,			/* m_reload */
157 		NULL,			/* m_traverse */
158 		NULL,			/* m_clear */
159 		NULL,			/* m_free */
160 	};
161 	PyObject *mod;
162 
163 	mod = PyModule_Create(&moduledef);
164 	/* Add perf_script_context to the module so it can be imported */
165 	PyObject_SetAttrString(mod, "perf_script_context", Py_None);
166 
167 	return mod;
168 }
169 #endif
170