@@ -1668,117 +1668,55 @@ PyObject *PyFtrace_tc_event_system(PyObject *self)
return PyUnicode_FromString(TC_SYS);
}
-struct ftracepy_kprobe {
- char *event;
- char *function;
- char *probe;
-};
-
-static bool register_kprobe(const char *event,
- const char *function,
- const char *probe)
-{
- if (tracefs_kprobe_raw(TC_SYS, event, function, probe) < 0) {
- TfsError_fmt(NULL, "Failed to register kprobe \'%s\'.",
- event);
- return false;
- }
-
- return true;
-}
-
-static bool register_kretprobe(const char *event,
- const char *function,
- const char *probe)
+static PyObject *dynevent_info2py(char *buff, int type)
{
- if (tracefs_kretprobe_raw(TC_SYS, event, function, probe) < 0) {
- TfsError_fmt(NULL, "Failed to register kretprobe \'%s\'.",
- event);
- return false;
- }
-
- return true;
-}
+ PyObject *ret;
-static bool unregister_kprobe(const char *event)
-{
- if (tracefs_kprobe_clear_probe(TC_SYS, event, true) < 0) {
- TfsError_fmt(NULL, "Failed to unregister kprobe \'%s\'.",
- event);
- return false;
+ if (type == TRACEFS_DYNEVENT_UNKNOWN) {
+ PyErr_SetString(TFS_ERROR, "Failed to get dynevent info.");
+ return NULL;
}
- return true;
-}
+ ret = PyUnicode_FromString(buff);
+ free(buff);
-PyObject *PyKprobe_event(PyKprobe *self)
-{
- return PyUnicode_FromString(self->ptrObj->event);
+ return ret;
}
-PyObject *PyKprobe_system(PyKprobe *self)
+PyObject *PyDynevent_system(PyDynevent *self)
{
- return PyUnicode_FromString(TC_SYS);
-}
+ char *buff;
+ int type;
-PyObject *PyKprobe_function(PyKprobe *self)
-{
- return PyUnicode_FromString(self->ptrObj->function);
+ type = tracefs_dynevent_info(self->ptrObj, &buff, NULL, NULL, NULL, NULL);
+ return dynevent_info2py(buff, type);
}
-PyObject *PyKprobe_probe(PyKprobe *self)
+PyObject *PyDynevent_event(PyDynevent *self)
{
- return PyUnicode_FromString(self->ptrObj->probe);
-}
+ char *buff;
+ int type;
-int ftracepy_kprobe_destroy(struct ftracepy_kprobe *kp)
-{
- return tracefs_kprobe_clear_probe(TC_SYS, kp-> event, true);
+ type = tracefs_dynevent_info(self->ptrObj, NULL, &buff, NULL, NULL, NULL);
+ return dynevent_info2py(buff, type);
}
-void ftracepy_kprobe_free(struct ftracepy_kprobe *kp)
+PyObject *PyDynevent_address(PyDynevent *self)
{
- free(kp->event);
- free(kp->function);
- free(kp->probe);
- free(kp);
+ char *buff;
+ int type;
+
+ type = tracefs_dynevent_info(self->ptrObj, NULL, NULL, NULL, &buff, NULL);
+ return dynevent_info2py(buff, type);
}
-static struct ftracepy_kprobe *
-kprobe_new(const char *event, const char *function, const char *probe,
- bool retprobe)
+PyObject *PyDynevent_probe(PyDynevent *self)
{
- struct ftracepy_kprobe *new_kprobe;
+ char *buff;
+ int type;
- if (retprobe) {
- if (!register_kretprobe(event, function, probe))
- return NULL;
- } else {
- if (!register_kprobe(event, function, probe))
- return NULL;
- }
-
- new_kprobe = calloc(1, sizeof(*new_kprobe));
- if (!new_kprobe) {
- MEM_ERROR;
- unregister_kprobe(event);
-
- return NULL;
- }
-
- new_kprobe->event = strdup(event);
- new_kprobe->function = strdup(function);
- new_kprobe->probe = strdup(probe);
- if (!new_kprobe->event ||
- !new_kprobe->function ||
- !new_kprobe->probe) {
- MEM_ERROR;
- ftracepy_kprobe_free(new_kprobe);
-
- return NULL;
- }
-
- return new_kprobe;
+ type = tracefs_dynevent_info(self->ptrObj, NULL, NULL, NULL, NULL, &buff);
+ return dynevent_info2py(buff, type);
}
PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
@@ -1786,7 +1724,7 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
{
static char *kwlist[] = {"event", "function", "probe", NULL};
const char *event, *function, *probe;
- struct ftracepy_kprobe *kprobe;
+ struct tracefs_dynevent *kprobe;
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
@@ -1798,11 +1736,19 @@ PyObject *PyFtrace_register_kprobe(PyObject *self, PyObject *args,
return NULL;
}
- kprobe = kprobe_new(event, function, probe, false);
- if (!kprobe)
+ kprobe = tracefs_kprobe_alloc(TC_SYS, event, function, probe);
+ if (!kprobe) {
+ MEM_ERROR;
return NULL;
+ }
+
+ if (tracefs_dynevent_create(kprobe) < 0) {
+ TfsError_fmt(NULL, "Failed to create kprobe '%s'", event);
+ tracefs_dynevent_free(kprobe);
+ return NULL;
+ }
- return PyKprobe_New(kprobe);
+ return PyDynevent_New(kprobe);
}
PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
@@ -1810,7 +1756,7 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
{
static char *kwlist[] = {"event", "function", "probe", NULL};
const char *event, *function, *probe = "$retval";
- struct ftracepy_kprobe *kprobe;
+ struct tracefs_dynevent *kprobe;
if (!PyArg_ParseTupleAndKeywords(args,
kwargs,
@@ -1822,20 +1768,29 @@ PyObject *PyFtrace_register_kretprobe(PyObject *self, PyObject *args,
return NULL;
}
- kprobe = kprobe_new(event, function, probe, true);
- if (!kprobe)
+ kprobe = tracefs_kretprobe_alloc(TC_SYS, event, function, probe, 0);
+ if (!kprobe) {
+ MEM_ERROR;
+ return NULL;
+ }
+
+ if (tracefs_dynevent_create(kprobe) < 0) {
+ TfsError_fmt(NULL, "Failed to create kretprobe '%s'", event);
+ tracefs_dynevent_free(kprobe);
return NULL;
+ }
- return PyKprobe_New(kprobe);
+ return PyDynevent_New(kprobe);
}
-PyObject *PyKprobe_set_filter(PyKprobe *self, PyObject *args,
- PyObject *kwargs)
+PyObject *PyDynevent_set_filter(PyDynevent *self, PyObject *args,
+ PyObject *kwargs)
{
struct tracefs_instance *instance;
PyObject *py_inst = NULL;
+ struct tep_handle * tep;
+ struct tep_event *event;
const char *filter;
- char path[PATH_MAX];
static char *kwlist[] = {"filter", "instance", NULL};
if (!PyArg_ParseTupleAndKeywords(args,
@@ -1850,72 +1805,153 @@ PyObject *PyKprobe_set_filter(PyKprobe *self, PyObject *args,
if (!get_optional_instance(py_inst, &instance))
return NULL;
- sprintf(path, "events/%s/%s/filter", TC_SYS, self->ptrObj->event);
- if (!write_to_file_and_check(instance, path, filter)) {
- TfsError_setstr(instance, "Failed to set kprobe filter.");
+ tep = tracefs_local_events(NULL);
+ if (!tep) {
+ TfsError_setstr(NULL, "Failed to get local events.");
+ return NULL;
+ }
+
+ event = tracefs_dynevent_get_event(tep, self->ptrObj);
+ if (!event) {
+ TfsError_setstr(NULL, "Failed to get event.");
+ return NULL;
+ }
+
+ if (tracefs_event_apply_filter(instance, event, filter) < 0) {
+ TfsError_fmt(NULL, "Failed to apply filter '%s' to event '%s'.",
+ filter, event->name);
return NULL;
}
Py_RETURN_NONE;
}
-PyObject *PyKprobe_clear_filter(PyKprobe *self, PyObject *args,
- PyObject *kwargs)
+PyObject *PyDynevent_get_filter(PyDynevent *self, PyObject *args,
+ PyObject *kwargs)
{
+ char *evt_name, *evt_system, *filter = NULL;
struct tracefs_instance *instance;
+ PyObject *ret = NULL;
char path[PATH_MAX];
+ int type;
if (!get_instance_from_arg(args, kwargs, &instance))
return NULL;
- sprintf(path, "events/%s/%s/filter", TC_SYS, self->ptrObj->event);
- if (!write_to_file(instance, path, OFF)) {
- TfsError_setstr(instance, "Failed to clear kprobe filter.");
+ type = tracefs_dynevent_info(self->ptrObj, &evt_system, &evt_name,
+ NULL, NULL, NULL);
+ if (type == TRACEFS_DYNEVENT_UNKNOWN) {
+ PyErr_SetString(TFS_ERROR, "Failed to get dynevent info.");
+ return NULL;
+ }
+
+ sprintf(path, "events/%s/%s/filter", evt_system, evt_name);
+ if (read_from_file(instance, path, &filter) <= 0)
+ goto free;
+
+ trim_new_line(filter);
+ ret = PyUnicode_FromString(filter);
+ free:
+ free(evt_system);
+ free(evt_name);
+ free(filter);
+
+ return ret;
+}
+
+PyObject *PyDynevent_clear_filter(PyDynevent *self, PyObject *args,
+ PyObject *kwargs)
+{
+ struct tracefs_instance *instance;
+ struct tep_handle * tep;
+ struct tep_event *event;
+
+ if (!get_instance_from_arg(args, kwargs, &instance))
+ return NULL;
+
+ tep = tracefs_local_events(NULL);
+ if (!tep) {
+ TfsError_setstr(NULL, "Failed to get local events.");
+ return NULL;
+ }
+
+ event = tracefs_dynevent_get_event(tep, self->ptrObj);
+ if (!event) {
+ TfsError_setstr(NULL, "Failed to get event.");
+ return NULL;
+ }
+
+ if (tracefs_event_clear_filter(instance, event) < 0) {
+ TfsError_fmt(NULL, "Failed to clear filter for event '%s'.",
+ event->name);
return NULL;
}
Py_RETURN_NONE;
}
-static bool enable_kprobe(PyKprobe *self, PyObject *args, PyObject *kwargs,
+static bool enable_dynevent(PyDynevent *self, PyObject *args, PyObject *kwargs,
bool enable)
{
struct tracefs_instance *instance;
+ char * evt_name;
+ int type;
+ bool ret;
if (!get_instance_from_arg(args, kwargs, &instance))
return false;
- return event_enable_disable(instance, TC_SYS, self->ptrObj->event,
- enable);
+ type = tracefs_dynevent_info(self->ptrObj, NULL, &evt_name, NULL, NULL, NULL);
+ if (type == TRACEFS_DYNEVENT_UNKNOWN) {
+ PyErr_SetString(TFS_ERROR, "Failed to get dynevent info.");
+ return NULL;
+ }
+
+ ret = event_enable_disable(instance, TC_SYS, evt_name, enable);
+ free(evt_name);
+
+ return ret;
}
-PyObject *PyKprobe_enable(PyKprobe *self, PyObject *args,
- PyObject *kwargs)
+PyObject *PyDynevent_enable(PyDynevent *self, PyObject *args,
+ PyObject *kwargs)
{
- if (!enable_kprobe(self, args, kwargs, true))
+ if (!enable_dynevent(self, args, kwargs, true))
return NULL;
Py_RETURN_NONE;
}
-PyObject *PyKprobe_disable(PyKprobe *self, PyObject *args,
- PyObject *kwargs)
+PyObject *PyDynevent_disable(PyDynevent *self, PyObject *args,
+ PyObject *kwargs)
{
- if (!enable_kprobe(self, args, kwargs, false))
+ if (!enable_dynevent(self, args, kwargs, false))
return NULL;
Py_RETURN_NONE;
}
-PyObject *PyKprobe_is_enabled(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_is_enabled(PyDynevent *self, PyObject *args,
PyObject *kwargs)
{
struct tracefs_instance *instance;
+ char * evt_name;
+ PyObject *ret;
+ int type;
if (!get_instance_from_arg(args, kwargs, &instance))
return NULL;
- return event_is_enabled(instance, TC_SYS, self->ptrObj->event);
+ type = tracefs_dynevent_info(self->ptrObj, NULL, &evt_name, NULL, NULL, NULL);
+ if (type == TRACEFS_DYNEVENT_UNKNOWN) {
+ PyErr_SetString(TFS_ERROR, "Failed to get dynevent info.");
+ return NULL;
+ }
+
+ ret = event_is_enabled(instance, TC_SYS, evt_name);
+ free(evt_name);
+
+ return ret;
}
PyObject *PyFtrace_set_ftrace_loglevel(PyObject *self, PyObject *args,
@@ -24,13 +24,9 @@ C_OBJECT_WRAPPER_DECLARE(tep_handle, PyTep)
C_OBJECT_WRAPPER_DECLARE(tracefs_instance, PyTfsInstance)
-struct ftracepy_kprobe;
+struct tracefs_dynevent;
-int ftracepy_kprobe_destroy(struct ftracepy_kprobe *kp);
-
-void ftracepy_kprobe_free(struct ftracepy_kprobe *kp);
-
-C_OBJECT_WRAPPER_DECLARE(ftracepy_kprobe, PyKprobe);
+C_OBJECT_WRAPPER_DECLARE(tracefs_dynevent, PyDynevent);
PyObject *PyTepRecord_time(PyTepRecord* self);
@@ -68,27 +64,30 @@ PyObject *PyTep_short_kprobe_print(PyTep *self, PyObject *args,
PyObject *PyTfsInstance_dir(PyTfsInstance *self);
-PyObject *PyKprobe_event(PyKprobe *self);
+PyObject *PyDynevent_event(PyDynevent *self);
-PyObject *PyKprobe_system(PyKprobe *self);
+PyObject *PyDynevent_system(PyDynevent *self);
-PyObject *PyKprobe_function(PyKprobe *self);
+PyObject *PyDynevent_address(PyDynevent *self);
-PyObject *PyKprobe_probe(PyKprobe *self);
+PyObject *PyDynevent_probe(PyDynevent *self);
-PyObject *PyKprobe_set_filter(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_set_filter(PyDynevent *self, PyObject *args,
PyObject *kwargs);
-PyObject *PyKprobe_clear_filter(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_get_filter(PyDynevent *self, PyObject *args,
+ PyObject *kwargs);
+
+PyObject *PyDynevent_clear_filter(PyDynevent *self, PyObject *args,
PyObject *kwargs);
-PyObject *PyKprobe_enable(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_enable(PyDynevent *self, PyObject *args,
PyObject *kwargs);
-PyObject *PyKprobe_disable(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_disable(PyDynevent *self, PyObject *args,
PyObject *kwargs);
-PyObject *PyKprobe_is_enabled(PyKprobe *self, PyObject *args,
+PyObject *PyDynevent_is_enabled(PyDynevent *self, PyObject *args,
PyObject *kwargs);
PyObject *PyFtrace_dir(PyObject *self);
@@ -106,58 +106,67 @@ C_OBJECT_WRAPPER(tracefs_instance, PyTfsInstance,
tracefs_instance_destroy,
tracefs_instance_free)
-static PyMethodDef PyKprobe_methods[] = {
+static PyMethodDef PyDynevent_methods[] = {
{"event",
- (PyCFunction) PyKprobe_event,
+ (PyCFunction) PyDynevent_event,
METH_NOARGS,
- "Get the name of the kprobe event."
+ "Get the name of the dynamic event."
},
{"system",
- (PyCFunction) PyKprobe_system,
+ (PyCFunction) PyDynevent_system,
METH_NOARGS,
- "Get the system name of the kprobe event."
+ "Get the system name of the dynamic event."
},
- {"function",
- (PyCFunction) PyKprobe_function,
+ {"address",
+ (PyCFunction) PyDynevent_address,
METH_NOARGS,
- "Get the function name of the kprobe event."
+ "Get the address / function name of the dynamic event."
},
{"probe",
- (PyCFunction) PyKprobe_probe,
+ (PyCFunction) PyDynevent_probe,
METH_NOARGS,
- "Get the kprobe event definition."
+ "Get the event definition."
},
{"set_filter",
- (PyCFunction) PyKprobe_set_filter,
+ (PyCFunction) PyDynevent_set_filter,
METH_VARARGS | METH_KEYWORDS,
- "Define a filter for a kprobe."
+ "Define a filter for a dynamic event."
+ },
+ {"get_filter",
+ (PyCFunction) PyDynevent_get_filter,
+ METH_VARARGS | METH_KEYWORDS,
+ "Get the filter of a dynamic event."
},
{"clear_filter",
- (PyCFunction) PyKprobe_clear_filter,
+ (PyCFunction) PyDynevent_clear_filter,
METH_VARARGS | METH_KEYWORDS,
- "Clear the filter of a kprobe."
+ "Clear the filter of a dynamic event."
},
{"enable",
- (PyCFunction) PyKprobe_enable,
+ (PyCFunction) PyDynevent_enable,
METH_VARARGS | METH_KEYWORDS,
- "Enable kprobe event."
+ "Enable dynamic event."
},
{"disable",
- (PyCFunction) PyKprobe_disable,
+ (PyCFunction) PyDynevent_disable,
METH_VARARGS | METH_KEYWORDS,
- "Disable kprobe event."
+ "Disable dynamic event."
},
{"is_enabled",
- (PyCFunction) PyKprobe_is_enabled,
+ (PyCFunction) PyDynevent_is_enabled,
METH_VARARGS | METH_KEYWORDS,
- "Check if kprobe event is enabled."
+ "Check if dynamic event is enabled."
},
{NULL, NULL, 0, NULL}
};
-C_OBJECT_WRAPPER(ftracepy_kprobe, PyKprobe,
- ftracepy_kprobe_destroy,
- ftracepy_kprobe_free)
+static int dynevent_destroy(struct tracefs_dynevent *devt)
+{
+ return tracefs_dynevent_destroy(devt, true);
+}
+C_OBJECT_WRAPPER(tracefs_dynevent, PyDynevent,
+ dynevent_destroy,
+ tracefs_dynevent_free)
static PyMethodDef ftracepy_methods[] = {
{"dir",
@@ -375,7 +384,7 @@ PyMODINIT_FUNC PyInit_ftracepy(void)
if (!PyTfsInstanceTypeInit())
return NULL;
- if (!PyKprobeTypeInit())
+ if (!PyDyneventTypeInit())
return NULL;
TFS_ERROR = PyErr_NewException("tracecruncher.ftracepy.tfs_error",
@@ -393,7 +402,8 @@ PyMODINIT_FUNC PyInit_ftracepy(void)
PyModule_AddObject(module, "tep_event", (PyObject *) &PyTepEventType);
PyModule_AddObject(module, "tep_record", (PyObject *) &PyTepRecordType);
PyModule_AddObject(module, "tracefs_instance", (PyObject *) &PyTfsInstanceType);
- PyModule_AddObject(module, "ftracepy_kprobe", (PyObject *) &PyKprobeType);
+ PyModule_AddObject(module, "tracefs_dynevent", (PyObject *) &PyDyneventType);
+
PyModule_AddObject(module, "tfs_error", TFS_ERROR);
PyModule_AddObject(module, "tep_error", TEP_ERROR);
@@ -414,15 +414,31 @@ class KprobeTestCase(unittest.TestCase):
kp1 = ft.register_kprobe(event=evt1, function=evt1_func,
probe=evt1_prove)
self.assertEqual(evt1, kp1.event())
- self.assertEqual(evt1_func, kp1.function())
+ self.assertEqual(evt1_func, kp1.address())
self.assertEqual(evt1_prove, kp1.probe())
kp2 = ft.register_kprobe(event=evt2, function=evt2_func,
probe=evt2_prove)
self.assertEqual(evt2, kp2.event())
- self.assertEqual(evt2_func, kp2.function())
+ self.assertEqual(evt2_func, kp2.address())
self.assertEqual(evt2_prove, kp2.probe())
+ def test_filter_kprobe(self):
+ evt1 = 'mkdir'
+ evt1_func = 'do_mkdirat'
+ evt1_prove = 'path=+u0($arg2):ustring'
+ flt = 'path~\'/sys/fs/cgroup/*\''
+
+ kp1 = ft.register_kprobe(event=evt1, function=evt1_func,
+ probe=evt1_prove)
+ inst = ft.create_instance(instance_name)
+
+ kp1.set_filter(instance=inst, filter=flt)
+ flt_get = kp1.get_filter(instance=inst)
+ self.assertEqual(flt, flt_get)
+ kp1.clear_filter(instance=inst)
+ flt_get = kp1.get_filter(instance=inst)
+ self.assertEqual(flt_get, 'none')
def test_enable_kprobe(self):
evt1 = 'mkdir'
@@ -45,7 +45,8 @@ class InstanceTestCase(unittest.TestCase):
instance_name = 'test_instance'
inst = ft.create_instance(instance_name)
systems = ft.available_event_systems(instance=inst)
- systems.remove('ftrace')
+ if 'ftrace' in systems:
+ systems.remove('ftrace')
for s in systems:
ret = ft.event_is_enabled(instance=inst,
system=s)
Trace-cruncher currently uses some untagged libtracefs APIs - in particular the APIs for dealing with kprobes. Those libtracefs APIs have been modified recently, so here we port those changes into trace-cruncher. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@gmail.com> --- src/ftracepy-utils.c | 278 ++++++++++-------- src/ftracepy-utils.h | 29 +- src/ftracepy.c | 60 ++-- .../tests/1_unit/test_01_ftracepy_unit.py | 20 +- .../test_01_ftracepy_integration.py | 3 +- 5 files changed, 226 insertions(+), 164 deletions(-)