X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Ftrace-kernel.c;h=b9d03a72e002ca0042764a877f0ae556e87f1faa;hp=083add3f30f907eee80dc259b0e961f028e50ab3;hb=87597c2c3bbaa1502ad2025cbf16704829f3b464;hpb=753873bfbbfd0d7adb26c96223999a901ae46fd5 diff --git a/src/bin/lttng-sessiond/trace-kernel.c b/src/bin/lttng-sessiond/trace-kernel.c index 083add3f3..b9d03a72e 100644 --- a/src/bin/lttng-sessiond/trace-kernel.c +++ b/src/bin/lttng-sessiond/trace-kernel.c @@ -21,6 +21,11 @@ #include #include +#include +#include +#include +#include + #include #include @@ -257,11 +262,33 @@ struct ltt_kernel_context *trace_kernel_create_context( if (ctx) { memcpy(&kctx->ctx, ctx, sizeof(kctx->ctx)); } +error: + return kctx; +} + +/* + * Allocate and init a kernel context object from an existing kernel context + * object. + * + * Return the allocated object or NULL on error. + */ +struct ltt_kernel_context *trace_kernel_copy_context( + struct ltt_kernel_context *kctx) +{ + struct ltt_kernel_context *kctx_copy; + + assert(kctx); + kctx_copy = zmalloc(sizeof(*kctx_copy)); + if (!kctx_copy) { + PERROR("zmalloc ltt_kernel_context"); + goto error; + } - CDS_INIT_LIST_HEAD(&kctx->list); + memcpy(kctx_copy, kctx, sizeof(*kctx_copy)); + memset(&kctx_copy->list, 0, sizeof(kctx_copy->list)); error: - return kctx; + return kctx_copy; } /* @@ -270,18 +297,23 @@ error: * * Return pointer to structure or NULL. */ -struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, - char *filter_expression, struct lttng_filter_bytecode *filter) +enum lttng_error_code trace_kernel_create_event( + struct lttng_event *ev, char *filter_expression, + struct lttng_filter_bytecode *filter, + struct ltt_kernel_event **kernel_event) { - struct ltt_kernel_event *lke; + enum lttng_error_code ret; struct lttng_kernel_event *attr; + struct ltt_kernel_event *local_kernel_event; + struct lttng_userspace_probe_location *userspace_probe_location = NULL; assert(ev); - lke = zmalloc(sizeof(struct ltt_kernel_event)); + local_kernel_event = zmalloc(sizeof(struct ltt_kernel_event)); attr = zmalloc(sizeof(struct lttng_kernel_event)); - if (lke == NULL || attr == NULL) { + if (local_kernel_event == NULL || attr == NULL) { PERROR("kernel event zmalloc"); + ret = LTTNG_ERR_NOMEM; goto error; } @@ -294,6 +326,84 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, ev->attr.probe.symbol_name, LTTNG_KERNEL_SYM_NAME_LEN); attr->u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; break; + case LTTNG_EVENT_USERSPACE_PROBE: + { + const struct lttng_userspace_probe_location* location = NULL; + const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; + + location = lttng_event_get_userspace_probe_location(ev); + if (!location) { + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + + /* + * From this point on, the specific term 'uprobe' is used + * instead of the generic 'userspace probe' because it's the + * technology used at the moment for this instrumentation. + * LTTng currently implements userspace probes using uprobes. + * In the interactions with the kernel tracer, we use the + * uprobe term. + */ + attr->instrumentation = LTTNG_KERNEL_UPROBE; + + /* + * Only the elf lookup method is supported at the moment. + */ + lookup = lttng_userspace_probe_location_get_lookup_method( + location); + if (!lookup) { + ret = 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. */ + attr->u.uprobe.fd = + lttng_userspace_probe_location_function_get_binary_fd(location); + + /* + * Save a reference to the probe location used during + * the listing of events. Close its FD since it won't + * be needed for listing. + */ + userspace_probe_location = + lttng_userspace_probe_location_copy(location); + ret = lttng_userspace_probe_location_function_set_binary_fd( + userspace_probe_location, -1); + if (ret) { + goto error; + } + break; + case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: + /* Get the file descriptor on the target binary. */ + attr->u.uprobe.fd = + lttng_userspace_probe_location_tracepoint_get_binary_fd(location); + + /* + * Save a reference to the probe location used during the listing of + * events. Close its FD since it won't be needed for listing. + */ + userspace_probe_location = + lttng_userspace_probe_location_copy(location); + ret = lttng_userspace_probe_location_tracepoint_set_binary_fd( + userspace_probe_location, -1); + if (ret) { + goto error; + } + break; + default: + DBG("Unsupported lookup method type"); + ret = LTTNG_ERR_PROBE_LOCATION_INVAL; + goto error; + } + break; + } case LTTNG_EVENT_FUNCTION: attr->instrumentation = LTTNG_KERNEL_KRETPROBE; attr->u.kretprobe.addr = ev->attr.probe.addr; @@ -319,6 +429,7 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, break; default: ERR("Unknown kernel instrumentation type (%d)", ev->type); + ret = LTTNG_ERR_INVALID; goto error; } @@ -327,20 +438,23 @@ struct ltt_kernel_event *trace_kernel_create_event(struct lttng_event *ev, attr->name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; /* Setting up a kernel event */ - lke->fd = -1; - lke->event = attr; - lke->enabled = 1; - lke->filter_expression = filter_expression; - lke->filter = filter; + local_kernel_event->fd = -1; + local_kernel_event->event = attr; + local_kernel_event->enabled = 1; + local_kernel_event->filter_expression = filter_expression; + local_kernel_event->filter = filter; + local_kernel_event->userspace_probe_location = userspace_probe_location; - return lke; + *kernel_event = local_kernel_event; + + return LTTNG_OK; error: free(filter_expression); free(filter); - free(lke); + free(local_kernel_event); free(attr); - return NULL; + return ret; } /* @@ -479,7 +593,9 @@ void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) { assert(ctx); - cds_list_del(&ctx->list); + if (ctx->in_list) { + cds_list_del(&ctx->list); + } free(ctx); } @@ -527,7 +643,7 @@ void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) && channel->published_to_notification_thread) { status = notification_thread_command_remove_channel( notification_thread_handle, - channel->fd, LTTNG_DOMAIN_KERNEL); + channel->key, LTTNG_DOMAIN_KERNEL); assert(status == LTTNG_OK); } free(channel->channel->attr.extended.ptr);