#include <string.h>
#include <unistd.h>
+#include <lttng/event.h>
+#include <lttng/lttng-error.h>
+#include <lttng/userspace-probe.h>
+#include <lttng/userspace-probe-internal.h>
+
#include <common/common.h>
#include <common/defaults.h>
+#include <common/trace-chunk.h>
#include "consumer.h"
#include "trace-kernel.h"
* Find the channel name for the given kernel session.
*/
struct ltt_kernel_channel *trace_kernel_get_channel_by_name(
- char *name, struct ltt_kernel_session *session)
+ const char *name, struct ltt_kernel_session *session)
{
struct ltt_kernel_channel *chan;
*
* 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;
}
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;
break;
default:
ERR("Unknown kernel instrumentation type (%d)", ev->type);
+ ret = LTTNG_ERR_INVALID;
goto error;
}
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;
+
+ *kernel_event = local_kernel_event;
- return lke;
+ return LTTNG_OK;
error:
free(filter_expression);
free(filter);
- free(lke);
+ free(local_kernel_event);
free(attr);
- return NULL;
+ return ret;
}
/*
cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) {
trace_kernel_destroy_channel(channel);
}
+}
+/* Free elements needed by destroy notifiers. */
+void trace_kernel_free_session(struct ltt_kernel_session *session)
+{
/* Wipe consumer output object */
consumer_output_put(session->consumer);