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 
15 #if PY_MAJOR_VERSION < 3
16 #define _PyCapsule_GetPointer(arg1, arg2) \
17   PyCObject_AsVoidPtr(arg1)
18 #define _PyBytes_FromStringAndSize(arg1, arg2) \
19   PyString_FromStringAndSize((arg1), (arg2))
20 
21 PyMODINIT_FUNC initperf_trace_context(void);
22 #else
23 #define _PyCapsule_GetPointer(arg1, arg2) \
24   PyCapsule_GetPointer((arg1), (arg2))
25 #define _PyBytes_FromStringAndSize(arg1, arg2) \
26   PyBytes_FromStringAndSize((arg1), (arg2))
27 
28 PyMODINIT_FUNC PyInit_perf_trace_context(void);
29 #endif
30 
31 static struct scripting_context *get_scripting_context(PyObject *args)
32 {
33 	PyObject *context;
34 
35 	if (!PyArg_ParseTuple(args, "O", &context))
36 		return NULL;
37 
38 	return _PyCapsule_GetPointer(context, NULL);
39 }
40 
41 static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
42 {
43 	struct scripting_context *c = get_scripting_context(args);
44 
45 	if (!c)
46 		return NULL;
47 
48 	return Py_BuildValue("i", common_pc(c));
49 }
50 
51 static PyObject *perf_trace_context_common_flags(PyObject *obj,
52 						 PyObject *args)
53 {
54 	struct scripting_context *c = get_scripting_context(args);
55 
56 	if (!c)
57 		return NULL;
58 
59 	return Py_BuildValue("i", common_flags(c));
60 }
61 
62 static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
63 						      PyObject *args)
64 {
65 	struct scripting_context *c = get_scripting_context(args);
66 
67 	if (!c)
68 		return NULL;
69 
70 	return Py_BuildValue("i", common_lock_depth(c));
71 }
72 
73 static PyObject *perf_sample_insn(PyObject *obj, PyObject *args)
74 {
75 	struct scripting_context *c = get_scripting_context(args);
76 
77 	if (!c)
78 		return NULL;
79 
80 	if (c->sample->ip && !c->sample->insn_len &&
81 	    c->al->thread->maps && c->al->thread->maps->machine)
82 		script_fetch_insn(c->sample, c->al->thread, c->al->thread->maps->machine);
83 
84 	if (!c->sample->insn_len)
85 		Py_RETURN_NONE; /* N.B. This is a return statement */
86 
87 	return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len);
88 }
89 
90 static PyMethodDef ContextMethods[] = {
91 	{ "common_pc", perf_trace_context_common_pc, METH_VARARGS,
92 	  "Get the common preempt count event field value."},
93 	{ "common_flags", perf_trace_context_common_flags, METH_VARARGS,
94 	  "Get the common flags event field value."},
95 	{ "common_lock_depth", perf_trace_context_common_lock_depth,
96 	  METH_VARARGS,	"Get the common lock depth event field value."},
97 	{ "perf_sample_insn", perf_sample_insn,
98 	  METH_VARARGS,	"Get the machine code instruction."},
99 	{ NULL, NULL, 0, NULL}
100 };
101 
102 #if PY_MAJOR_VERSION < 3
103 PyMODINIT_FUNC initperf_trace_context(void)
104 {
105 	(void) Py_InitModule("perf_trace_context", ContextMethods);
106 }
107 #else
108 PyMODINIT_FUNC PyInit_perf_trace_context(void)
109 {
110 	static struct PyModuleDef moduledef = {
111 		PyModuleDef_HEAD_INIT,
112 		"perf_trace_context",	/* m_name */
113 		"",			/* m_doc */
114 		-1,			/* m_size */
115 		ContextMethods,		/* m_methods */
116 		NULL,			/* m_reload */
117 		NULL,			/* m_traverse */
118 		NULL,			/* m_clear */
119 		NULL,			/* m_free */
120 	};
121 	PyObject *mod;
122 
123 	mod = PyModule_Create(&moduledef);
124 	/* Add perf_script_context to the module so it can be imported */
125 	PyObject_SetAttrString(mod, "perf_script_context", Py_None);
126 
127 	return mod;
128 }
129 #endif
130