X-Git-Url: http://git.lttng.org/?p=lttng-modules.git;a=blobdiff_plain;f=src%2Flttng-events.c;h=75a193045b1d381a3bf531542e763d741b095d8a;hp=84ffd28332e9b5b02a1cafed7d83f82e9249cff3;hb=99d223adfae9b68800e91bda470c92acb14efae6;hpb=2b16f0c9dfdc1b1a593c5ed58fd08a89e18eccae diff --git a/src/lttng-events.c b/src/lttng-events.c index 84ffd283..75a19304 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,14 +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_KPROBE: + case LTTNG_KERNEL_UPROBE: WRITE_ONCE(event_notifier->enabled, 1); break; - case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_FUNCTION: - case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_KRETPROBE: default: @@ -642,14 +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_KPROBE: + case LTTNG_KERNEL_UPROBE: WRITE_ONCE(event_notifier->enabled, 0); break; - case LTTNG_KERNEL_SYSCALL: case LTTNG_KERNEL_FUNCTION: - case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_NOOP: case LTTNG_KERNEL_KRETPROBE: default: @@ -814,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) { @@ -958,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) @@ -1008,13 +1014,13 @@ struct lttng_event_notifier *_lttng_event_notifier_create( event_name = event_desc->name; break; case LTTNG_KERNEL_KPROBE: + case LTTNG_KERNEL_UPROBE: + case LTTNG_KERNEL_SYSCALL: event_name = event_notifier_param->event.name; break; - case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: - case LTTNG_KERNEL_SYSCALL: default: WARN_ON_ONCE(1); ret = -EINVAL; @@ -1042,11 +1048,13 @@ struct lttng_event_notifier *_lttng_event_notifier_create( event_notifier->group = event_notifier_group; event_notifier->user_token = token; + event_notifier->num_captures = 0; event_notifier->filter = filter; 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->capture_bytecode_runtime_head); INIT_LIST_HEAD(&event_notifier->enablers_ref_head); switch (itype) { @@ -1086,11 +1094,68 @@ struct lttng_event_notifier *_lttng_event_notifier_create( 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; @@ -1157,7 +1222,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: @@ -1200,13 +1265,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 */ @@ -1235,11 +1300,13 @@ void register_event_notifier(struct lttng_event_notifier *event_notifier) desc->event_notifier_callback, 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_SYSCALL: - case LTTNG_KERNEL_UPROBE: case LTTNG_KERNEL_KRETPROBE: case LTTNG_KERNEL_FUNCTION: case LTTNG_KERNEL_NOOP: @@ -1271,11 +1338,16 @@ int _lttng_event_notifier_unregister( 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); } @@ -1307,7 +1379,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: @@ -1332,11 +1404,15 @@ void _lttng_event_notifier_destroy(struct lttng_event_notifier *event_notifier) module_put(event_notifier->desc->owner); lttng_kprobes_destroy_event_notifier_private(event_notifier); break; - case LTTNG_KERNEL_KRETPROBE: - case LTTNG_KERNEL_FUNCTION: 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); } @@ -1619,7 +1695,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) { @@ -1685,7 +1760,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); @@ -1695,7 +1770,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; @@ -1869,7 +1944,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); } @@ -1910,7 +1996,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); @@ -1947,8 +2033,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. */ } @@ -1967,6 +2053,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; @@ -1977,11 +2066,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); @@ -2013,8 +2120,15 @@ 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); + + /* Link capture bytecodes if not linked yet. */ + lttng_enabler_link_bytecode(event_notifier->desc, + lttng_static_ctx, &event_notifier->capture_bytecode_runtime_head, + &event_notifier_enabler->capture_bytecode_head); + + event_notifier->num_captures = event_notifier_enabler->num_captures; } return 0; } @@ -2110,17 +2224,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; @@ -2129,6 +2243,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; @@ -2137,15 +2252,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; @@ -2163,7 +2278,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; } @@ -2178,12 +2293,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); } } @@ -2212,10 +2327,12 @@ 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); + INIT_LIST_HEAD(&event_notifier_enabler->capture_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; + event_notifier_enabler->num_captures = 0; + + 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; @@ -2251,13 +2368,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) @@ -2270,6 +2387,61 @@ error: return ret; } +int lttng_event_notifier_enabler_attach_capture_bytecode( + struct lttng_event_notifier_enabler *event_notifier_enabler, + struct lttng_kernel_capture_bytecode __user *bytecode) +{ + struct lttng_bytecode_node *bytecode_node; + struct lttng_enabler *enabler = + lttng_event_notifier_enabler_as_enabler(event_notifier_enabler); + uint32_t bytecode_len; + int ret; + + ret = get_user(bytecode_len, &bytecode->len); + if (ret) + return ret; + + bytecode_node = lttng_kvzalloc(sizeof(*bytecode_node) + bytecode_len, + GFP_KERNEL); + if (!bytecode_node) + return -ENOMEM; + + ret = copy_from_user(&bytecode_node->bc, bytecode, + sizeof(*bytecode) + bytecode_len); + if (ret) + goto error_free; + + bytecode_node->type = LTTNG_BYTECODE_NODE_TYPE_CAPTURE; + bytecode_node->enabler = enabler; + + /* Enforce length based on allocated size */ + bytecode_node->bc.len = bytecode_len; + list_add_tail(&bytecode_node->node, &event_notifier_enabler->capture_bytecode_head); + + event_notifier_enabler->num_captures++; + + lttng_event_notifier_group_sync_enablers(event_notifier_enabler->group); + goto end; + +error_free: + lttng_kvfree(bytecode_node); +end: + 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) @@ -2362,8 +2534,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); } } @@ -2445,8 +2617,13 @@ 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); + + /* Enable captures */ + list_for_each_entry(runtime, + &event_notifier->capture_bytecode_runtime_head, node) + lttng_bytecode_capture_sync_state(runtime); } }