X-Git-Url: https://git.lttng.org/?p=lttng-modules.git;a=blobdiff_plain;f=src%2Fprobes%2Flttng-kretprobes.c;h=2677f8ab8abe77ce35adcf44a322a0df53546b76;hp=25bdec90ef52b90d6bde748a9d66e7704fc762ee;hb=8a57ec025ffbe56153748fd69b60118862707182;hpb=12bb2edb6ed3e96d3299a979e49b828f2b17dcb2 diff --git a/src/probes/lttng-kretprobes.c b/src/probes/lttng-kretprobes.c index 25bdec90..2677f8ab 100644 --- a/src/probes/lttng-kretprobes.c +++ b/src/probes/lttng-kretprobes.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,7 @@ enum lttng_kretprobe_type { struct lttng_krp { struct kretprobe krp; - struct lttng_event *event[2]; /* ENTRY and EXIT */ + struct lttng_kernel_event_common *event[2]; /* ENTRY and EXIT */ struct kref kref_register; struct kref kref_alloc; }; @@ -37,38 +38,63 @@ int _lttng_kretprobes_handler(struct kretprobe_instance *krpi, { struct lttng_krp *lttng_krp = container_of(lttng_get_kretprobe(krpi), struct lttng_krp, krp); - struct lttng_event *event = - lttng_krp->event[type]; - struct lttng_probe_ctx lttng_probe_ctx = { + struct lttng_kernel_event_common *event = lttng_krp->event[type]; + struct lttng_kernel_probe_ctx lttng_probe_ctx = { .event = event, .interruptible = !lttng_regs_irqs_disabled(regs), }; - struct lttng_channel *chan = event->chan; - struct lib_ring_buffer_ctx ctx; - int ret; struct { unsigned long ip; unsigned long parent_ip; } payload; - if (unlikely(!LTTNG_READ_ONCE(chan->session->active))) - return 0; - if (unlikely(!LTTNG_READ_ONCE(chan->enabled))) - return 0; + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + { + struct lttng_kernel_event_recorder *event_recorder = + container_of(event, struct lttng_kernel_event_recorder, parent); + struct lttng_channel *chan = event_recorder->chan; + + if (unlikely(!LTTNG_READ_ONCE(chan->session->active))) + return 0; + if (unlikely(!LTTNG_READ_ONCE(chan->enabled))) + return 0; + break; + } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: /* Fall-through. */ + default: + WARN_ON_ONCE(1); + } + if (unlikely(!LTTNG_READ_ONCE(event->enabled))) return 0; - payload.ip = (unsigned long) lttng_get_kretprobe(krpi)->kp.addr; - payload.parent_ip = (unsigned long) krpi->ret_addr; + switch (event->type) { + case LTTNG_KERNEL_EVENT_TYPE_RECORDER: + { + struct lttng_kernel_event_recorder *event_recorder = + container_of(event, struct lttng_kernel_event_recorder, parent); + struct lttng_channel *chan = event_recorder->chan; + struct lttng_kernel_ring_buffer_ctx ctx; + int ret; - lib_ring_buffer_ctx_init(&ctx, chan->chan, <tng_probe_ctx, sizeof(payload), - lttng_alignof(payload), -1); - ret = chan->ops->event_reserve(&ctx, event->id); - if (ret < 0) - return 0; - lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload)); - chan->ops->event_write(&ctx, &payload, sizeof(payload)); - chan->ops->event_commit(&ctx); + payload.ip = (unsigned long) lttng_get_kretprobe(krpi)->kp.addr; + payload.parent_ip = (unsigned long) krpi->ret_addr; + + lib_ring_buffer_ctx_init(&ctx, event_recorder, sizeof(payload), + lttng_alignof(payload), <tng_probe_ctx); + ret = chan->ops->event_reserve(&ctx); + if (ret < 0) + return 0; + lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload)); + chan->ops->event_write(&ctx, &payload, sizeof(payload)); + chan->ops->event_commit(&ctx); + break; + } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: /* Fall-through. */ + default: + WARN_ON_ONCE(1); + } return 0; } @@ -86,21 +112,25 @@ int lttng_kretprobes_handler_exit(struct kretprobe_instance *krpi, return _lttng_kretprobes_handler(krpi, regs, EVENT_EXIT); } +static const struct lttng_kernel_type_common *event_type = + lttng_kernel_static_type_integer_from_type(unsigned long, __BYTE_ORDER, 16); + /* * Create event description */ static -int lttng_create_kprobe_event(const char *name, struct lttng_event *event, +int lttng_create_kprobe_event(const char *name, struct lttng_kernel_event_recorder *event_recorder, enum lttng_kretprobe_type type) { - struct lttng_event_field *fields; - struct lttng_event_desc *desc; - int ret; + const struct lttng_kernel_event_field **fieldp_array; + struct lttng_kernel_event_field *field; + struct lttng_kernel_event_desc *desc; char *alloc_name; size_t name_len; const char *suffix = NULL; + int ret; - desc = kzalloc(sizeof(*event->desc), GFP_KERNEL); + desc = kzalloc(sizeof(*desc), GFP_KERNEL); if (!desc) return -ENOMEM; name_len = strlen(name); @@ -120,39 +150,44 @@ int lttng_create_kprobe_event(const char *name, struct lttng_event *event, } strcpy(alloc_name, name); strcat(alloc_name, suffix); - desc->name = alloc_name; + desc->event_name = alloc_name; desc->nr_fields = 2; - desc->fields = fields = - kzalloc(2 * sizeof(struct lttng_event_field), GFP_KERNEL); - if (!desc->fields) { + fieldp_array = kzalloc(desc->nr_fields * sizeof(struct lttng_kernel_event_field *), GFP_KERNEL); + if (!fieldp_array) { + ret = -ENOMEM; + goto error_fieldp_array; + } + desc->fields = fieldp_array; + + field = kzalloc(sizeof(struct lttng_kernel_event_field), GFP_KERNEL); + if (!field) { + ret = -ENOMEM; + goto error_field0; + } + field->name = "ip"; + field->type = event_type; + desc->fields[0] = field; + + field = kzalloc(sizeof(struct lttng_kernel_event_field), GFP_KERNEL); + if (!field) { ret = -ENOMEM; - goto error_fields; + goto error_field1; } - fields[0].name = "ip"; - fields[0].type.type = lttng_kernel_type_integer; - fields[0].type.u.integer.size = sizeof(unsigned long) * CHAR_BIT; - fields[0].type.u.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; - fields[0].type.u.integer.signedness = lttng_is_signed_type(unsigned long); - fields[0].type.u.integer.reverse_byte_order = 0; - fields[0].type.u.integer.base = 16; - fields[0].type.u.integer.encoding = lttng_encode_none; - - fields[1].name = "parent_ip"; - fields[1].type.type = lttng_kernel_type_integer; - fields[1].type.u.integer.size = sizeof(unsigned long) * CHAR_BIT; - fields[1].type.u.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; - fields[1].type.u.integer.signedness = lttng_is_signed_type(unsigned long); - fields[1].type.u.integer.reverse_byte_order = 0; - fields[1].type.u.integer.base = 16; - fields[1].type.u.integer.encoding = lttng_encode_none; + field->name = "parent_ip"; + field->type = event_type; + desc->fields[1] = field; desc->owner = THIS_MODULE; - event->desc = desc; + event_recorder->priv->parent.desc = desc; return 0; -error_fields: - kfree(desc->name); +error_field1: + kfree(desc->fields[0]); +error_field0: + kfree(fieldp_array); +error_fieldp_array: + kfree(desc->event_name); error_str: kfree(desc); return ret; @@ -162,8 +197,8 @@ int lttng_kretprobes_register(const char *name, const char *symbol_name, uint64_t offset, uint64_t addr, - struct lttng_event *event_entry, - struct lttng_event *event_exit) + struct lttng_kernel_event_recorder *event_recorder_entry, + struct lttng_kernel_event_recorder *event_recorder_exit) { int ret; struct lttng_krp *lttng_krp; @@ -172,10 +207,10 @@ int lttng_kretprobes_register(const char *name, if (symbol_name[0] == '\0') symbol_name = NULL; - ret = lttng_create_kprobe_event(name, event_entry, EVENT_ENTRY); + ret = lttng_create_kprobe_event(name, event_recorder_entry, EVENT_ENTRY); if (ret) goto error; - ret = lttng_create_kprobe_event(name, event_exit, EVENT_EXIT); + ret = lttng_create_kprobe_event(name, event_recorder_exit, EVENT_EXIT); if (ret) goto event_exit_error; lttng_krp = kzalloc(sizeof(*lttng_krp), GFP_KERNEL); @@ -193,19 +228,19 @@ int lttng_kretprobes_register(const char *name, } lttng_krp->krp.kp.symbol_name = alloc_symbol; - event_entry->u.kretprobe.symbol_name = + event_recorder_entry->priv->parent.u.kretprobe.symbol_name = alloc_symbol; - event_exit->u.kretprobe.symbol_name = + event_recorder_exit->priv->parent.u.kretprobe.symbol_name = alloc_symbol; } lttng_krp->krp.kp.offset = offset; lttng_krp->krp.kp.addr = (void *) (unsigned long) addr; /* Allow probe handler to find event structures */ - lttng_krp->event[EVENT_ENTRY] = event_entry; - lttng_krp->event[EVENT_EXIT] = event_exit; - event_entry->u.kretprobe.lttng_krp = lttng_krp; - event_exit->u.kretprobe.lttng_krp = lttng_krp; + lttng_krp->event[EVENT_ENTRY] = &event_recorder_entry->parent; + lttng_krp->event[EVENT_EXIT] = &event_recorder_exit->parent; + event_recorder_entry->priv->parent.u.kretprobe.lttng_krp = lttng_krp; + event_recorder_exit->priv->parent.u.kretprobe.lttng_krp = lttng_krp; /* * Both events must be unregistered before the kretprobe is @@ -233,13 +268,17 @@ register_error: name_error: kfree(lttng_krp); krp_error: - kfree(event_exit->desc->fields); - kfree(event_exit->desc->name); - kfree(event_exit->desc); + kfree(event_recorder_exit->priv->parent.desc->fields[0]); + kfree(event_recorder_exit->priv->parent.desc->fields[1]); + kfree(event_recorder_exit->priv->parent.desc->fields); + kfree(event_recorder_exit->priv->parent.desc->event_name); + kfree(event_recorder_exit->priv->parent.desc); event_exit_error: - kfree(event_entry->desc->fields); - kfree(event_entry->desc->name); - kfree(event_entry->desc); + kfree(event_recorder_entry->priv->parent.desc->fields[0]); + kfree(event_recorder_entry->priv->parent.desc->fields[1]); + kfree(event_recorder_entry->priv->parent.desc->fields); + kfree(event_recorder_entry->priv->parent.desc->event_name); + kfree(event_recorder_entry->priv->parent.desc); error: return ret; } @@ -253,9 +292,9 @@ void _lttng_kretprobes_unregister_release(struct kref *kref) unregister_kretprobe(<tng_krp->krp); } -void lttng_kretprobes_unregister(struct lttng_event *event) +void lttng_kretprobes_unregister(struct lttng_kernel_event_recorder *event_recorder) { - kref_put(&event->u.kretprobe.lttng_krp->kref_register, + kref_put(&event_recorder->priv->parent.u.kretprobe.lttng_krp->kref_register, _lttng_kretprobes_unregister_release); } EXPORT_SYMBOL_GPL(lttng_kretprobes_unregister); @@ -268,29 +307,31 @@ void _lttng_kretprobes_release(struct kref *kref) kfree(lttng_krp->krp.kp.symbol_name); } -void lttng_kretprobes_destroy_private(struct lttng_event *event) +void lttng_kretprobes_destroy_private(struct lttng_kernel_event_recorder *event_recorder) { - kfree(event->desc->fields); - kfree(event->desc->name); - kfree(event->desc); - kref_put(&event->u.kretprobe.lttng_krp->kref_alloc, + kfree(event_recorder->priv->parent.desc->fields[0]); + kfree(event_recorder->priv->parent.desc->fields[1]); + kfree(event_recorder->priv->parent.desc->fields); + kfree(event_recorder->priv->parent.desc->event_name); + kfree(event_recorder->priv->parent.desc); + kref_put(&event_recorder->priv->parent.u.kretprobe.lttng_krp->kref_alloc, _lttng_kretprobes_release); } EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private); -int lttng_kretprobes_event_enable_state(struct lttng_event *event, +int lttng_kretprobes_event_enable_state(struct lttng_kernel_event_common *event, int enable) { - struct lttng_event *event_exit; + struct lttng_kernel_event_common *event_exit; struct lttng_krp *lttng_krp; - if (event->instrumentation != LTTNG_KERNEL_KRETPROBE) { + if (event->priv->instrumentation != LTTNG_KERNEL_ABI_KRETPROBE) { return -EINVAL; } if (event->enabled == enable) { return -EBUSY; } - lttng_krp = event->u.kretprobe.lttng_krp; + lttng_krp = event->priv->u.kretprobe.lttng_krp; event_exit = lttng_krp->event[EVENT_EXIT]; WRITE_ONCE(event->enabled, enable); WRITE_ONCE(event_exit->enabled, enable);