at for-next 6.3 kB view raw
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 35PyMODINIT_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 44PyMODINIT_FUNC PyInit_perf_trace_context(void); 45#endif 46 47static 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 58static struct scripting_context *get_scripting_context(PyObject *args) 59{ 60 return get_args(args, "context", NULL); 61} 62 63#ifdef HAVE_LIBTRACEEVENT 64static 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 74static 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 85static 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 97static 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 115static 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); 137out: 138 return Py_BuildValue("i", retval); 139} 140 141static 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 176static PyObject *perf_sample_srcline(PyObject *obj, PyObject *args) 177{ 178 return perf_sample_src(obj, args, false); 179} 180 181static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args) 182{ 183 return perf_sample_src(obj, args, true); 184} 185 186static 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 195static 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 217PyMODINIT_FUNC initperf_trace_context(void) 218{ 219 (void) Py_InitModule("perf_trace_context", ContextMethods); 220} 221#else 222PyMODINIT_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