/* * 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 "../../perf.h"#include "../debug.h"#include "../callchain.h"#include "../evsel.h"#include "../util.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 "../machine.h"#include "../call-path.h"#include "thread_map.h"#include "cpumap.h"#include "print_binary.h"#include "stat.h" PyMODINIT_FUNC initperf_trace_context(void); #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; 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 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 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 == 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++, PyString_FromString(ev_name)); PyTuple_SetItem(t, n++, PyString_FromString(field_name)); PyTuple_SetItem(t, n++, PyInt_FromLong(value)); PyTuple_SetItem(t, n++, PyString_FromString(field_str)); try_call_object(handler_name, t); Py_DECREF(t);} static void define_values(enum print_arg_type field_type, struct 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 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 == PRINT_SYMBOL) handler_name = "define_symbolic_field"; if (field_type == PRINT_FLAGS) t = PyTuple_New(3); else t = PyTuple_New(2); if (!t) Py_FatalError("couldn't create Python tuple"); PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); PyTuple_SetItem(t, n++, PyString_FromString(field_name)); if (field_type == PRINT_FLAGS) PyTuple_SetItem(t, n++, PyString_FromString(delim)); try_call_object(handler_name, t); Py_DECREF(t);} static void define_event_symbols(struct event_format *event, const char *ev_name, struct print_arg *args){ if (args == NULL) return; switch (args->type) { case PRINT_NULL: break; case PRINT_ATOM: define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; case PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; case PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_field(PRINT_FLAGS, ev_name, cur_field_name, args->flags.delim); define_values(PRINT_FLAGS, args->flags.flags, ev_name, cur_field_name); break; case PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; case PRINT_HEX: case PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; case 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 PRINT_STRING: break; case PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; case 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 PRINT_BSTRING: case PRINT_DYNAMIC_ARRAY: case PRINT_DYNAMIC_ARRAY_LEN: case PRINT_FUNC: case PRINT_BITMASK: /* we should warn... */ return; } if (args->next) define_event_symbols(event, ev_name, args->next);} static PyObject *get_field_numeric_entry(struct event_format *event, struct format_field *field, void *data){ bool is_array = field->flags & 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 & FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && (long long)val <= LONG_MAX) obj = PyInt_FromLong(val); else obj = PyLong_FromLongLong(val); } else { if (val <= LONG_MAX) obj = PyInt_FromLong(val); else obj = PyLong_FromUnsignedLongLong(val); } if (is_array) PyList_SET_ITEM(list, i, obj); } if (is_array) obj = list; return obj;} static PyObject *python_process_callchain(struct perf_sample *sample, struct perf_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->sym) { PyObject *pysym = PyDict_New(); if (!pysym) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pysym, "start", PyLong_FromUnsignedLongLong(node->sym->start)); pydict_set_item_string_decref(pysym, "end", PyLong_FromUnsignedLongLong(node->sym->end)); pydict_set_item_string_decref(pysym, "binding", PyInt_FromLong(node->sym->binding)); pydict_set_item_string_decref(pysym, "name", PyString_FromStringAndSize(node->sym->name, node->sym->namelen)); pydict_set_item_string_decref(pyelem, "sym", pysym); } if (node->map) { struct map *map = node->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; } pydict_set_item_string_decref(pyelem, "dso", PyString_FromString(dsoname)); } callchain_cursor_advance(&callchain_cursor); PyList_Append(pylist, pyelem); Py_DECREF(pyelem); } exit: return pylist;} static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al){ struct event_format *event = evsel->tp_format; PyObject *handler, *context, *t, *obj = NULL, *callchain; PyObject *dict = NULL; static char handler_name[256]; struct format_field *field; unsigned long s, ns; unsigned n = 0; int pid; int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; const char *comm = thread__comm_str(al->thread); t = PyTuple_New(MAX_FIELDS); if (!t) Py_FatalError("couldn't create Python tuple"); if (!event) { snprintf(handler_name, sizeof(handler_name), "ug! no event found for type %" PRIu64, (u64)evsel->attr.config); Py_FatalError(handler_name); } pid = raw_field_value(event, "common_pid", data); sprintf(handler_name, "%s__%s", event->system, event->name); if (!test_and_set_bit(event->id, events_defined)) define_event_symbols(event, handler_name, event->print_fmt.args); handler = get_handler(handler_name); if (!handler) { dict = PyDict_New(); if (!dict) Py_FatalError("couldn't create Python dict"); } s = nsecs / NSEC_PER_SEC; ns = nsecs - s * NSEC_PER_SEC; scripting_context->event_data = data; scripting_context->pevent = evsel->tp_format->pevent; context = PyCObject_FromVoidPtr(scripting_context, NULL); PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); PyTuple_SetItem(t, n++, context); /* ip unwinding */ callchain = python_process_callchain(sample, evsel, al); if (handler) { PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); PyTuple_SetItem(t, n++, PyInt_FromLong(s)); PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); PyTuple_SetItem(t, n++, PyString_FromString(comm)); PyTuple_SetItem(t, n++, callchain); } else { pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); pydict_set_item_string_decref(dict, "common_callchain", callchain); } for (field = event->format.fields; field; field = field->next) { unsigned int offset, len; unsigned long long val; if (field->flags & FIELD_IS_ARRAY) { offset = field->offset; len = field->size; if (field->flags & FIELD_IS_DYNAMIC) { val = pevent_read_number(scripting_context->pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } if (field->flags & FIELD_IS_STRING && is_printable_array(data + offset, len)) { obj = PyString_FromString((char *) data + offset); } else { obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); field->flags &= ~FIELD_IS_STRING; } } else { /* FIELD_IS_NUMERIC */ obj = get_field_numeric_entry(event, field, data); } if (handler) PyTuple_SetItem(t, n++, obj); else pydict_set_item_string_decref(dict, field->name, obj); } if (!handler) PyTuple_SetItem(t, n++, dict); if (_PyTuple_Resize(&t, n) == -1) Py_FatalError("error resizing Python tuple"); if (handler) {Lines 1–500 of 1367. 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 "../../perf.h" #include "../debug.h" #include "../callchain.h" #include "../evsel.h" #include "../util.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 "../machine.h" #include "../call-path.h" #include "thread_map.h" #include "cpumap.h" #include "print_binary.h" #include "stat.h" PyMODINIT_FUNC initperf_trace_context(void); #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; 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 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 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 == 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++, PyString_FromString(ev_name)); PyTuple_SetItem(t, n++, PyString_FromString(field_name)); PyTuple_SetItem(t, n++, PyInt_FromLong(value)); PyTuple_SetItem(t, n++, PyString_FromString(field_str)); try_call_object(handler_name, t); Py_DECREF(t); } static void define_values(enum print_arg_type field_type, struct 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 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 == PRINT_SYMBOL) handler_name = "define_symbolic_field"; if (field_type == PRINT_FLAGS) t = PyTuple_New(3); else t = PyTuple_New(2); if (!t) Py_FatalError("couldn't create Python tuple"); PyTuple_SetItem(t, n++, PyString_FromString(ev_name)); PyTuple_SetItem(t, n++, PyString_FromString(field_name)); if (field_type == PRINT_FLAGS) PyTuple_SetItem(t, n++, PyString_FromString(delim)); try_call_object(handler_name, t); Py_DECREF(t); } static void define_event_symbols(struct event_format *event, const char *ev_name, struct print_arg *args) { if (args == NULL) return; switch (args->type) { case PRINT_NULL: break; case PRINT_ATOM: define_value(PRINT_FLAGS, ev_name, cur_field_name, "0", args->atom.atom); zero_flag_atom = 0; break; case PRINT_FIELD: free(cur_field_name); cur_field_name = strdup(args->field.name); break; case PRINT_FLAGS: define_event_symbols(event, ev_name, args->flags.field); define_field(PRINT_FLAGS, ev_name, cur_field_name, args->flags.delim); define_values(PRINT_FLAGS, args->flags.flags, ev_name, cur_field_name); break; case PRINT_SYMBOL: define_event_symbols(event, ev_name, args->symbol.field); define_field(PRINT_SYMBOL, ev_name, cur_field_name, NULL); define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name, cur_field_name); break; case PRINT_HEX: case PRINT_HEX_STR: define_event_symbols(event, ev_name, args->hex.field); define_event_symbols(event, ev_name, args->hex.size); break; case 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 PRINT_STRING: break; case PRINT_TYPE: define_event_symbols(event, ev_name, args->typecast.item); break; case 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 PRINT_BSTRING: case PRINT_DYNAMIC_ARRAY: case PRINT_DYNAMIC_ARRAY_LEN: case PRINT_FUNC: case PRINT_BITMASK: /* we should warn... */ return; } if (args->next) define_event_symbols(event, ev_name, args->next); } static PyObject *get_field_numeric_entry(struct event_format *event, struct format_field *field, void *data) { bool is_array = field->flags & 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 & FIELD_IS_SIGNED) { if ((long long)val >= LONG_MIN && (long long)val <= LONG_MAX) obj = PyInt_FromLong(val); else obj = PyLong_FromLongLong(val); } else { if (val <= LONG_MAX) obj = PyInt_FromLong(val); else obj = PyLong_FromUnsignedLongLong(val); } if (is_array) PyList_SET_ITEM(list, i, obj); } if (is_array) obj = list; return obj; } static PyObject *python_process_callchain(struct perf_sample *sample, struct perf_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->sym) { PyObject *pysym = PyDict_New(); if (!pysym) Py_FatalError("couldn't create Python dictionary"); pydict_set_item_string_decref(pysym, "start", PyLong_FromUnsignedLongLong(node->sym->start)); pydict_set_item_string_decref(pysym, "end", PyLong_FromUnsignedLongLong(node->sym->end)); pydict_set_item_string_decref(pysym, "binding", PyInt_FromLong(node->sym->binding)); pydict_set_item_string_decref(pysym, "name", PyString_FromStringAndSize(node->sym->name, node->sym->namelen)); pydict_set_item_string_decref(pyelem, "sym", pysym); } if (node->map) { struct map *map = node->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; } pydict_set_item_string_decref(pyelem, "dso", PyString_FromString(dsoname)); } callchain_cursor_advance(&callchain_cursor); PyList_Append(pylist, pyelem); Py_DECREF(pyelem); } exit: return pylist; } static void python_process_tracepoint(struct perf_sample *sample, struct perf_evsel *evsel, struct addr_location *al) { struct event_format *event = evsel->tp_format; PyObject *handler, *context, *t, *obj = NULL, *callchain; PyObject *dict = NULL; static char handler_name[256]; struct format_field *field; unsigned long s, ns; unsigned n = 0; int pid; int cpu = sample->cpu; void *data = sample->raw_data; unsigned long long nsecs = sample->time; const char *comm = thread__comm_str(al->thread); t = PyTuple_New(MAX_FIELDS); if (!t) Py_FatalError("couldn't create Python tuple"); if (!event) { snprintf(handler_name, sizeof(handler_name), "ug! no event found for type %" PRIu64, (u64)evsel->attr.config); Py_FatalError(handler_name); } pid = raw_field_value(event, "common_pid", data); sprintf(handler_name, "%s__%s", event->system, event->name); if (!test_and_set_bit(event->id, events_defined)) define_event_symbols(event, handler_name, event->print_fmt.args); handler = get_handler(handler_name); if (!handler) { dict = PyDict_New(); if (!dict) Py_FatalError("couldn't create Python dict"); } s = nsecs / NSEC_PER_SEC; ns = nsecs - s * NSEC_PER_SEC; scripting_context->event_data = data; scripting_context->pevent = evsel->tp_format->pevent; context = PyCObject_FromVoidPtr(scripting_context, NULL); PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); PyTuple_SetItem(t, n++, context); /* ip unwinding */ callchain = python_process_callchain(sample, evsel, al); if (handler) { PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); PyTuple_SetItem(t, n++, PyInt_FromLong(s)); PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); PyTuple_SetItem(t, n++, PyString_FromString(comm)); PyTuple_SetItem(t, n++, callchain); } else { pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); pydict_set_item_string_decref(dict, "common_callchain", callchain); } for (field = event->format.fields; field; field = field->next) { unsigned int offset, len; unsigned long long val; if (field->flags & FIELD_IS_ARRAY) { offset = field->offset; len = field->size; if (field->flags & FIELD_IS_DYNAMIC) { val = pevent_read_number(scripting_context->pevent, data + offset, len); offset = val; len = offset >> 16; offset &= 0xffff; } if (field->flags & FIELD_IS_STRING && is_printable_array(data + offset, len)) { obj = PyString_FromString((char *) data + offset); } else { obj = PyByteArray_FromStringAndSize((const char *) data + offset, len); field->flags &= ~FIELD_IS_STRING; } } else { /* FIELD_IS_NUMERIC */ obj = get_field_numeric_entry(event, field, data); } if (handler) PyTuple_SetItem(t, n++, obj); else pydict_set_item_string_decref(dict, field->name, obj); } if (!handler) PyTuple_SetItem(t, n++, dict); if (_PyTuple_Resize(&t, n) == -1) Py_FatalError("error resizing Python tuple"); if (handler) {