@@ -13,6 +13,8 @@ from Cython.Build import cythonize
def main():
kshark_path = '/usr/local/lib/kernelshark'
+ traceevent_path = '/usr/local/lib/traceevent/'
+ tracecmd_path = '/usr/local/lib/trace-cmd/'
module_ks = Extension('tracecruncher.ksharkpy',
sources=['src/ksharkpy.c'],
@@ -25,6 +27,13 @@ def main():
],
)
+ module_ft = Extension('tracecruncher.ftracepy',
+ sources=['src/ftracepy.c'],
+ library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+ runtime_library_dirs=[kshark_path, traceevent_path, tracecmd_path],
+ libraries=['kshark', 'traceevent', 'tracecmd'],
+ )
+
setup(name='tracecruncher',
version='0.1.0',
description='NumPy based interface for accessing tracing data in Python.',
@@ -33,7 +42,7 @@ def main():
url='https://github.com/vmware/trace-cruncher',
license='LGPL-2.1',
packages=find_packages(),
- ext_modules=[module_ks],
+ ext_modules=[module_ks, module_ft],
classifiers=[
'Development Status :: 3 - Alpha',
'Programming Language :: Python :: 3',
@@ -9,6 +9,7 @@
#define TRACECRUNCHER_ERROR tracecruncher_error
#define KSHARK_ERROR kshark_error
+#define FTRACE_ERROR ftrace_error
#define KS_INIT_ERROR \
PyErr_SetString(KSHARK_ERROR, "libshark failed to initialize");
new file mode 100644
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: LGPL-2.1
+
+/*
+ * Copyright (C) 2019 VMware Inc, Yordan Karadzhov (VMware) <y.karadz@gmail.com>
+ */
+
+// Python
+#include <Python.h>
+
+// trace-cmd
+#include "trace-cmd/trace-cmd.h"
+
+// KernelShark
+#include "kernelshark/libkshark.h"
+#include "kernelshark/libkshark-tepdata.h"
+
+// trace-cruncher
+#include "common.h"
+
+static PyObject *KSHARK_ERROR = NULL;
+static PyObject *FTRACE_ERROR = NULL;
+
+static PyObject *method_event_id(PyObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct kshark_context *kshark_ctx = NULL;
+ struct tep_event *event;
+ const char *system, *name;
+
+ static char *kwlist[] = {"system", "event", NULL};
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "ss",
+ kwlist,
+ &system,
+ &name)) {
+ return NULL;
+ }
+
+ if (!kshark_instance(&kshark_ctx)) {
+ KS_INIT_ERROR
+ return NULL;
+ }
+
+ event = tep_find_event_by_name(kshark_ctx->pevent, system, name);
+ if (!event) {
+ PyErr_Format(FTRACE_ERROR,
+ "Failed to find event '%s/%s'",
+ system, name);
+ }
+
+ return PyLong_FromLong(event->id);
+}
+
+static PyObject *method_read_event_field(PyObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct kshark_context *kshark_ctx = NULL;
+ struct tep_format_field *evt_field;
+ struct tep_record *record;
+ struct tep_event *event;
+ unsigned long long val;
+ const char *field;
+ uint64_t offset;
+ int event_id, ret;
+
+ static char *kwlist[] = {"offset", "event_id", "field", NULL};
+ if(!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "Lis",
+ kwlist,
+ &offset,
+ &event_id,
+ &field)) {
+ return NULL;
+ }
+
+ if (!kshark_instance(&kshark_ctx)) {
+ KS_INIT_ERROR
+ return NULL;
+ }
+
+ event = tep_find_event(kshark_ctx->pevent, event_id);
+ if (!event) {
+ PyErr_Format(FTRACE_ERROR,
+ "Failed to find event '%i'",
+ event_id);
+ return NULL;
+ }
+
+ evt_field = tep_find_any_field(event, field);
+ if (!evt_field) {
+ PyErr_Format(FTRACE_ERROR,
+ "Failed to find field '%s' of event '%i'",
+ field, event_id);
+ return NULL;
+ }
+
+ record = tracecmd_read_at(kshark_ctx->handle, offset, NULL);
+ if (!record) {
+ PyErr_Format(FTRACE_ERROR,
+ "Failed to read record at offset '%i'",
+ offset);
+ return NULL;
+ }
+
+ ret = tep_read_number_field(evt_field, record->data, &val);
+ free_record(record);
+
+ if (ret != 0) {
+ PyErr_Format(FTRACE_ERROR,
+ "Failed to read field '%s' of event '%i'",
+ field, event_id);
+ return NULL;
+ }
+
+ return PyLong_FromLong(val);
+}
+
+static PyObject *method_get_function(PyObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct kshark_context *kshark_ctx = NULL;
+ unsigned long long address;
+ const char *func;
+
+ static char *kwlist[] = {"address"};
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "i",
+ kwlist,
+ &address)) {
+ return NULL;
+ }
+
+ if (!kshark_instance(&kshark_ctx)) {
+ KS_INIT_ERROR
+ return NULL;
+ }
+
+ func = tep_find_function(kshark_ctx->pevent, address);
+ if (!func)
+ Py_RETURN_NONE;
+
+ return PyUnicode_FromString(func);
+}
+
+static PyObject *method_map_instruction_address(PyObject *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct kshark_context *kshark_ctx = NULL;
+ struct tracecmd_proc_addr_map *mem_map;
+ unsigned long long proc_addr, obj_addr;
+ int pid;
+ PyObject *ret;
+
+ static char *kwlist[] = {"pid", "proc_addr"};
+ if (!PyArg_ParseTupleAndKeywords(args,
+ kwargs,
+ "iL",
+ kwlist,
+ &pid,
+ &proc_addr)) {
+ return NULL;
+ }
+
+ if (!kshark_instance(&kshark_ctx)) {
+ KS_INIT_ERROR
+ return NULL;
+ }
+
+ mem_map = tracecmd_search_task_map(kshark_ctx->handle,
+ pid, proc_addr);
+
+ if (!mem_map)
+ Py_RETURN_NONE;
+
+ ret = PyDict_New();
+
+ PyDict_SetItemString(ret, "obj_file",
+ PyUnicode_FromString(mem_map->lib_name));
+
+ obj_addr = proc_addr - mem_map->start;
+ PyDict_SetItemString(ret, "address", PyLong_FromLong(obj_addr));
+
+ return ret;
+}
+
+static PyMethodDef ftracepy_methods[] = {
+ {"event_id",
+ (PyCFunction) method_event_id,
+ METH_VARARGS | METH_KEYWORDS,
+ "Get the Id of the event from its name"
+ },
+ {"read_event_field",
+ (PyCFunction) method_read_event_field,
+ METH_VARARGS | METH_KEYWORDS,
+ "Get the value of an event field having a given name"
+ },
+ {"get_function",
+ (PyCFunction) method_get_function,
+ METH_VARARGS | METH_KEYWORDS,
+ ""
+ },
+ {"map_instruction_address",
+ (PyCFunction) method_map_instruction_address,
+ METH_VARARGS | METH_KEYWORDS,
+ ""
+ },
+ {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef ftracepy_module = {
+ PyModuleDef_HEAD_INIT,
+ "ftracepy",
+ "",
+ -1,
+ ftracepy_methods
+};
+
+PyMODINIT_FUNC PyInit_ftracepy(void)
+{
+ PyObject *module = PyModule_Create(&ftracepy_module);
+
+ KSHARK_ERROR = PyErr_NewException("tracecruncher.ftracepy.ks_error",
+ NULL, NULL);
+ PyModule_AddObject(module, "ks_error", KSHARK_ERROR);
+
+ FTRACE_ERROR = PyErr_NewException("tracecruncher.ftracepy.ft_error",
+ NULL, NULL);
+ PyModule_AddObject(module, "ft_error", FTRACE_ERROR);
+
+ return module;
+}
The part of the interface that relies on libtraceevent gets re-implemented as an extension called "tracecruncher.ftracepy". The new extension gets build together with the previously implemented "tracecruncher.ksharkpy" extension. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com> --- setup.py | 11 ++- src/common.h | 1 + src/ftracepy.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 src/ftracepy.c