The new methods makes it easy to print: - the name and PID of the process that generated the trace record, - the unique fields of the record (called also 'info') or - all information for the event all together. Signed-off-by: Yordan Karadzhov (VMware) <y.karadz@xxxxxxxxx> --- examples/kprobe_open.py | 8 +- src/ftracepy-utils.c | 159 ++++++++++++++++++++++++++++++++++++++++ src/ftracepy-utils.h | 9 +++ src/ftracepy.c | 15 ++++ 4 files changed, 186 insertions(+), 5 deletions(-) diff --git a/examples/kprobe_open.py b/examples/kprobe_open.py index f8d4d8b..5b217d3 100755 --- a/examples/kprobe_open.py +++ b/examples/kprobe_open.py @@ -26,12 +26,10 @@ open_probe.add_ptr_arg(name='mode', open_probe.register() +tep = tc.local_tep() + def callback(event, record): - if event.id() == open_probe.id(): - file_name = event.parse_record_field(record=record, field='file') - flags = event.parse_record_field(record, 'flags') - mode = event.parse_record_field(record, 'mode') - print('file: {0} (flags: {1}; mode: {2})'.format(file_name, hex(flags), hex(mode))) + print(tep.info(event, record)) if __name__ == "__main__": diff --git a/src/ftracepy-utils.c b/src/ftracepy-utils.c index 6739db7..3c000a7 100644 --- a/src/ftracepy-utils.c +++ b/src/ftracepy-utils.c @@ -298,6 +298,162 @@ PyObject *PyTep_get_event(PyTep *self, PyObject *args, return PyTepEvent_New(event); } +static struct trace_seq seq; + +static bool init_print_seq(void) +{ + if (!seq.buffer) + trace_seq_init(&seq); + + if (!seq.buffer) { + PyErr_SetString(TFS_ERROR, "Unable to initialize 'trace_seq'."); + return false; + } + + trace_seq_reset(&seq); + + return true; +} + +static char *get_comm_from_pid(int pid) +{ + char *comm_file, *comm = NULL; + char buff[PATH_MAX]; + int fd, r; + + if (asprintf(&comm_file, "/proc/%i/comm", pid) <= 0) { + MEM_ERROR; + return NULL; + } + + /* + * This file is not guaranteed to exist. Return NULL if the process + * is no longer active. + */ + fd = open(comm_file, O_RDONLY); + free(comm_file); + if (fd < 0) + return NULL; + + r = read(fd, buff, PATH_MAX); + close(fd); + if (r <= 0) + return NULL; + + comm = strdup(buff); + if (!comm) + MEM_ERROR; + + return comm; +} + +static void print_comm_pid(struct tep_handle *tep, + struct trace_seq *seq, + struct tep_record *record, + struct tep_event *event) +{ + int pid = get_pid(event, record); + if (!tep_is_pid_registered(tep, pid)) { + char *comm = get_comm_from_pid(pid); + if (comm) { + tep_register_comm(tep, comm, pid); + free(comm); + } + } + + tep_print_event(tep, seq, record, "%s-%i", + TEP_PRINT_COMM, + TEP_PRINT_PID); +} + +static void print_name_info(struct tep_handle *tep, + struct trace_seq *seq, + struct tep_record *record, + struct tep_event *event) +{ + trace_seq_printf(seq, " %s: ", event->name); + tep_print_event(tep, seq, record, "%s", TEP_PRINT_INFO); +} + +static void print_event(struct tep_handle *tep, + struct trace_seq *seq, + struct tep_record *record, + struct tep_event *event) +{ + tep_print_event(tep, seq, record, "%6.1000d ", TEP_PRINT_TIME); + print_comm_pid(tep, seq, record, event); + tep_print_event(tep, seq, record, " cpu=%i ", TEP_PRINT_CPU); + print_name_info(tep, seq, record, event); +} + +static bool print_init(PyObject *args, PyObject *kwargs, + struct tep_event **event, + struct tep_record **record) +{ + static char *kwlist[] = { "event", "record", NULL}; + PyTepRecord *py_record; + PyTepEvent *py_event; + + if (!init_print_seq()) + return false; + + if(!PyArg_ParseTupleAndKeywords(args, + kwargs, + "OO", + kwlist, + &py_event, + &py_record)) { + return false; + } + + *event = py_event->ptrObj; + *record = py_record->ptrObj; + + return true; +} + +PyObject *PyTep_event_record(PyTep *self, PyObject *args, + PyObject *kwargs) +{ + struct tep_record *record; + struct tep_event *event; + + if (!print_init(args, kwargs, &event, &record)) + return NULL; + + print_event(self->ptrObj, &seq, record, event); + + return PyUnicode_FromString(seq.buffer); +} + +PyObject *PyTep_info(PyTep *self, PyObject *args, + PyObject *kwargs) +{ + struct tep_record *record; + struct tep_event *event; + + if (!print_init(args, kwargs, &event, &record)) + return NULL; + + print_name_info(self->ptrObj, &seq, record, event); + + return PyUnicode_FromString(seq.buffer); +} + +PyObject *PyTep_process(PyTep *self, PyObject *args, + PyObject *kwargs) +{ + struct tep_record *record; + struct tep_event *event; + + if (!print_init(args, kwargs, &event, &record)) + return NULL; + + print_comm_pid(self->ptrObj, &seq, record, event); + + return PyUnicode_FromString(seq.buffer); +} + static bool check_file(struct tracefs_instance *instance, const char *file) { if (!tracefs_file_exists(instance, file)) { @@ -2222,4 +2378,7 @@ void PyFtrace_at_exit(void) { destroy_all_kprobes(); destroy_all_instances(); + + if (seq.buffer) + trace_seq_destroy(&seq); } diff --git a/src/ftracepy-utils.h b/src/ftracepy-utils.h index 5d7c19c..aca1ccc 100644 --- a/src/ftracepy-utils.h +++ b/src/ftracepy-utils.h @@ -44,6 +44,15 @@ PyObject *PyTep_init_local(PyTep *self, PyObject *args, PyObject *PyTep_get_event(PyTep *self, PyObject *args, PyObject *kwargs); +PyObject *PyTep_event_record(PyTep *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyTep_info(PyTep *self, PyObject *args, + PyObject *kwargs); + +PyObject *PyTep_process(PyTep *self, PyObject *args, + PyObject *kwargs); + PyObject *PyFtrace_dir(PyObject *self); PyObject *PyFtrace_create_instance(PyObject *self, PyObject *args, diff --git a/src/ftracepy.c b/src/ftracepy.c index e3fec7b..e948b15 100644 --- a/src/ftracepy.c +++ b/src/ftracepy.c @@ -68,6 +68,21 @@ static PyMethodDef PyTep_methods[] = { METH_VARARGS | METH_KEYWORDS, "Get a PyTepEvent object." }, + {"event_record", + (PyCFunction) PyTep_event_record, + METH_VARARGS | METH_KEYWORDS, + "Generic print of a trace event." + }, + {"process", + (PyCFunction) PyTep_process, + METH_VARARGS | METH_KEYWORDS, + "Generic print of the process that generated the trace event." + }, + {"info", + (PyCFunction) PyTep_info, + METH_VARARGS | METH_KEYWORDS, + "Generic print of a trace event info." + }, {NULL} }; -- 2.30.2