X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ftrace-kernel.c;h=cbafd12bd45ebbb35177894136a30e0cf7269ca5;hb=a0377dfefe40662ba7d68617bce6ff467114136c;hp=dfdc9fd14e96b9b2124034983dc0d1db4525633a;hpb=e368fb4396b9bdb22de16f0c93512c9f6d7ab0b4;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index dfdc9fd14..cbafd12bd 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -13,9 +13,19 @@ #include #include +#include #include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include @@ -34,8 +44,8 @@ struct ltt_kernel_channel *trace_kernel_get_channel_by_name( { struct ltt_kernel_channel *chan; - assert(session); - assert(name); + LTTNG_ASSERT(session); + LTTNG_ASSERT(name); /* * If we receive an empty string for channel name, it means the @@ -62,13 +72,13 @@ struct ltt_kernel_channel *trace_kernel_get_channel_by_name( struct ltt_kernel_event *trace_kernel_find_event( char *name, struct ltt_kernel_channel *channel, enum lttng_event_type type, - struct lttng_filter_bytecode *filter) + struct lttng_bytecode *filter) { struct ltt_kernel_event *ev; int found = 0; - assert(name); - assert(channel); + LTTNG_ASSERT(name); + LTTNG_ASSERT(channel); cds_list_for_each_entry(ev, &channel->events_list.head, list) { if (type != LTTNG_EVENT_ALL && ev->type != type) { @@ -109,8 +119,8 @@ struct ltt_kernel_event *trace_kernel_get_event_by_name( struct ltt_kernel_event *ev; int found = 0; - assert(name); - assert(channel); + LTTNG_ASSERT(name); + LTTNG_ASSERT(channel); cds_list_for_each_entry(ev, &channel->events_list.head, list) { if (type != LTTNG_EVENT_ALL && ev->type != type) { @@ -210,7 +220,7 @@ struct ltt_kernel_channel *trace_kernel_create_channel( struct ltt_kernel_channel *lkc; struct lttng_channel_extended *extended = NULL; - assert(chan); + LTTNG_ASSERT(chan); lkc = zmalloc(sizeof(struct ltt_kernel_channel)); if (lkc == NULL) { @@ -242,7 +252,7 @@ struct ltt_kernel_channel *trace_kernel_create_channel( strncpy(lkc->channel->name, DEFAULT_CHANNEL_NAME, sizeof(lkc->channel->name)); } - lkc->channel->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + lkc->channel->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; lkc->fd = -1; lkc->stream_count = 0; @@ -271,7 +281,7 @@ error: * Return the allocated object or NULL on error. */ struct ltt_kernel_context *trace_kernel_create_context( - struct lttng_kernel_context *ctx) + struct lttng_kernel_abi_context *ctx) { struct ltt_kernel_context *kctx; @@ -299,7 +309,7 @@ struct ltt_kernel_context *trace_kernel_copy_context( { struct ltt_kernel_context *kctx_copy; - assert(kctx); + LTTNG_ASSERT(kctx); kctx_copy = zmalloc(sizeof(*kctx_copy)); if (!kctx_copy) { PERROR("zmalloc ltt_kernel_context"); @@ -321,18 +331,18 @@ error: */ enum lttng_error_code trace_kernel_create_event( struct lttng_event *ev, char *filter_expression, - struct lttng_filter_bytecode *filter, + struct lttng_bytecode *filter, struct ltt_kernel_event **kernel_event) { enum lttng_error_code ret; - struct lttng_kernel_event *attr; + struct lttng_kernel_abi_event *attr; struct ltt_kernel_event *local_kernel_event; struct lttng_userspace_probe_location *userspace_probe_location = NULL; - assert(ev); + LTTNG_ASSERT(ev); local_kernel_event = zmalloc(sizeof(struct ltt_kernel_event)); - attr = zmalloc(sizeof(struct lttng_kernel_event)); + attr = zmalloc(sizeof(struct lttng_kernel_abi_event)); if (local_kernel_event == NULL || attr == NULL) { PERROR("kernel event zmalloc"); ret = LTTNG_ERR_NOMEM; @@ -341,12 +351,12 @@ enum lttng_error_code trace_kernel_create_event( switch (ev->type) { case LTTNG_EVENT_PROBE: - attr->instrumentation = LTTNG_KERNEL_KPROBE; + attr->instrumentation = LTTNG_KERNEL_ABI_KPROBE; attr->u.kprobe.addr = ev->attr.probe.addr; attr->u.kprobe.offset = ev->attr.probe.offset; strncpy(attr->u.kprobe.symbol_name, - ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); - attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); + attr->u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_USERSPACE_PROBE: { @@ -367,11 +377,8 @@ enum lttng_error_code trace_kernel_create_event( * In the interactions with the kernel tracer, we use the * uprobe term. */ - attr->instrumentation = LTTNG_KERNEL_UPROBE; + attr->instrumentation = LTTNG_KERNEL_ABI_UPROBE; - /* - * Only the elf lookup method is supported at the moment. - */ lookup = lttng_userspace_probe_location_get_lookup_method( location); if (!lookup) { @@ -416,27 +423,30 @@ enum lttng_error_code trace_kernel_create_event( break; } case LTTNG_EVENT_FUNCTION: - attr->instrumentation = LTTNG_KERNEL_KRETPROBE; + attr->instrumentation = LTTNG_KERNEL_ABI_KRETPROBE; attr->u.kretprobe.addr = ev->attr.probe.addr; attr->u.kretprobe.offset = ev->attr.probe.offset; strncpy(attr->u.kretprobe.symbol_name, - ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); - attr->u.kretprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); + attr->u.kretprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_FUNCTION_ENTRY: - attr->instrumentation = LTTNG_KERNEL_FUNCTION; + attr->instrumentation = LTTNG_KERNEL_ABI_FUNCTION; strncpy(attr->u.ftrace.symbol_name, - ev->attr.ftrace.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); - attr->u.ftrace.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + ev->attr.ftrace.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); + attr->u.ftrace.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; break; case LTTNG_EVENT_TRACEPOINT: - attr->instrumentation = LTTNG_KERNEL_TRACEPOINT; + attr->instrumentation = LTTNG_KERNEL_ABI_TRACEPOINT; break; case LTTNG_EVENT_SYSCALL: - attr->instrumentation = LTTNG_KERNEL_SYSCALL; + attr->instrumentation = LTTNG_KERNEL_ABI_SYSCALL; + attr->u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; + attr->u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; + attr->u.syscall.match = LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; break; case LTTNG_EVENT_ALL: - attr->instrumentation = LTTNG_KERNEL_ALL; + attr->instrumentation = LTTNG_KERNEL_ABI_ALL; break; default: ERR("Unknown kernel instrumentation type (%d)", ev->type); @@ -445,8 +455,8 @@ enum lttng_error_code trace_kernel_create_event( } /* Copy event name */ - strncpy(attr->name, ev->name, LTTNG_KERNEL_SYM_NAME_LEN); - attr->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; + strncpy(attr->name, ev->name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); + attr->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; /* Setting up a kernel event */ local_kernel_event->fd = -1; @@ -468,6 +478,251 @@ error: return ret; } +/* + * Allocate and initialize a kernel token event rule. + * + * Return pointer to structure or NULL. + */ +enum lttng_error_code trace_kernel_create_event_notifier_rule( + struct lttng_trigger *trigger, + uint64_t token, + uint64_t error_counter_index, + struct ltt_kernel_event_notifier_rule **event_notifier_rule) +{ + enum lttng_error_code ret = LTTNG_OK; + enum lttng_condition_type condition_type; + enum lttng_event_rule_type event_rule_type; + enum lttng_condition_status condition_status; + struct ltt_kernel_event_notifier_rule *local_kernel_token_event_rule; + const struct lttng_condition *condition = NULL; + const struct lttng_event_rule *event_rule = NULL; + + LTTNG_ASSERT(event_notifier_rule); + + condition = lttng_trigger_get_const_condition(trigger); + LTTNG_ASSERT(condition); + + condition_type = lttng_condition_get_type(condition); + LTTNG_ASSERT(condition_type == LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES); + + condition_status = lttng_condition_event_rule_matches_get_rule( + condition, &event_rule); + LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK); + LTTNG_ASSERT(event_rule); + + event_rule_type = lttng_event_rule_get_type(event_rule); + LTTNG_ASSERT(event_rule_type != LTTNG_EVENT_RULE_TYPE_UNKNOWN); + + local_kernel_token_event_rule = + zmalloc(sizeof(struct ltt_kernel_event_notifier_rule)); + if (local_kernel_token_event_rule == NULL) { + PERROR("Failed to allocate ltt_kernel_token_event_rule structure"); + ret = LTTNG_ERR_NOMEM; + goto error; + } + + local_kernel_token_event_rule->fd = -1; + local_kernel_token_event_rule->enabled = 1; + local_kernel_token_event_rule->token = token; + local_kernel_token_event_rule->error_counter_index = error_counter_index; + + /* Get the reference of the event rule. */ + lttng_trigger_get(trigger); + + local_kernel_token_event_rule->trigger = trigger; + /* The event rule still owns the filter and bytecode. */ + local_kernel_token_event_rule->filter = + lttng_event_rule_get_filter_bytecode(event_rule); + + DBG3("Created kernel event notifier rule: token = %" PRIu64, + local_kernel_token_event_rule->token); +error: + *event_notifier_rule = local_kernel_token_event_rule; + return ret; +} + +/* + * Initialize a kernel trigger from an event rule. + */ +enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule( + const struct lttng_event_rule *rule, + struct lttng_kernel_abi_event_notifier *kernel_event_notifier) +{ + enum lttng_error_code ret_code; + const char *name; + int strncpy_ret; + + switch (lttng_event_rule_get_type(rule)) { + case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE: + { + uint64_t address = 0, offset = 0; + const char *symbol_name = NULL; + const struct lttng_kernel_probe_location *location = NULL; + enum lttng_kernel_probe_location_status k_status; + enum lttng_event_rule_status status; + + status = lttng_event_rule_kernel_kprobe_get_location(rule, &location); + if (status != LTTNG_EVENT_RULE_STATUS_OK) { + ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + switch (lttng_kernel_probe_location_get_type(location)) { + case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: + { + k_status = lttng_kernel_probe_location_address_get_address( + location, &address); + LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); + break; + } + case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: + { + k_status = lttng_kernel_probe_location_symbol_get_offset( + location, &offset); + LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); + symbol_name = lttng_kernel_probe_location_symbol_get_name( + location); + break; + } + default: + abort(); + } + + kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_KPROBE; + kernel_event_notifier->event.u.kprobe.addr = address; + kernel_event_notifier->event.u.kprobe.offset = offset; + if (symbol_name) { + strncpy_ret = lttng_strncpy( + kernel_event_notifier->event.u.kprobe.symbol_name, + symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); + + if (strncpy_ret) { + ret_code = LTTNG_ERR_INVALID; + goto error; + } + } + + kernel_event_notifier->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; + + status = lttng_event_rule_kernel_kprobe_get_event_name(rule, &name); + LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); + ret_code = LTTNG_OK; + break; + } + case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE: + { + const struct lttng_userspace_probe_location* location = NULL; + const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; + enum lttng_event_rule_status status; + + status = lttng_event_rule_kernel_uprobe_get_location(rule, &location); + if (status != LTTNG_EVENT_RULE_STATUS_OK) { + ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_UPROBE; + + lookup = lttng_userspace_probe_location_get_lookup_method( + location); + if (!lookup) { + ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + /* + * From the kernel tracer's perspective, all userspace probe + * event types are all the same: a file and an offset. + */ + switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: + /* Get the file descriptor on the target binary. */ + kernel_event_notifier->event.u.uprobe.fd = + lttng_userspace_probe_location_function_get_binary_fd(location); + + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: + /* Get the file descriptor on the target binary. */ + kernel_event_notifier->event.u.uprobe.fd = + lttng_userspace_probe_location_tracepoint_get_binary_fd(location); + break; + default: + abort(); + } + + status = lttng_event_rule_kernel_uprobe_get_event_name( + rule, &name); + LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); + ret_code = LTTNG_OK; + break; + } + case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT: + { + const enum lttng_event_rule_status status = + lttng_event_rule_kernel_tracepoint_get_name_pattern( + rule, &name); + + LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); + kernel_event_notifier->event.instrumentation = + LTTNG_KERNEL_ABI_TRACEPOINT; + + ret_code = LTTNG_OK; + break; + } + case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL: + { + const enum lttng_event_rule_status status = + lttng_event_rule_kernel_syscall_get_name_pattern( + rule, &name); + const enum lttng_event_rule_kernel_syscall_emission_site + emission_site = + lttng_event_rule_kernel_syscall_get_emission_site(rule); + enum lttng_kernel_abi_syscall_entryexit entryexit; + + LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); + LTTNG_ASSERT(emission_site != LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN); + + switch(emission_site) { + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: + entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY; + break; + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: + entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT; + break; + case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: + entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; + break; + default: + abort(); + break; + } + + kernel_event_notifier->event.instrumentation = + LTTNG_KERNEL_ABI_SYSCALL; + kernel_event_notifier->event.u.syscall.abi = + LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; + kernel_event_notifier->event.u.syscall.entryexit = + entryexit; + kernel_event_notifier->event.u.syscall.match = + LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; + ret_code = LTTNG_OK; + break; + } + default: + abort(); + break; + } + + strncpy_ret = lttng_strncpy(kernel_event_notifier->event.name, name, + LTTNG_KERNEL_ABI_SYM_NAME_LEN); + if (strncpy_ret) { + ret_code = LTTNG_ERR_INVALID; + goto error; + } + +error: + return ret_code; +} /* * Allocate and initialize a kernel metadata. * @@ -543,7 +798,7 @@ struct ltt_kernel_stream *trace_kernel_create_stream(const char *name, int ret; struct ltt_kernel_stream *lks; - assert(name); + LTTNG_ASSERT(name); lks = zmalloc(sizeof(struct ltt_kernel_stream)); if (lks == NULL) { @@ -575,7 +830,7 @@ error: */ void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream) { - assert(stream); + LTTNG_ASSERT(stream); DBG("[trace] Closing stream fd %d", stream->fd); /* Close kernel fd */ @@ -598,7 +853,7 @@ void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream) */ void trace_kernel_destroy_event(struct ltt_kernel_event *event) { - assert(event); + LTTNG_ASSERT(event); if (event->fd >= 0) { int ret; @@ -610,7 +865,7 @@ void trace_kernel_destroy_event(struct ltt_kernel_event *event) PERROR("close"); } } else { - DBG("[trace] Tearing down event (no associated fd)"); + DBG("[trace] Tearing down event (no associated file descriptor)"); } /* Remove from event list */ @@ -623,12 +878,44 @@ void trace_kernel_destroy_event(struct ltt_kernel_event *event) free(event); } +/* + * Cleanup kernel event structure. + */ +static void free_token_event_rule_rcu(struct rcu_head *rcu_node) +{ + struct ltt_kernel_event_notifier_rule *rule = caa_container_of(rcu_node, + struct ltt_kernel_event_notifier_rule, rcu_node); + + free(rule); +} + +void trace_kernel_destroy_event_notifier_rule( + struct ltt_kernel_event_notifier_rule *event) +{ + LTTNG_ASSERT(event); + + if (event->fd >= 0) { + const int ret = close(event->fd); + + DBG("Closing kernel event notifier rule file descriptor: fd = %d", + event->fd); + if (ret) { + PERROR("Failed to close kernel event notifier file descriptor: fd = %d", + event->fd); + } + } else { + DBG("Destroying kernel event notifier rule (no associated file descriptor)"); + } + + lttng_trigger_put(event->trigger); + call_rcu(&event->rcu_node, free_token_event_rule_rcu); +} /* * Cleanup kernel context structure. */ void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) { - assert(ctx); + LTTNG_ASSERT(ctx); if (ctx->in_list) { cds_list_del(&ctx->list); @@ -647,7 +934,7 @@ void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) int ret; enum lttng_error_code status; - assert(channel); + LTTNG_ASSERT(channel); DBG("[trace] Closing channel fd %d", channel->fd); /* Close kernel fd */ @@ -676,12 +963,12 @@ void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) /* Remove from channel list */ cds_list_del(&channel->list); - if (notification_thread_handle - && channel->published_to_notification_thread) { + if (the_notification_thread_handle && + channel->published_to_notification_thread) { status = notification_thread_command_remove_channel( - notification_thread_handle, - channel->key, LTTNG_DOMAIN_KERNEL); - assert(status == LTTNG_OK); + the_notification_thread_handle, channel->key, + LTTNG_DOMAIN_KERNEL); + LTTNG_ASSERT(status == LTTNG_OK); } free(channel->channel->attr.extended.ptr); free(channel->channel); @@ -693,7 +980,7 @@ void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) */ void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata) { - assert(metadata); + LTTNG_ASSERT(metadata); DBG("[trace] Closing metadata fd %d", metadata->fd); /* Close kernel fd */ @@ -720,7 +1007,7 @@ void trace_kernel_destroy_session(struct ltt_kernel_session *session) struct ltt_kernel_channel *channel, *ctmp; int ret; - assert(session); + LTTNG_ASSERT(session); DBG("[trace] Closing session fd %d", session->fd); /* Close kernel fds */