From: Mathieu Desnoyers Date: Mon, 28 Feb 2022 20:20:51 +0000 (-0500) Subject: Implement event notifier kretprobe support X-Git-Url: http://git.lttng.org./?a=commitdiff_plain;h=e54574796087599492d30f70cdbf4da091825c96;p=lttng-modules.git Implement event notifier kretprobe support Signed-off-by: Mathieu Desnoyers Change-Id: I32b42ddad79889a19ee8833ed9b52e4a37505f7b --- diff --git a/src/lttng-abi.c b/src/lttng-abi.c index 66c4a311..1d074b29 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -2386,27 +2386,6 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file, struct file *event_notifier_file; void *priv; - switch (event_notifier_param->event.instrumentation) { - case LTTNG_KERNEL_ABI_TRACEPOINT: - lttng_fallthrough; - case LTTNG_KERNEL_ABI_UPROBE: - break; - case LTTNG_KERNEL_ABI_KPROBE: - event_notifier_param->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; - break; - case LTTNG_KERNEL_ABI_SYSCALL: - break; - case LTTNG_KERNEL_ABI_KRETPROBE: - /* Placing an event notifier on kretprobe is not supported. */ - lttng_fallthrough; - case LTTNG_KERNEL_ABI_FUNCTION: - lttng_fallthrough; - case LTTNG_KERNEL_ABI_NOOP: - default: - ret = -EINVAL; - goto inval_instr; - } - switch (event_notifier_param->event.instrumentation) { case LTTNG_KERNEL_ABI_TRACEPOINT: lttng_fallthrough; @@ -2431,6 +2410,16 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file, } event_notifier_param->event.name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; + switch (event_notifier_param->event.instrumentation) { + case LTTNG_KERNEL_ABI_KRETPROBE: + event_notifier_param->event.u.kretprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; + break; + case LTTNG_KERNEL_ABI_KPROBE: + event_notifier_param->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; + break; + default: + break; + } event_notifier_fd = get_unused_fd_flags(0); if (event_notifier_fd < 0) { @@ -2485,8 +2474,6 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file, case LTTNG_KERNEL_ABI_KPROBE: lttng_fallthrough; - case LTTNG_KERNEL_ABI_KRETPROBE: - lttng_fallthrough; case LTTNG_KERNEL_ABI_UPROBE: { struct lttng_kernel_event_common *event; @@ -2508,6 +2495,48 @@ int lttng_abi_create_event_notifier(struct file *event_notifier_group_file, break; } + case LTTNG_KERNEL_ABI_KRETPROBE: + { + struct lttng_kernel_event_common *event[2]; + struct lttng_event_notifier_enabler *event_enabler; + struct lttng_kernel_event_pair event_pair; + + if (strlen(event_notifier_param->event.name) + strlen("_entry") >= LTTNG_KERNEL_ABI_SYM_NAME_LEN) + return -EINVAL; + + memset(&event_pair, 0, sizeof(event_pair)); + event_enabler = lttng_event_notifier_enabler_create(LTTNG_ENABLER_FORMAT_NAME, + event_notifier_param, event_notifier_group); + if (!event_enabler) { + ret = -ENOMEM; + goto event_notifier_error; + } + + strcpy(event_pair.name, event_notifier_param->event.name); + strcat(event_pair.name, "_entry"); + /* + * We tolerate no failure path after event creation. It + * will stay invariant for the rest of the session. + */ + event[0] = lttng_kernel_event_create(&event_enabler->parent, NULL, &event_pair); + if (IS_ERR(event[0])) { + lttng_event_enabler_destroy(&event_enabler->parent); + ret = PTR_ERR(event[0]); + goto event_notifier_error; + } + + strcpy(event_pair.name, event_notifier_param->event.name); + strcat(event_pair.name, "_exit"); + event[1] = lttng_kernel_event_create(&event_enabler->parent, NULL, &event_pair); + lttng_event_enabler_destroy(&event_enabler->parent); + if (IS_ERR(event[1])) { + ret = PTR_ERR(event[1]); + goto event_notifier_error; + } + priv = event[0]; + break; + } + case LTTNG_KERNEL_ABI_FUNCTION: lttng_fallthrough; case LTTNG_KERNEL_ABI_NOOP: diff --git a/src/lttng-events.c b/src/lttng-events.c index 97c123b2..860d8f7e 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -673,14 +673,7 @@ int lttng_event_enable(struct lttng_kernel_event_common *event) break; } case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: - switch (event->priv->instrumentation) { - case LTTNG_KERNEL_ABI_KRETPROBE: - ret = -EINVAL; - goto end; - default: - break; - } - break; + lttng_fallthrough; case LTTNG_KERNEL_EVENT_TYPE_COUNTER: break; default: @@ -739,14 +732,7 @@ int lttng_event_disable(struct lttng_kernel_event_common *event) break; } case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: - switch (event->priv->instrumentation) { - case LTTNG_KERNEL_ABI_KRETPROBE: - ret = -EINVAL; - goto end; - default: - break; - } - break; + lttng_fallthrough; case LTTNG_KERNEL_EVENT_TYPE_COUNTER: break; default: @@ -1767,11 +1753,11 @@ void unregister_event(struct lttng_kernel_event_common *event) case LTTNG_KERNEL_EVENT_TYPE_RECORDER: lttng_fallthrough; case LTTNG_KERNEL_EVENT_TYPE_COUNTER: + lttng_fallthrough; + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: lttng_kretprobes_unregister(event); ret = 0; break; - case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: - WARN_ON_ONCE(1); break; } break; diff --git a/src/lttng-kretprobes.c b/src/lttng-kretprobes.c index 1b8bbb0a..d59bd0de 100644 --- a/src/lttng-kretprobes.c +++ b/src/lttng-kretprobes.c @@ -104,6 +104,16 @@ int _lttng_kretprobes_handler(struct kretprobe_instance *krpi, chan->ops->event_commit(&ctx); break; } + case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: + { + struct lttng_kernel_event_notifier *event_notifier = + container_of(event, struct lttng_kernel_event_notifier, parent); + struct lttng_kernel_notification_ctx notif_ctx; + + notif_ctx.eval_capture = LTTNG_READ_ONCE(event_notifier->eval_capture); + event_notifier->notification_send(event_notifier, NULL, NULL, ¬if_ctx); + break; + } case LTTNG_KERNEL_EVENT_TYPE_COUNTER: { struct lttng_kernel_event_counter *event_counter = @@ -112,8 +122,6 @@ int _lttng_kretprobes_handler(struct kretprobe_instance *krpi, (void) event_counter->chan->ops->event_counter_add(event_counter, 1); break; } - case LTTNG_KERNEL_EVENT_TYPE_NOTIFIER: - lttng_fallthrough; default: WARN_ON_ONCE(1); }