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