X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-events.c;h=9b78ac56f5d43b0fcae0e3d60a38c18965419d04;hb=52cfcdf36dfa58e0b6fb0ac3e1809e5a2538a149;hp=41bbd7098ddae75f57c7df7a9ee61bddbc0f1258;hpb=8bf17deb525927d1191c59a1765d5b11b37c4320;p=lttng-modules.git diff --git a/src/lttng-events.c b/src/lttng-events.c index 41bbd709..9b78ac56 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -280,7 +281,7 @@ void lttng_session_destroy(struct lttng_session *session) mutex_lock(&sessions_mutex); WRITE_ONCE(session->active, 0); list_for_each_entry(chan, &session->chan, list) { - ret = lttng_syscalls_unregister(chan); + ret = lttng_syscalls_unregister_event(chan); WARN_ON(ret); } list_for_each_entry(event, &session->events, list) { @@ -289,7 +290,7 @@ void lttng_session_destroy(struct lttng_session *session) } synchronize_trace(); /* Wait for in-flight events to complete */ list_for_each_entry(chan, &session->chan, list) { - ret = lttng_syscalls_destroy(chan); + ret = lttng_syscalls_destroy_event(chan); WARN_ON(ret); } list_for_each_entry_safe(event_enabler, tmp_event_enabler, @@ -329,6 +330,9 @@ void lttng_event_notifier_group_destroy( mutex_lock(&sessions_mutex); + ret = lttng_syscalls_unregister_event_notifier(event_notifier_group); + WARN_ON(ret); + list_for_each_entry_safe(event_notifier, tmpevent_notifier, &event_notifier_group->event_notifiers_head, list) { ret = _lttng_event_notifier_unregister(event_notifier); @@ -340,6 +344,8 @@ void lttng_event_notifier_group_destroy( irq_work_sync(&event_notifier_group->wakeup_pending); + kfree(event_notifier_group->sc_filter); + list_for_each_entry_safe(event_notifier_enabler, tmp_event_notifier_enabler, &event_notifier_group->enablers_head, node) lttng_event_notifier_enabler_destroy(event_notifier_enabler); @@ -612,12 +618,14 @@ int lttng_event_notifier_enable(struct lttng_event_notifier *event_notifier) } switch (event_notifier->instrumentation) { case LTTNG_KERNEL_TRACEPOINT: + case LTTNG_KERNEL_SYSCALL: ret = -EINVAL; break; - case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_UPROBE: + WRITE_ONCE(event_notifier->enabled, 1); + break; + case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_KRETPROBE: default: @@ -640,12 +648,14 @@ int lttng_event_notifier_disable(struct lttng_event_notifier *event_notifier) } switch (event_notifier->instrumentation) { case LTTNG_KERNEL_TRACEPOINT: + case LTTNG_KERNEL_SYSCALL: ret = -EINVAL; break; - case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_UPROBE: + WRITE_ONCE(event_notifier->enabled, 0); + break; + case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_KRETPROBE: default: @@ -810,7 +820,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, event->id = chan->free_event_id++; event->instrumentation = itype; event->evtype = LTTNG_TYPE_EVENT; - INIT_LIST_HEAD(&event->bytecode_runtime_head); + INIT_LIST_HEAD(&event->filter_bytecode_runtime_head); INIT_LIST_HEAD(&event->enablers_ref_head); switch (itype) { @@ -954,7 +964,7 @@ struct lttng_event *_lttng_event_create(struct lttng_channel *chan, */ smp_wmb(); - ret = lttng_uprobes_register(event_param->name, + ret = lttng_uprobes_register_event(event_param->name, event_param->u.uprobe.fd, event); if (ret) @@ -1005,10 +1015,12 @@ struct lttng_event_notifier *_lttng_event_notifier_create( break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: + case LTTNG_KERNEL_SYSCALL: + event_name = event_notifier_param->event.name; + break; case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: - case LTTNG_KERNEL_SYSCALL: default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -1040,7 +1052,7 @@ struct lttng_event_notifier *_lttng_event_notifier_create( event_notifier->instrumentation = itype; event_notifier->evtype = LTTNG_TYPE_EVENT; event_notifier->send_notification = lttng_event_notifier_notification_send; - INIT_LIST_HEAD(&event_notifier->bytecode_runtime_head); + INIT_LIST_HEAD(&event_notifier->filter_bytecode_runtime_head); INIT_LIST_HEAD(&event_notifier->enablers_ref_head); switch (itype) { @@ -1057,11 +1069,91 @@ struct lttng_event_notifier *_lttng_event_notifier_create( smp_wmb(); break; case LTTNG_KERNEL_KPROBE: + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event_notifier->enabled = 0; + event_notifier->registered = 1; + /* + * Populate lttng_event_notifier structure before event + * registration. + */ + smp_wmb(); + ret = lttng_kprobes_register_event_notifier( + event_notifier_param->event.u.kprobe.symbol_name, + event_notifier_param->event.u.kprobe.offset, + event_notifier_param->event.u.kprobe.addr, + event_notifier); + if (ret) { + ret = -EINVAL; + goto register_error; + } + ret = try_module_get(event_notifier->desc->owner); + WARN_ON_ONCE(!ret); + break; + case LTTNG_KERNEL_NOOP: + case LTTNG_KERNEL_SYSCALL: + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event_notifier->enabled = 0; + event_notifier->registered = 0; + event_notifier->desc = event_desc; + switch (event_notifier_param->event.u.syscall.entryexit) { + case LTTNG_KERNEL_SYSCALL_ENTRYEXIT: + ret = -EINVAL; + goto register_error; + case LTTNG_KERNEL_SYSCALL_ENTRY: + event_notifier->u.syscall.entryexit = LTTNG_SYSCALL_ENTRY; + break; + case LTTNG_KERNEL_SYSCALL_EXIT: + event_notifier->u.syscall.entryexit = LTTNG_SYSCALL_EXIT; + break; + } + switch (event_notifier_param->event.u.syscall.abi) { + case LTTNG_KERNEL_SYSCALL_ABI_ALL: + ret = -EINVAL; + goto register_error; + case LTTNG_KERNEL_SYSCALL_ABI_NATIVE: + event_notifier->u.syscall.abi = LTTNG_SYSCALL_ABI_NATIVE; + break; + case LTTNG_KERNEL_SYSCALL_ABI_COMPAT: + event_notifier->u.syscall.abi = LTTNG_SYSCALL_ABI_COMPAT; + break; + } + + if (!event_notifier->desc) { + ret = -EINVAL; + goto register_error; + } + break; case LTTNG_KERNEL_UPROBE: + /* + * Needs to be explicitly enabled after creation, since + * we may want to apply filters. + */ + event_notifier->enabled = 0; + event_notifier->registered = 1; + + /* + * Populate lttng_event_notifier structure before + * event_notifier registration. + */ + smp_wmb(); + + ret = lttng_uprobes_register_event_notifier( + event_notifier_param->event.name, + event_notifier_param->event.u.uprobe.fd, + event_notifier); + if (ret) + goto register_error; + ret = try_module_get(event_notifier->desc->owner); + WARN_ON_ONCE(!ret); + break; case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: - case LTTNG_KERNEL_NOOP: - case LTTNG_KERNEL_SYSCALL: default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -1128,7 +1220,7 @@ void register_event(struct lttng_event *event) event); break; case LTTNG_KERNEL_SYSCALL: - ret = lttng_syscall_filter_enable(event->chan, event); + ret = lttng_syscall_filter_enable_event(event->chan, event); break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: @@ -1171,13 +1263,13 @@ int _lttng_event_unregister(struct lttng_event *event) ret = 0; break; case LTTNG_KERNEL_SYSCALL: - ret = lttng_syscall_filter_disable(event->chan, event); + ret = lttng_syscall_filter_disable_event(event->chan, event); break; case LTTNG_KERNEL_NOOP: ret = 0; break; case LTTNG_KERNEL_UPROBE: - lttng_uprobes_unregister(event); + lttng_uprobes_unregister_event(event); ret = 0; break; case LTTNG_KERNEL_FUNCTION: /* Fall-through */ @@ -1207,8 +1299,12 @@ void register_event_notifier(struct lttng_event_notifier *event_notifier) event_notifier); break; case LTTNG_KERNEL_SYSCALL: + ret = lttng_syscall_filter_enable_event_notifier(event_notifier); + break; case LTTNG_KERNEL_KPROBE: case LTTNG_KERNEL_UPROBE: + ret = 0; + break; case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: @@ -1237,11 +1333,19 @@ int _lttng_event_notifier_unregister( event_notifier); break; case LTTNG_KERNEL_KPROBE: + lttng_kprobes_unregister_event_notifier(event_notifier); + ret = 0; + break; + case LTTNG_KERNEL_UPROBE: + lttng_uprobes_unregister_event_notifier(event_notifier); + ret = 0; + break; + case LTTNG_KERNEL_SYSCALL: + ret = lttng_syscall_filter_disable_event_notifier(event_notifier); + break; case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: - case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_NOOP: - case LTTNG_KERNEL_UPROBE: default: WARN_ON_ONCE(1); } @@ -1273,7 +1377,7 @@ void _lttng_event_destroy(struct lttng_event *event) break; case LTTNG_KERNEL_UPROBE: module_put(event->desc->owner); - lttng_uprobes_destroy_private(event); + lttng_uprobes_destroy_event_private(event); break; case LTTNG_KERNEL_FUNCTION: /* Fall-through */ default: @@ -1295,11 +1399,18 @@ void _lttng_event_notifier_destroy(struct lttng_event_notifier *event_notifier) lttng_event_desc_put(event_notifier->desc); break; case LTTNG_KERNEL_KPROBE: - case LTTNG_KERNEL_KRETPROBE: - case LTTNG_KERNEL_FUNCTION: + module_put(event_notifier->desc->owner); + lttng_kprobes_destroy_event_notifier_private(event_notifier); + break; case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_SYSCALL: + break; case LTTNG_KERNEL_UPROBE: + module_put(event_notifier->desc->owner); + lttng_uprobes_destroy_event_notifier_private(event_notifier); + break; + case LTTNG_KERNEL_KRETPROBE: + case LTTNG_KERNEL_FUNCTION: default: WARN_ON_ONCE(1); } @@ -1582,7 +1693,6 @@ int lttng_match_enabler_name(const char *desc_name, return 1; } -static int lttng_desc_match_enabler(const struct lttng_event_desc *desc, struct lttng_enabler *enabler) { @@ -1648,7 +1758,7 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc, return -EINVAL; } switch (enabler->event_param.u.syscall.match) { - case LTTNG_SYSCALL_MATCH_NAME: + case LTTNG_KERNEL_SYSCALL_MATCH_NAME: switch (enabler->format_type) { case LTTNG_ENABLER_FORMAT_STAR_GLOB: return lttng_match_enabler_star_glob(desc_name, enabler_name); @@ -1658,7 +1768,7 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc, return -EINVAL; } break; - case LTTNG_SYSCALL_MATCH_NR: + case LTTNG_KERNEL_SYSCALL_MATCH_NR: return -EINVAL; /* Not implemented. */ default: return -EINVAL; @@ -1832,7 +1942,18 @@ void lttng_create_syscall_event_if_missing(struct lttng_event_enabler *event_ena { int ret; - ret = lttng_syscalls_register(event_enabler->chan, NULL); + ret = lttng_syscalls_register_event(event_enabler->chan, NULL); + WARN_ON_ONCE(ret); +} + +static +void lttng_create_syscall_event_notifier_if_missing(struct lttng_event_notifier_enabler *event_notifier_enabler) +{ + int ret; + + ret = lttng_syscalls_register_event_notifier(event_notifier_enabler, NULL); + WARN_ON_ONCE(ret); + ret = lttng_syscals_create_matching_event_notifiers(event_notifier_enabler, NULL); WARN_ON_ONCE(ret); } @@ -1873,7 +1994,7 @@ int lttng_event_enabler_ref_events(struct lttng_event_enabler *event_enabler) if (base_enabler->event_param.instrumentation == LTTNG_KERNEL_SYSCALL && base_enabler->event_param.u.syscall.entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT && base_enabler->event_param.u.syscall.abi == LTTNG_KERNEL_SYSCALL_ABI_ALL && - base_enabler->event_param.u.syscall.match == LTTNG_SYSCALL_MATCH_NAME && + base_enabler->event_param.u.syscall.match == LTTNG_KERNEL_SYSCALL_MATCH_NAME && !strcmp(base_enabler->event_param.name, "*")) { if (base_enabler->enabled) WRITE_ONCE(chan->syscall_all, 1); @@ -1910,8 +2031,8 @@ int lttng_event_enabler_ref_events(struct lttng_event_enabler *event_enabler) */ lttng_enabler_link_bytecode(event->desc, lttng_static_ctx, - &event->bytecode_runtime_head, - lttng_event_enabler_as_enabler(event_enabler)); + &event->filter_bytecode_runtime_head, + <tng_event_enabler_as_enabler(event_enabler)->filter_bytecode_head); /* TODO: merge event context. */ } @@ -1930,6 +2051,9 @@ void lttng_create_event_notifier_if_missing(struct lttng_event_notifier_enabler case LTTNG_KERNEL_TRACEPOINT: lttng_create_tracepoint_event_notifier_if_missing(event_notifier_enabler); break; + case LTTNG_KERNEL_SYSCALL: + lttng_create_syscall_event_notifier_if_missing(event_notifier_enabler); + break; default: WARN_ON_ONCE(1); break; @@ -1940,11 +2064,29 @@ void lttng_create_event_notifier_if_missing(struct lttng_event_notifier_enabler * Create event_notifiers associated with a event_notifier enabler (if not already present). */ static -int lttng_event_notifier_enabler_ref_event_notifiers(struct lttng_event_notifier_enabler *event_notifier_enabler) +int lttng_event_notifier_enabler_ref_event_notifiers( + struct lttng_event_notifier_enabler *event_notifier_enabler) { struct lttng_event_notifier_group *event_notifier_group = event_notifier_enabler->group; + struct lttng_enabler *base_enabler = lttng_event_notifier_enabler_as_enabler(event_notifier_enabler); struct lttng_event_notifier *event_notifier; + if (base_enabler->event_param.instrumentation == LTTNG_KERNEL_SYSCALL && + base_enabler->event_param.u.syscall.abi == LTTNG_KERNEL_SYSCALL_ABI_ALL && + base_enabler->event_param.u.syscall.match == LTTNG_KERNEL_SYSCALL_MATCH_NAME && + !strcmp(base_enabler->event_param.name, "*")) { + + int enabled = base_enabler->enabled; + enum lttng_kernel_syscall_entryexit entryexit = base_enabler->event_param.u.syscall.entryexit; + + if (entryexit == LTTNG_KERNEL_SYSCALL_ENTRY || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) + WRITE_ONCE(event_notifier_group->syscall_all_entry, enabled); + + if (entryexit == LTTNG_KERNEL_SYSCALL_EXIT || entryexit == LTTNG_KERNEL_SYSCALL_ENTRYEXIT) + WRITE_ONCE(event_notifier_group->syscall_all_exit, enabled); + + } + /* First ensure that probe event_notifiers are created for this enabler. */ lttng_create_event_notifier_if_missing(event_notifier_enabler); @@ -1976,8 +2118,8 @@ int lttng_event_notifier_enabler_ref_event_notifiers(struct lttng_event_notifier * Link filter bytecodes if not linked yet. */ lttng_enabler_link_bytecode(event_notifier->desc, - lttng_static_ctx, &event_notifier->bytecode_runtime_head, - lttng_event_notifier_enabler_as_enabler(event_notifier_enabler)); + lttng_static_ctx, &event_notifier->filter_bytecode_runtime_head, + <tng_event_notifier_enabler_as_enabler(event_notifier_enabler)->filter_bytecode_head); } return 0; } @@ -2073,17 +2215,17 @@ int lttng_event_enabler_disable(struct lttng_event_enabler *event_enabler) } static -int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, +int lttng_enabler_attach_filter_bytecode(struct lttng_enabler *enabler, struct lttng_kernel_filter_bytecode __user *bytecode) { - struct lttng_filter_bytecode_node *bytecode_node; + struct lttng_bytecode_node *bytecode_node; uint32_t bytecode_len; int ret; ret = get_user(bytecode_len, &bytecode->len); if (ret) return ret; - bytecode_node = kzalloc(sizeof(*bytecode_node) + bytecode_len, + bytecode_node = lttng_kvzalloc(sizeof(*bytecode_node) + bytecode_len, GFP_KERNEL); if (!bytecode_node) return -ENOMEM; @@ -2092,6 +2234,7 @@ int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, if (ret) goto error_free; + bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_FILTER; bytecode_node->enabler = enabler; /* Enforce length based on allocated size */ bytecode_node->bc.len = bytecode_len; @@ -2100,15 +2243,15 @@ int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler, return 0; error_free: - kfree(bytecode_node); + lttng_kvfree(bytecode_node); return ret; } -int lttng_event_enabler_attach_bytecode(struct lttng_event_enabler *event_enabler, +int lttng_event_enabler_attach_filter_bytecode(struct lttng_event_enabler *event_enabler, struct lttng_kernel_filter_bytecode __user *bytecode) { int ret; - ret = lttng_enabler_attach_bytecode( + ret = lttng_enabler_attach_filter_bytecode( lttng_event_enabler_as_enabler(event_enabler), bytecode); if (ret) goto error; @@ -2126,7 +2269,7 @@ int lttng_event_add_callsite(struct lttng_event *event, switch (event->instrumentation) { case LTTNG_KERNEL_UPROBE: - return lttng_uprobes_add_callsite(event, callsite); + return lttng_uprobes_event_add_callsite(event, callsite); default: return -EINVAL; } @@ -2141,12 +2284,12 @@ int lttng_event_enabler_attach_context(struct lttng_event_enabler *event_enabler static void lttng_enabler_destroy(struct lttng_enabler *enabler) { - struct lttng_filter_bytecode_node *filter_node, *tmp_filter_node; + struct lttng_bytecode_node *filter_node, *tmp_filter_node; /* Destroy filter bytecode */ list_for_each_entry_safe(filter_node, tmp_filter_node, &enabler->filter_bytecode_head, node) { - kfree(filter_node); + lttng_kvfree(filter_node); } } @@ -2176,9 +2319,8 @@ struct lttng_event_notifier_enabler *lttng_event_notifier_enabler_create( event_notifier_enabler->base.format_type = format_type; INIT_LIST_HEAD(&event_notifier_enabler->base.filter_bytecode_head); - memcpy(&event_notifier_enabler->base.event_param.name, event_notifier_param->event.name, - sizeof(event_notifier_enabler->base.event_param.name)); - event_notifier_enabler->base.event_param.instrumentation = event_notifier_param->event.instrumentation; + memcpy(&event_notifier_enabler->base.event_param, &event_notifier_param->event, + sizeof(event_notifier_enabler->base.event_param)); event_notifier_enabler->base.evtype = LTTNG_TYPE_ENABLER; event_notifier_enabler->base.enabled = 0; @@ -2214,13 +2356,13 @@ int lttng_event_notifier_enabler_disable( return 0; } -int lttng_event_notifier_enabler_attach_bytecode( +int lttng_event_notifier_enabler_attach_filter_bytecode( struct lttng_event_notifier_enabler *event_notifier_enabler, struct lttng_kernel_filter_bytecode __user *bytecode) { int ret; - ret = lttng_enabler_attach_bytecode( + ret = lttng_enabler_attach_filter_bytecode( lttng_event_notifier_enabler_as_enabler(event_notifier_enabler), bytecode); if (ret) @@ -2233,6 +2375,19 @@ error: return ret; } +int lttng_event_notifier_add_callsite(struct lttng_event_notifier *event_notifier, + struct lttng_kernel_event_callsite __user *callsite) +{ + + switch (event_notifier->instrumentation) { + case LTTNG_KERNEL_UPROBE: + return lttng_uprobes_event_notifier_add_callsite(event_notifier, + callsite); + default: + return -EINVAL; + } +} + int lttng_event_notifier_enabler_attach_context( struct lttng_event_notifier_enabler *event_notifier_enabler, struct lttng_kernel_context *context_param) @@ -2325,8 +2480,8 @@ void lttng_session_sync_event_enablers(struct lttng_session *session) /* Enable filters */ list_for_each_entry(runtime, - &event->bytecode_runtime_head, node) - lttng_filter_sync_state(runtime); + &event->filter_bytecode_runtime_head, node) + lttng_bytecode_filter_sync_state(runtime); } } @@ -2408,8 +2563,8 @@ void lttng_event_notifier_group_sync_enablers(struct lttng_event_notifier_group /* Enable filters */ list_for_each_entry(runtime, - &event_notifier->bytecode_runtime_head, node) - lttng_filter_sync_state(runtime); + &event_notifier->filter_bytecode_runtime_head, node) + lttng_bytecode_filter_sync_state(runtime); } }