/* * trace-event-python. Feed trace events to an embedded Python interpreter. * * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <Python.h> #include <inttypes.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>#include <errno.h>#include <linux/bitmap.h>#include <linux/compiler.h>#include <linux/time64.h> #include "../build-id.h"#include "../counts.h"#include "../debug.h"#include "../dso.h"#include "../callchain.h"#include "../evsel.h"#include "../event.h"#include "../thread.h"#include "../comm.h"#include "../machine.h"#include "../db-export.h"#include "../thread-stack.h"#include "../trace-event.h"#include "../call-path.h"#include "map.h"#include "symbol.h"#include "thread_map.h"#include "print_binary.h"#include "stat.h"#include "mem-events.h" #if PY_MAJOR_VERSION < 3#define _PyUnicode_FromString(arg) \ PyString_FromString(arg)#define _PyUnicode_FromStringAndSize(arg1, arg2) \ PyString_FromStringAndSize((arg1), (arg2))#define _PyBytes_FromStringAndSize(arg1, arg2) \ PyString_FromStringAndSize((arg1), (arg2))#define _PyLong_FromLong(arg) \ PyInt_FromLong(arg)#define _PyLong_AsLong(arg) \ PyInt_AsLong(arg)#define _PyCapsule_New(arg1, arg2, arg3) \ PyCObject_FromVoidPtr((arg1), (arg2)) PyMODINIT_FUNC initperf_trace_context(void);#else#define _PyUnicode_FromString(arg) \ PyUnicode_FromString(arg)#define _PyUnicode_FromStringAndSize(arg1, arg2) \ PyUnicode_FromStringAndSize((arg1), (arg2))#define _PyBytes_FromStringAndSize(arg1, arg2) \ PyBytes_FromStringAndSize((arg1), (arg2))#define _PyLong_FromLong(arg) \ PyLong_FromLong(arg)#define _PyLong_AsLong(arg) \ PyLong_AsLong(arg)#define _PyCapsule_New(arg1, arg2, arg3) \ PyCapsule_New((arg1), (arg2), (arg3)) PyMODINIT_FUNC PyInit_perf_trace_context(void);#endif #define TRACE_EVENT_TYPE_MAX \ ((1 << (sizeof(unsigned short) * 8)) - 1) static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); #define MAX_FIELDS 64#define N_COMMON_FIELDS 7 extern struct scripting_context *scripting_context; static char *cur_field_name;static int zero_flag_atom; static PyObject *main_module, *main_dict; struct tables { struct db_export dbe; PyObject *evsel_handler; PyObject *machine_handler; PyObject *thread_handler; PyObject *comm_handler; PyObject *comm_thread_handler; PyObject *dso_handler; PyObject *symbol_handler; PyObject *branch_type_handler; PyObject *sample_handler; PyObject *call_path_handler; PyObject *call_return_handler; PyObject *synth_handler; PyObject *context_switch_handler; bool db_export_mode;}; static struct tables tables_global; static void handler_call_die(const char *handler_name) __noreturn;static void handler_call_die(const char *handler_name){ PyErr_Print(); Py_FatalError("problem in Python trace event handler"); // Py_FatalError does not return // but we have to make the compiler happy abort();} /* * Insert val into into the dictionary and decrement the reference counter. * This is necessary for dictionaries since PyDict_SetItemString() does not * steal a reference, as opposed to PyTuple_SetItem(). */static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val){ PyDict_SetItemString(dict, key, val); Py_DECREF(val);} static PyObject *get_handler(const char *handler_name){ PyObject *handler; handler = PyDict_GetItemString(main_dict, handler_name); if (handler && !PyCallable_Check(handler)) return NULL; return handler;} static int get_argument_count(PyObject *handler){ int arg_count = 0; /* * The attribute for the code object is func_code in Python 2, * whereas it is __code__ in Python 3.0+. */ PyObject *code_obj = PyObject_GetAttrString(handler, "func_code"); if (PyErr_Occurred()) { PyErr_Clear(); code_obj = PyObject_GetAttrString(handler, "__code__"); } PyErr_Clear(); if (code_obj) { PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, "co_argcount"); if (arg_count_obj) { arg_count = (int) _PyLong_AsLong(arg_count_obj); Py_DECREF(arg_count_obj); } Py_DECREF(code_obj); } return arg_count;} static void call_object(PyObject *handler, PyObject *args, const char *die_msg){ PyObject *retval; retval = PyObject_CallObject(handler, args); if (retval == NULL) handler_call_die(die_msg); Py_DECREF(retval);} static void try_call_object(const char *handler_name, PyObject *args){ PyObject *handler; handler = get_handler(handler_name); if (handler) call_object(handler, args, handler_name);} static void define_value(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *field_value, const char *field_str){ const char *handler_name = "define_flag_value"; PyObject *t; unsigned long long value; unsigned n = 0; if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_value"; t = PyTuple_New(4); if (!t) Py_FatalError("couldn't create Python tuple"); value = eval_flag(field_value); PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); try_call_object(handler_name, t); Py_DECREF(t);} static void define_values(enum tep_print_arg_type field_type, struct tep_print_flag_sym *field, const char *ev_name, const char *field_name){ define_value(field_type, ev_name, field_name, field->value, field->str); if (field->next) define_values(field_type, field->next, ev_name, field_name);} static void define_field(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *delim){ const char *handler_name = "define_flag_field"; PyObject *t; unsigned n = 0; if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_field"; if (field_type == TEP_PRINT_FLAGS) t = PyTuple_New(3); else t = PyTuple_New(2); if (!t) Py_FatalError("couldn't create Python tuple"); PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); if (field_type == TEP_PRINT_FLAGS) PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); try_call_object(handler_name, t); Py_DECREF(t);} static void define_event_symbols(struct tep_event *event, const char *ev_name, struct tep_print_arg *args){ if (args == NULL) return; switch (args->type) { case TEP_PRINT_NULL: break; case TEP_PRINT_ATOM: define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; case TEP_PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; case TEP_PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name, args->flags.delim); define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name, cur_field_name); break; case TEP_PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL); define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; case TEP_PRINT_HEX: case TEP_PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; case TEP_PRINT_INT_ARRAY: define_event_symbols(event, ev_name, args->int_array.field); define_event_symbols(event, ev_name, args->int_array.count); define_event_symbols(event, ev_name, args->int_array.el_size); break; case TEP_PRINT_STRING: break; case TEP_PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) zero_flag_atom = 1; define_event_symbols(event, ev_name, args->op.left); define_event_symbols(event, ev_name, args->op.right); break; default: /* gcc warns for these? */ case TEP_PRINT_BSTRING: case TEP_PRINT_DYNAMIC_ARRAY: case TEP_PRINT_DYNAMIC_ARRAY_LEN: case TEP_PRINT_FUNC: case TEP_PRINT_BITMASK: /* we should warn... */ return; } if (args->next) define_event_symbols(event, ev_name, args->next);} static PyObject *get_field_numeric_entry(struct tep_event *event, struct tep_format_field *field, void *data){ bool is_array = field->flags & TEP_FIELD_IS_ARRAY; PyObject *obj = NULL, *list = NULL; unsigned long long val; unsigned int item_size, n_items, i; if (is_array) { list = PyList_New(field->arraylen); item_size = field->size / field->arraylen; n_items = field->arraylen; } else { item_size = field->size; n_items = 1; } for (i = 0; i < n_items; i++) { val = read_size(event, data + field->offset + i * item_size, item_size); if (field->flags & TEP_FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && (long long)val <= LONG_MAX) obj = _PyLong_FromLong(val); else obj = PyLong_FromLongLong(val); } else { if (val <= LONG_MAX) obj = _PyLong_FromLong(val); else obj = PyLong_FromUnsignedLongLong(val); } if (is_array) PyList_SET_ITEM(list, i, obj); } if (is_array) obj = list; return obj;} static const char *get_dsoname(struct map *map){ const char *dsoname = "[unknown]"; if (map && map->dso) { if (symbol_conf.show_kernel_path && map->dso->long_name) dsoname = map->dso->long_name; else dsoname = map->dso->name; } return dsoname;} static PyObject *python_process_callchain(struct perf_sample *sample, struct evsel *evsel, struct addr_location *al){ PyObject *pylist; pylist = PyList_New(0); if (!pylist) Py_FatalError("couldn't create Python list"); if (!symbol_conf.use_callchain || !sample->callchain) goto exit; if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, scripting_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); goto exit; } callchain_cursor_commit(&callchain_cursor); while (1) { PyObject *pyelem; struct callchain_cursor_node *node; node = callchain_cursor_current(&callchain_cursor); if (!node) break; pyelem = PyDict_New(); if (!pyelem) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pyelem, "ip", PyLong_FromUnsignedLongLong(node->ip)); if (node->ms.sym) { PyObject *pysym = PyDict_New(); if (!pysym) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pysym, "start", PyLong_FromUnsignedLongLong(node->ms.sym->start)); pydict_set_item_string_decref(pysym, "end", PyLong_FromUnsignedLongLong(node->ms.sym->end)); pydict_set_item_string_decref(pysym, "binding", _PyLong_FromLong(node->ms.sym->binding)); pydict_set_item_string_decref(pysym, "name", _PyUnicode_FromStringAndSize(node->ms.sym->name, node->ms.sym->namelen)); pydict_set_item_string_decref(pyelem, "sym", pysym); } if (node->ms.map) { const char *dsoname = get_dsoname(node->ms.map); pydict_set_item_string_decref(pyelem, "dso", _PyUnicode_FromString(dsoname)); } callchain_cursor_advance(&callchain_cursor); PyList_Append(pylist, pyelem); Py_DECREF(pyelem); } exit: return pylist;} static PyObject *python_process_brstack(struct perf_sample *sample, struct thread *thread){ struct branch_stack *br = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); PyObject *pylist; u64 i; pylist = PyList_New(0); if (!pylist) Py_FatalError("couldn't create Python list"); if (!(br && br->nr)) goto exit; for (i = 0; i < br->nr; i++) { PyObject *pyelem; struct addr_location al; const char *dsoname; pyelem = PyDict_New(); if (!pyelem) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pyelem, "from", PyLong_FromUnsignedLongLong(entries[i].from)); pydict_set_item_string_decref(pyelem, "to", PyLong_FromUnsignedLongLong(entries[i].to)); pydict_set_item_string_decref(pyelem, "mispred", PyBool_FromLong(entries[i].flags.mispred)); pydict_set_item_string_decref(pyelem, "predicted", PyBool_FromLong(entries[i].flags.predicted)); pydict_set_item_string_decref(pyelem, "in_tx", PyBool_FromLong(entries[i].flags.in_tx)); pydict_set_item_string_decref(pyelem, "abort", PyBool_FromLong(entries[i].flags.abort)); pydict_set_item_string_decref(pyelem, "cycles", PyLong_FromUnsignedLongLong(entries[i].flags.cycles));Lines 1–500 of 1890. Load more
/* * trace-event-python. Feed trace events to an embedded Python interpreter. * * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include <Python.h> #include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include <errno.h> #include <linux/bitmap.h> #include <linux/compiler.h> #include <linux/time64.h> #include "../build-id.h" #include "../counts.h" #include "../debug.h" #include "../dso.h" #include "../callchain.h" #include "../evsel.h" #include "../event.h" #include "../thread.h" #include "../comm.h" #include "../machine.h" #include "../db-export.h" #include "../thread-stack.h" #include "../trace-event.h" #include "../call-path.h" #include "map.h" #include "symbol.h" #include "thread_map.h" #include "print_binary.h" #include "stat.h" #include "mem-events.h" #if PY_MAJOR_VERSION < 3 #define _PyUnicode_FromString(arg) \ PyString_FromString(arg) #define _PyUnicode_FromStringAndSize(arg1, arg2) \ PyString_FromStringAndSize((arg1), (arg2)) #define _PyBytes_FromStringAndSize(arg1, arg2) \ PyString_FromStringAndSize((arg1), (arg2)) #define _PyLong_FromLong(arg) \ PyInt_FromLong(arg) #define _PyLong_AsLong(arg) \ PyInt_AsLong(arg) #define _PyCapsule_New(arg1, arg2, arg3) \ PyCObject_FromVoidPtr((arg1), (arg2)) PyMODINIT_FUNC initperf_trace_context(void); #else #define _PyUnicode_FromString(arg) \ PyUnicode_FromString(arg) #define _PyUnicode_FromStringAndSize(arg1, arg2) \ PyUnicode_FromStringAndSize((arg1), (arg2)) #define _PyBytes_FromStringAndSize(arg1, arg2) \ PyBytes_FromStringAndSize((arg1), (arg2)) #define _PyLong_FromLong(arg) \ PyLong_FromLong(arg) #define _PyLong_AsLong(arg) \ PyLong_AsLong(arg) #define _PyCapsule_New(arg1, arg2, arg3) \ PyCapsule_New((arg1), (arg2), (arg3)) PyMODINIT_FUNC PyInit_perf_trace_context(void); #endif #define TRACE_EVENT_TYPE_MAX \ ((1 << (sizeof(unsigned short) * 8)) - 1) static DECLARE_BITMAP(events_defined, TRACE_EVENT_TYPE_MAX); #define MAX_FIELDS 64 #define N_COMMON_FIELDS 7 extern struct scripting_context *scripting_context; static char *cur_field_name; static int zero_flag_atom; static PyObject *main_module, *main_dict; struct tables { struct db_export dbe; PyObject *evsel_handler; PyObject *machine_handler; PyObject *thread_handler; PyObject *comm_handler; PyObject *comm_thread_handler; PyObject *dso_handler; PyObject *symbol_handler; PyObject *branch_type_handler; PyObject *sample_handler; PyObject *call_path_handler; PyObject *call_return_handler; PyObject *synth_handler; PyObject *context_switch_handler; bool db_export_mode; }; static struct tables tables_global; static void handler_call_die(const char *handler_name) __noreturn; static void handler_call_die(const char *handler_name) { PyErr_Print(); Py_FatalError("problem in Python trace event handler"); // Py_FatalError does not return // but we have to make the compiler happy abort(); } /* * Insert val into into the dictionary and decrement the reference counter. * This is necessary for dictionaries since PyDict_SetItemString() does not * steal a reference, as opposed to PyTuple_SetItem(). */ static void pydict_set_item_string_decref(PyObject *dict, const char *key, PyObject *val) { PyDict_SetItemString(dict, key, val); Py_DECREF(val); } static PyObject *get_handler(const char *handler_name) { PyObject *handler; handler = PyDict_GetItemString(main_dict, handler_name); if (handler && !PyCallable_Check(handler)) return NULL; return handler; } static int get_argument_count(PyObject *handler) { int arg_count = 0; /* * The attribute for the code object is func_code in Python 2, * whereas it is __code__ in Python 3.0+. */ PyObject *code_obj = PyObject_GetAttrString(handler, "func_code"); if (PyErr_Occurred()) { PyErr_Clear(); code_obj = PyObject_GetAttrString(handler, "__code__"); } PyErr_Clear(); if (code_obj) { PyObject *arg_count_obj = PyObject_GetAttrString(code_obj, "co_argcount"); if (arg_count_obj) { arg_count = (int) _PyLong_AsLong(arg_count_obj); Py_DECREF(arg_count_obj); } Py_DECREF(code_obj); } return arg_count; } static void call_object(PyObject *handler, PyObject *args, const char *die_msg) { PyObject *retval; retval = PyObject_CallObject(handler, args); if (retval == NULL) handler_call_die(die_msg); Py_DECREF(retval); } static void try_call_object(const char *handler_name, PyObject *args) { PyObject *handler; handler = get_handler(handler_name); if (handler) call_object(handler, args, handler_name); } static void define_value(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *field_value, const char *field_str) { const char *handler_name = "define_flag_value"; PyObject *t; unsigned long long value; unsigned n = 0; if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_value"; t = PyTuple_New(4); if (!t) Py_FatalError("couldn't create Python tuple"); value = eval_flag(field_value); PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); PyTuple_SetItem(t, n++, _PyLong_FromLong(value)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_str)); try_call_object(handler_name, t); Py_DECREF(t); } static void define_values(enum tep_print_arg_type field_type, struct tep_print_flag_sym *field, const char *ev_name, const char *field_name) { define_value(field_type, ev_name, field_name, field->value, field->str); if (field->next) define_values(field_type, field->next, ev_name, field_name); } static void define_field(enum tep_print_arg_type field_type, const char *ev_name, const char *field_name, const char *delim) { const char *handler_name = "define_flag_field"; PyObject *t; unsigned n = 0; if (field_type == TEP_PRINT_SYMBOL) handler_name = "define_symbolic_field"; if (field_type == TEP_PRINT_FLAGS) t = PyTuple_New(3); else t = PyTuple_New(2); if (!t) Py_FatalError("couldn't create Python tuple"); PyTuple_SetItem(t, n++, _PyUnicode_FromString(ev_name)); PyTuple_SetItem(t, n++, _PyUnicode_FromString(field_name)); if (field_type == TEP_PRINT_FLAGS) PyTuple_SetItem(t, n++, _PyUnicode_FromString(delim)); try_call_object(handler_name, t); Py_DECREF(t); } static void define_event_symbols(struct tep_event *event, const char *ev_name, struct tep_print_arg *args) { if (args == NULL) return; switch (args->type) { case TEP_PRINT_NULL: break; case TEP_PRINT_ATOM: define_value(TEP_PRINT_FLAGS, ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; case TEP_PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; case TEP_PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_field(TEP_PRINT_FLAGS, ev_name, cur_field_name, args->flags.delim); define_values(TEP_PRINT_FLAGS, args->flags.flags, ev_name, cur_field_name); break; case TEP_PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_field(TEP_PRINT_SYMBOL, ev_name, cur_field_name, NULL); define_values(TEP_PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; case TEP_PRINT_HEX: case TEP_PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; case TEP_PRINT_INT_ARRAY: define_event_symbols(event, ev_name, args->int_array.field); define_event_symbols(event, ev_name, args->int_array.count); define_event_symbols(event, ev_name, args->int_array.el_size); break; case TEP_PRINT_STRING: break; case TEP_PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; case TEP_PRINT_OP: if (strcmp(args->op.op, ":") == 0) zero_flag_atom = 1; define_event_symbols(event, ev_name, args->op.left); define_event_symbols(event, ev_name, args->op.right); break; default: /* gcc warns for these? */ case TEP_PRINT_BSTRING: case TEP_PRINT_DYNAMIC_ARRAY: case TEP_PRINT_DYNAMIC_ARRAY_LEN: case TEP_PRINT_FUNC: case TEP_PRINT_BITMASK: /* we should warn... */ return; } if (args->next) define_event_symbols(event, ev_name, args->next); } static PyObject *get_field_numeric_entry(struct tep_event *event, struct tep_format_field *field, void *data) { bool is_array = field->flags & TEP_FIELD_IS_ARRAY; PyObject *obj = NULL, *list = NULL; unsigned long long val; unsigned int item_size, n_items, i; if (is_array) { list = PyList_New(field->arraylen); item_size = field->size / field->arraylen; n_items = field->arraylen; } else { item_size = field->size; n_items = 1; } for (i = 0; i < n_items; i++) { val = read_size(event, data + field->offset + i * item_size, item_size); if (field->flags & TEP_FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && (long long)val <= LONG_MAX) obj = _PyLong_FromLong(val); else obj = PyLong_FromLongLong(val); } else { if (val <= LONG_MAX) obj = _PyLong_FromLong(val); else obj = PyLong_FromUnsignedLongLong(val); } if (is_array) PyList_SET_ITEM(list, i, obj); } if (is_array) obj = list; return obj; } static const char *get_dsoname(struct map *map) { const char *dsoname = "[unknown]"; if (map && map->dso) { if (symbol_conf.show_kernel_path && map->dso->long_name) dsoname = map->dso->long_name; else dsoname = map->dso->name; } return dsoname; } static PyObject *python_process_callchain(struct perf_sample *sample, struct evsel *evsel, struct addr_location *al) { PyObject *pylist; pylist = PyList_New(0); if (!pylist) Py_FatalError("couldn't create Python list"); if (!symbol_conf.use_callchain || !sample->callchain) goto exit; if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel, sample, NULL, NULL, scripting_max_stack) != 0) { pr_err("Failed to resolve callchain. Skipping\n"); goto exit; } callchain_cursor_commit(&callchain_cursor); while (1) { PyObject *pyelem; struct callchain_cursor_node *node; node = callchain_cursor_current(&callchain_cursor); if (!node) break; pyelem = PyDict_New(); if (!pyelem) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pyelem, "ip", PyLong_FromUnsignedLongLong(node->ip)); if (node->ms.sym) { PyObject *pysym = PyDict_New(); if (!pysym) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pysym, "start", PyLong_FromUnsignedLongLong(node->ms.sym->start)); pydict_set_item_string_decref(pysym, "end", PyLong_FromUnsignedLongLong(node->ms.sym->end)); pydict_set_item_string_decref(pysym, "binding", _PyLong_FromLong(node->ms.sym->binding)); pydict_set_item_string_decref(pysym, "name", _PyUnicode_FromStringAndSize(node->ms.sym->name, node->ms.sym->namelen)); pydict_set_item_string_decref(pyelem, "sym", pysym); } if (node->ms.map) { const char *dsoname = get_dsoname(node->ms.map); pydict_set_item_string_decref(pyelem, "dso", _PyUnicode_FromString(dsoname)); } callchain_cursor_advance(&callchain_cursor); PyList_Append(pylist, pyelem); Py_DECREF(pyelem); } exit: return pylist; } static PyObject *python_process_brstack(struct perf_sample *sample, struct thread *thread) { struct branch_stack *br = sample->branch_stack; struct branch_entry *entries = perf_sample__branch_entries(sample); PyObject *pylist; u64 i; pylist = PyList_New(0); if (!pylist) Py_FatalError("couldn't create Python list"); if (!(br && br->nr)) goto exit; for (i = 0; i < br->nr; i++) { PyObject *pyelem; struct addr_location al; const char *dsoname; pyelem = PyDict_New(); if (!pyelem) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pyelem, "from", PyLong_FromUnsignedLongLong(entries[i].from)); pydict_set_item_string_decref(pyelem, "to", PyLong_FromUnsignedLongLong(entries[i].to)); pydict_set_item_string_decref(pyelem, "mispred", PyBool_FromLong(entries[i].flags.mispred)); pydict_set_item_string_decref(pyelem, "predicted", PyBool_FromLong(entries[i].flags.predicted)); pydict_set_item_string_decref(pyelem, "in_tx", PyBool_FromLong(entries[i].flags.in_tx)); pydict_set_item_string_decref(pyelem, "abort", PyBool_FromLong(entries[i].flags.abort)); pydict_set_item_string_decref(pyelem, "cycles", PyLong_FromUnsignedLongLong(entries[i].flags.cycles));