From f17701fb89c69c3950c22a0c20d0233092e7d6ed Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 18 May 2011 22:05:24 -0400 Subject: [PATCH] Add event description for each kprobe event Signed-off-by: Mathieu Desnoyers --- ltt-debugfs-abi.h | 8 +++- ltt-events.c | 26 ++++-------- ltt-events.h | 11 +++-- probes/lttng-kprobes.c | 94 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 112 insertions(+), 27 deletions(-) diff --git a/ltt-debugfs-abi.h b/ltt-debugfs-abi.h index ecbd5413..411c37b7 100644 --- a/ltt-debugfs-abi.h +++ b/ltt-debugfs-abi.h @@ -16,6 +16,7 @@ enum lttng_kernel_instrumentation { LTTNG_KERNEL_TRACEPOINTS, LTTNG_KERNEL_KPROBES, + LTTNG_KERNEL_FUNCTION_TRACER, }; /* @@ -40,13 +41,18 @@ struct lttng_kernel_kprobe { char symbol_name[LTTNG_KPROBE_SYM_NAME_LEN]; }; +struct lttng_kernel_function_tracer { + char symbol_name[LTTNG_KPROBE_SYM_NAME_LEN]; +}; + struct lttng_kernel_event { enum lttng_kernel_instrumentation instrumentation; /* Per instrumentation type configuration */ union { struct lttng_kernel_kprobe kprobe; + struct lttng_kernel_function_tracer ftrace; } u; - char name[]; + char name[]; /* event name */ }; struct lttng_kernel_tracer_version { diff --git a/ltt-events.c b/ltt-events.c index ec5d6830..29d0ed74 100644 --- a/ltt-events.c +++ b/ltt-events.c @@ -237,24 +237,13 @@ struct ltt_event *ltt_event_create(struct ltt_channel *chan, char *name, goto register_error; break; case LTTNG_KERNEL_KPROBES: - event->u.kprobe.kp.pre_handler = lttng_kprobes_handler_pre; - event->u.kprobe.symbol_name = - kzalloc(LTTNG_KPROBE_SYM_NAME_LEN * sizeof(char), - GFP_KERNEL); - if (!event->u.kprobe.symbol_name) - goto register_error; - memcpy(event->u.kprobe.symbol_name, - event_param->u.kprobe.symbol_name, - LTTNG_KPROBE_SYM_NAME_LEN * sizeof(char)); - event->u.kprobe.kp.symbol_name = - event->u.kprobe.symbol_name; - event->u.kprobe.kp.offset = event_param->u.kprobe.offset; - event->u.kprobe.kp.addr = (void *) event_param->u.kprobe.addr; - ret = register_kprobe(&event->u.kprobe.kp); - if (ret) { - kfree(event->u.kprobe.symbol_name); + ret = lttng_kprobes_register(name, + event_param->u.kprobe.symbol_name, + event_param->u.kprobe.offset, + event_param->u.kprobe.addr, + event); + if (ret) goto register_error; - } break; default: WARN_ON_ONCE(1); @@ -294,8 +283,7 @@ int _ltt_event_unregister(struct ltt_event *event) return ret; break; case LTTNG_KERNEL_KPROBES: - unregister_kprobe(&event->u.kprobe.kp); - kfree(event->u.kprobe.symbol_name); + lttng_kprobes_unregister(event); ret = 0; break; default: diff --git a/ltt-events.h b/ltt-events.h index 42e12c0a..a26638c4 100644 --- a/ltt-events.h +++ b/ltt-events.h @@ -104,7 +104,7 @@ struct lttng_enum { struct lttng_event_field { const char *name; - const struct lttng_type type; + struct lttng_type type; }; struct lttng_event_desc { @@ -127,7 +127,7 @@ struct lttng_probe_desc { struct ltt_event { unsigned int id; struct ltt_channel *chan; - const struct lttng_event_desc *desc; + struct lttng_event_desc *desc; void *filter; enum lttng_kernel_instrumentation instrumentation; union { @@ -234,6 +234,11 @@ void ltt_event_put(const struct lttng_event_desc *desc); int ltt_probes_init(void); void ltt_probes_exit(void); -void lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs); +int lttng_kprobes_register(const char *name, + const char *symbol_name, + uint64_t offset, + uint64_t addr, + struct ltt_event *event); +void lttng_kprobes_unregister(struct ltt_event *event); #endif /* _LTT_EVENTS_H */ diff --git a/probes/lttng-kprobes.c b/probes/lttng-kprobes.c index eb6e16a0..bee935f7 100644 --- a/probes/lttng-kprobes.c +++ b/probes/lttng-kprobes.c @@ -9,11 +9,13 @@ #include #include +#include #include "../ltt-events.h" #include "../wrapper/ringbuffer/frontend_types.h" #include "../ltt-tracer.h" -void lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs) +static +int lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs) { struct ltt_event *event = container_of(p, struct ltt_event, u.kprobe.kp); @@ -23,17 +25,101 @@ void lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs) unsigned long data = (unsigned long) p->addr; if (!ACCESS_ONCE(chan->session->active)) - return; + return 0; lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, sizeof(data), ltt_alignof(data), -1); ret = chan->ops->event_reserve(&ctx); if (ret < 0) - return; + return 0; lib_ring_buffer_align_ctx(&ctx, ltt_alignof(data)); chan->ops->event_write(&ctx, &data, sizeof(data)); chan->ops->event_commit(&ctx); + return 0; } -EXPORT_SYMBOL_GPL(lttng_kprobes_handler_pre); + +/* + * Create event description + */ +static +int lttng_create_kprobe_event(const char *name, struct ltt_event *event) +{ + struct lttng_event_field *field; + int ret; + + event->desc = kzalloc(sizeof(*event->desc), GFP_KERNEL); + if (!event->desc) + return -ENOMEM; + event->desc->name = kstrdup(name, GFP_KERNEL); + if (!event->desc->name) { + ret = -ENOMEM; + goto error_str; + } + event->desc->nr_fields = 1; + event->desc->fields = field = + kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL); + field->name = "ip"; + field->type.atype = atype_integer; + field->type.u.basic.integer.size = sizeof(unsigned long); + field->type.u.basic.integer.alignment = ltt_alignof(unsigned long); + field->type.u.basic.integer.signedness = 0; + field->type.u.basic.integer.reverse_byte_order = 0; + + return 0; + +error_str: + kfree(event->desc); + return ret; +} + +int lttng_kprobes_register(const char *name, + const char *symbol_name, + uint64_t offset, + uint64_t addr, + struct ltt_event *event) +{ + int ret; + + ret = lttng_create_kprobe_event(name, event); + if (ret) + goto error; + memset(&event->u.kprobe.kp, 0, sizeof(event->u.kprobe.kp)); + event->u.kprobe.kp.pre_handler = lttng_kprobes_handler_pre; + event->u.kprobe.symbol_name = + kzalloc(LTTNG_KPROBE_SYM_NAME_LEN * sizeof(char), + GFP_KERNEL); + if (!event->u.kprobe.symbol_name) { + ret = -ENOMEM; + goto name_error; + } + memcpy(event->u.kprobe.symbol_name, symbol_name, + LTTNG_KPROBE_SYM_NAME_LEN * sizeof(char)); + event->u.kprobe.kp.symbol_name = + event->u.kprobe.symbol_name; + event->u.kprobe.kp.offset = offset; + event->u.kprobe.kp.addr = (void *) addr; + ret = register_kprobe(&event->u.kprobe.kp); + if (ret) + goto register_error; + return 0; + +register_error: + kfree(event->u.kprobe.symbol_name); +name_error: + kfree(event->desc->name); + kfree(event->desc); +error: + return ret; +} +EXPORT_SYMBOL_GPL(lttng_kprobes_register); + +void lttng_kprobes_unregister(struct ltt_event *event) +{ + unregister_kprobe(&event->u.kprobe.kp); + kfree(event->u.kprobe.symbol_name); + kfree(event->desc->name); + kfree(event->desc); +} +EXPORT_SYMBOL_GPL(lttng_kprobes_unregister); MODULE_LICENSE("GPL and additional rights"); MODULE_AUTHOR("Mathieu Desnoyers"); -- 2.34.1