[lttng-dev] [RFC PATCH lttng-tools 1/2] Add support for UST dynamic instrumentation

Zifei Tong soariez at gmail.com
Wed Sep 4 07:00:40 EDT 2013


Most parts of code are to deal with passing a varlen payload between
the sessiond, tracer application and lttng command, inspired by how
the filter feature are implemented.

You can also view the patch at:
https://github.com/5kg/lttng-tools/commit/fc2ca02a6915a4da513d47c7386e4a13f6629538
---
 include/lttng/lttng-error.h              |   2 +
 include/lttng/lttng.h                    |  19 ++++-
 src/bin/lttng-sessiond/Makefile.am       |   1 +
 src/bin/lttng-sessiond/cmd.c             |   6 ++
 src/bin/lttng-sessiond/lttng-ust-abi.h   |  30 +++++++-
 src/bin/lttng-sessiond/main.c            |  38 ++++++++++
 src/bin/lttng-sessiond/trace-ust.c       |  19 ++++-
 src/bin/lttng-sessiond/ust-app.c         | 126 +++++++++++++++++++++++++++++++
 src/bin/lttng-sessiond/ust-instrument.h  |  47 ++++++++++++
 src/bin/lttng/commands/enable_events.c   |  84 +++++++++++++++++++--
 src/bin/lttng/commands/list.c            |   2 +
 src/common/error.c                       |   2 +
 src/common/sessiond-comm/sessiond-comm.h |   2 +
 src/lib/lttng-ctl/lttng-ctl.c            |   7 ++
 14 files changed, 374 insertions(+), 11 deletions(-)
 create mode 100644 src/bin/lttng-sessiond/ust-instrument.h

diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h
index 51ef9ca..73e40b4 100644
--- a/include/lttng/lttng-error.h
+++ b/include/lttng/lttng-error.h
@@ -140,6 +140,8 @@ enum lttng_error_code {
 	LTTNG_ERR_FILTER_NOMEM           = 107, /* Lack of memory for filter bytecode */
 	LTTNG_ERR_FILTER_EXIST           = 108, /* Filter already exist */
 	LTTNG_ERR_NO_CONSUMER            = 109, /* No consumer exist for the session */
+	LTTNG_ERR_TARGET_INVAL           = 110, /* Invalid instrument target */
+	LTTNG_ERR_TARGET_NOMEM           = 111, /* Lack of memory for instrument target */
 
 	/* MUST be last element */
 	LTTNG_ERR_NR,                           /* Last element */
diff --git a/include/lttng/lttng.h b/include/lttng/lttng.h
index 4ffffd8..a6e018d 100644
--- a/include/lttng/lttng.h
+++ b/include/lttng/lttng.h
@@ -231,11 +231,27 @@ struct lttng_event_function_attr {
 };
 
 /*
+ * Instrument target
+ *
+ * The structures should be initialized to zero before use.
+ */
+#define LTTNG_EVENT_TARGET_PADDING        32
+struct lttng_event_target_attr {
+	int path_len;
+
+	char padding[LTTNG_EVENT_TARGET_PADDING];
+
+	/* This varlen field should always be the last element */
+	char path[0];
+};
+
+/*
  * Generic lttng event
  *
  * The structures should be initialized to zero before use.
  */
-#define LTTNG_EVENT_PADDING1               15
+#define LTTNG_EVENT_PADDING1               \
+	(15 - sizeof(struct lttng_event_target_attr *))
 #define LTTNG_EVENT_PADDING2               LTTNG_SYMBOL_NAME_LEN + 32
 struct lttng_event {
 	enum lttng_event_type type;
@@ -247,6 +263,7 @@ struct lttng_event {
 	int32_t enabled;	/* Does not apply: -1 */
 	pid_t pid;
 	unsigned char filter;	/* filter enabled ? */
+	struct lttng_event_target_attr *target;
 
 	char padding[LTTNG_EVENT_PADDING1];
 
diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am
index 77cc1d2..dce17cb 100644
--- a/src/bin/lttng-sessiond/Makefile.am
+++ b/src/bin/lttng-sessiond/Makefile.am
@@ -11,6 +11,7 @@ lttng_sessiond_SOURCES = utils.c utils.h \
                        kernel.c kernel.h \
                        ust-ctl.h ust-app.h trace-ust.h ust-thread.h \
                        ust-registry.h \
+                       ust-instrument.h \
                        context.c context.h \
                        channel.c channel.h \
                        event.c event.h \
diff --git a/src/bin/lttng-sessiond/cmd.c b/src/bin/lttng-sessiond/cmd.c
index e9fa3b4..c154927 100644
--- a/src/bin/lttng-sessiond/cmd.c
+++ b/src/bin/lttng-sessiond/cmd.c
@@ -235,9 +235,15 @@ static int list_lttng_ust_global_events(char *channel_name,
 			break;
 		case LTTNG_UST_PROBE:
 			tmp[i].type = LTTNG_EVENT_PROBE;
+			memcpy(&tmp[i].attr.probe, &uevent->attr.u.probe,
+					sizeof(struct lttng_ust_probe));
+			/* TODO: List instrument target information */
 			break;
 		case LTTNG_UST_FUNCTION:
 			tmp[i].type = LTTNG_EVENT_FUNCTION;
+			memcpy(&tmp[i].attr.probe, &uevent->attr.u.probe,
+					sizeof(struct lttng_ust_probe));
+			/* TODO: List instrument target information */
 			break;
 		}
 
diff --git a/src/bin/lttng-sessiond/lttng-ust-abi.h b/src/bin/lttng-sessiond/lttng-ust-abi.h
index 98470e4..29fc879 100644
--- a/src/bin/lttng-sessiond/lttng-ust-abi.h
+++ b/src/bin/lttng-sessiond/lttng-ust-abi.h
@@ -100,7 +100,32 @@ struct lttng_ust_stream {
 	 */
 } LTTNG_PACKED;
 
-#define LTTNG_UST_EVENT_PADDING1	16
+/*
+ * Either addr is used, or symbol_name and offset.
+ */
+#define LTTNG_UST_PROBE_PADDING	16
+struct lttng_ust_probe {
+	uint64_t addr;
+
+	uint64_t offset;
+	char symbol_name[LTTNG_UST_SYM_NAME_LEN];
+
+	char padding[LTTNG_UST_PROBE_PADDING];
+} LTTNG_PACKED;
+
+/*
+ * Instrument target
+ */
+#define LTTNG_UST_TARGET_PADDING	32
+struct lttng_ust_target {
+	uint32_t path_len;
+
+	char padding[LTTNG_UST_TARGET_PADDING];
+
+	char path[0];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_EVENT_PADDING1	(16 - sizeof(struct lttng_ust_target *))
 #define LTTNG_UST_EVENT_PADDING2	(LTTNG_UST_SYM_NAME_LEN + 32)
 struct lttng_ust_event {
 	enum lttng_ust_instrumentation instrumentation;
@@ -108,10 +133,12 @@ struct lttng_ust_event {
 
 	enum lttng_ust_loglevel_type loglevel_type;
 	int loglevel;	/* value, -1: all */
+	struct lttng_ust_target *target;
 	char padding[LTTNG_UST_EVENT_PADDING1];
 
 	/* Per instrumentation type configuration */
 	union {
+		struct lttng_ust_probe probe;
 		char padding[LTTNG_UST_EVENT_PADDING2];
 	} u;
 } LTTNG_PACKED;
@@ -275,6 +302,7 @@ struct lttng_ust_filter_bytecode {
 
 /* Event FD commands */
 #define LTTNG_UST_FILTER			_UST_CMD(0xA0)
+#define LTTNG_UST_TARGET			_UST_CMD(0xA1)
 
 #define LTTNG_UST_ROOT_HANDLE	0
 
diff --git a/src/bin/lttng-sessiond/main.c b/src/bin/lttng-sessiond/main.c
index d22e2a6..6c6b60b 100644
--- a/src/bin/lttng-sessiond/main.c
+++ b/src/bin/lttng-sessiond/main.c
@@ -2876,6 +2876,44 @@ skip_domain:
 	}
 	case LTTNG_ENABLE_EVENT:
 	{
+		/* TODO: Handle dynamic instrumentation with filter */
+		struct lttng_event_target_attr *target;
+
+		if (cmd_ctx->lsm->u.enable.event.target) {
+			if (cmd_ctx->lsm->u.enable.target_len
+					< sizeof(struct lttng_event_target_attr)) {
+				ret = LTTNG_ERR_TARGET_INVAL;
+				goto error;
+			}
+
+			target = zmalloc(cmd_ctx->lsm->u.enable.target_len);
+			if (!target) {
+				ret = LTTNG_ERR_TARGET_NOMEM;
+				goto error;
+			}
+
+			/* Receive var. len. data */
+			DBG("Receiving var len data target from client ...");
+			ret = lttcomm_recv_unix_sock(sock, target,
+					cmd_ctx->lsm->u.enable.target_len);
+			if (ret <= 0) {
+				DBG("Nothing recv() from client var len data... continuing");
+				*sock_error = 1;
+				free(target);
+				ret = LTTNG_ERR_TARGET_INVAL;
+				goto error;
+			}
+
+			if ((sizeof(struct lttng_event_target_attr) + target->path_len)
+						!= cmd_ctx->lsm->u.enable.target_len) {
+				free(target);
+				ret = LTTNG_ERR_TARGET_INVAL;
+				goto error;
+			}
+
+			cmd_ctx->lsm->u.enable.event.target = target;
+		}
+
 		ret = cmd_enable_event(cmd_ctx->session, &cmd_ctx->lsm->domain,
 				cmd_ctx->lsm->u.enable.channel_name,
 				&cmd_ctx->lsm->u.enable.event, NULL, kernel_poll_pipe[1]);
diff --git a/src/bin/lttng-sessiond/trace-ust.c b/src/bin/lttng-sessiond/trace-ust.c
index c80d5e7..f5f4122 100644
--- a/src/bin/lttng-sessiond/trace-ust.c
+++ b/src/bin/lttng-sessiond/trace-ust.c
@@ -324,12 +324,23 @@ struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
 	switch (ev->type) {
 	case LTTNG_EVENT_PROBE:
 		lue->attr.instrumentation = LTTNG_UST_PROBE;
+		lue->attr.u.probe.addr = ev->attr.probe.addr;
+		lue->attr.u.probe.offset = ev->attr.probe.offset;
+		strncpy(lue->attr.u.probe.symbol_name,
+				ev->attr.probe.symbol_name, LTTNG_UST_SYM_NAME_LEN);
+		lue->attr.u.probe.symbol_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+		/* Same layout. */
+		lue->attr.target = (struct lttng_ust_target *) ev->target;
 		break;
 	case LTTNG_EVENT_FUNCTION:
 		lue->attr.instrumentation = LTTNG_UST_FUNCTION;
-		break;
-	case LTTNG_EVENT_FUNCTION_ENTRY:
-		lue->attr.instrumentation = LTTNG_UST_FUNCTION;
+		lue->attr.u.probe.addr = ev->attr.probe.addr;
+		lue->attr.u.probe.offset = ev->attr.probe.offset;
+		strncpy(lue->attr.u.probe.symbol_name,
+				ev->attr.probe.symbol_name, LTTNG_UST_SYM_NAME_LEN);
+		lue->attr.u.probe.symbol_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+		/* Same layout. */
+		lue->attr.target = (struct lttng_ust_target *) ev->target;
 		break;
 	case LTTNG_EVENT_TRACEPOINT:
 		lue->attr.instrumentation = LTTNG_UST_TRACEPOINT;
@@ -514,6 +525,8 @@ void trace_ust_destroy_event(struct ltt_ust_event *event)
 	assert(event);
 
 	DBG2("Trace destroy UST event %s", event->attr.name);
+
+	free(event->attr.target);
 	free(event->filter);
 	free(event);
 }
diff --git a/src/bin/lttng-sessiond/ust-app.c b/src/bin/lttng-sessiond/ust-app.c
index 9fe5483..c8333bf 100644
--- a/src/bin/lttng-sessiond/ust-app.c
+++ b/src/bin/lttng-sessiond/ust-app.c
@@ -38,6 +38,7 @@
 #include "ust-app.h"
 #include "ust-consumer.h"
 #include "ust-ctl.h"
+#include "ust-instrument.h"
 #include "utils.h"
 
 /* Next available channel key. Access under next_channel_key_lock. */
@@ -270,6 +271,7 @@ void delete_ust_app_event(int sock, struct ust_app_event *ua_event)
 
 	assert(ua_event);
 
+	free(ua_event->attr.target);
 	free(ua_event->filter);
 
 	if (ua_event->obj != NULL) {
@@ -927,6 +929,28 @@ error:
 }
 
 /*
+ * Allocate a instrument target and copy the given original one.
+ *
+ * Return allocated instrument target or NULL on error.
+ */
+static struct lttng_ust_target *alloc_copy_ust_app_target(
+		struct lttng_ust_target *orig_t)
+{
+	struct lttng_ust_target *target = NULL;
+
+	target = zmalloc(sizeof(*target) + orig_t->path_len);
+	if (!target) {
+		PERROR("zmalloc alloc ust app instrument target");
+		goto error;
+	}
+
+	memcpy(target, orig_t, sizeof(*target) + orig_t->path_len);
+
+error:
+	return target;
+}
+
+/*
  * Allocate a filter and copy the given original filter.
  *
  * Return allocated filter or NULL on error.
@@ -1067,6 +1091,41 @@ error:
 }
 
 /*
+ * Set the target on the tracer.
+ */
+static
+int set_ust_event_target(struct ust_app_event *ua_event,
+		struct ust_app *app)
+{
+	int ret;
+
+	health_code_update();
+
+	if (!ua_event->attr.target) {
+		ret = 0;
+		goto error;
+	}
+
+	ret = ustctl_set_target(app->sock, ua_event->attr.target,
+			ua_event->obj);
+	if (ret < 0) {
+		if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+			ERR("UST app event %s set instrument target failed for app (pid: %d) "
+					"with ret %d", ua_event->attr.name, app->pid, ret);
+		} else {
+			DBG3("UST app set instrument target failed. Application is dead.");
+		}
+		goto error;
+	}
+
+	DBG2("UST instrument target set successfully for event %s", ua_event->name);
+
+error:
+	health_code_update();
+	return ret;
+}
+
+/*
  * Set the filter on the tracer.
  */
 static
@@ -1302,6 +1361,14 @@ int create_ust_event(struct ust_app *app, struct ust_app_session *ua_sess,
 
 	health_code_update();
 
+	/* Set instrument target if one is present. */
+	if (ua_event->attr.target) {
+		ret = set_ust_event_target(ua_event, app);
+		if (ret < 0) {
+			goto error;
+		}
+	}
+
 	/* Set filter if one is present. */
 	if (ua_event->filter) {
 		ret = set_ust_event_filter(ua_event, app);
@@ -1353,6 +1420,13 @@ static void shadow_copy_event(struct ust_app_event *ua_event,
 	/* Copy event attributes */
 	memcpy(&ua_event->attr, &uevent->attr, sizeof(ua_event->attr));
 
+	/* Copy instrument target */
+	if (uevent->attr.target) {
+		ua_event->attr.target =
+			alloc_copy_ust_app_target(uevent->attr.target);
+		/* Target might be NULL here in case of ENONEM. */
+	}
+
 	/* Copy filter bytecode */
 	if (uevent->filter) {
 		ua_event->filter = alloc_copy_ust_app_filter(uevent->filter);
@@ -4775,6 +4849,58 @@ int ust_app_recv_notify(int sock)
 
 		break;
 	}
+	case USTCTL_NOTIFY_CMD_INSTRUMENT:
+	{
+		enum lttng_ust_instrumentation instrumentation;
+		char name[LTTNG_UST_SYM_NAME_LEN], symbol[LTTNG_UST_SYM_NAME_LEN];
+		char object_path[PATH_MAX];
+		uint64_t addr, offset;
+		struct ust_app *app;
+
+		DBG2("UST app ustctl instrument probe received");
+
+		ret = ustctl_recv_instrument_probe(sock, object_path, name,
+				&instrumentation, &addr, symbol, &offset);
+		if (ret < 0) {
+			if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+				ERR("UST app recv instrument failed with ret %d", ret);
+			} else {
+				DBG3("UST app recv instrument failed. Application died");
+			}
+			goto error;
+		}
+
+		rcu_read_lock();
+
+		app = find_app_by_notify_sock(sock);
+		if (app == NULL) {
+			DBG3("UST app instrument failed to find app sock %d", sock);
+			goto error;
+		}
+
+		if (!app->compatible) {
+			goto error;
+		}
+
+		rcu_read_unlock();
+
+		ret = ust_instrument_probe(app, object_path, name, instrumentation,
+				addr, symbol, offset);
+
+		DBG3("UST app replying to instrument probe with pid %u, ret: %d",
+				app->pid, ret);
+
+		ret = ustctl_reply_instrument_probe(sock, ret);
+		if (ret < 0) {
+			if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+				ERR("UST app reply instrument failed with ret %d", ret);
+			} else {
+				DBG3("UST app reply instrument failed. Application died");
+			}
+			goto error;
+		}
+		break;
+	}
 	default:
 		/* Should NEVER happen. */
 		assert(0);
diff --git a/src/bin/lttng-sessiond/ust-instrument.h b/src/bin/lttng-sessiond/ust-instrument.h
new file mode 100644
index 0000000..4332253
--- /dev/null
+++ b/src/bin/lttng-sessiond/ust-instrument.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 - Zifei Tong <soariez at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _LTT_UST_INSTRUMENT_H
+#define _LTT_UST_INSTRUMENT_H
+
+#include <stdint.h>
+
+#include "trace-ust.h"
+
+#if defined(HAVE_UST_INSTRUMENT_PROBE) && defined(HAVE_LIBLTTNG_UST_CTL)
+
+int ust_instrument_probe(struct ust_app* app,
+		const char *object_path,
+		const char *name,
+		enum lttng_ust_instrumentation instrumentation,
+		uint64_t addr,
+		const char *symbol,
+		uint64_t offset);
+
+#else /* HAVE_UST_INSTRUMENT_PROBE && HAVE_LIBLTTNG_UST_CTL */
+
+static inline
+int ust_instrument_probe(struct ust_app *app, const char* object_path,
+		const char* name, enum lttng_ust_instrumentation instrumentation,
+		uint64_t addr, const char *symbol, uint64_t offset)
+{
+	return -ENOSYS;
+}
+
+#endif /* HAVE_UST_INSTRUMENT_PROBE && HAVE_LIBLTTNG_UST_CTL */
+
+#endif /* _LTT_UST_INSTRUEMENT_H */
diff --git a/src/bin/lttng/commands/enable_events.c b/src/bin/lttng/commands/enable_events.c
index 26195af..cd8e1a1 100644
--- a/src/bin/lttng/commands/enable_events.c
+++ b/src/bin/lttng/commands/enable_events.c
@@ -113,14 +113,16 @@ static void usage(FILE *ofp)
 	fprintf(ofp, "                             e.g.:\n");
 	fprintf(ofp, "                               \"*\"\n");
 	fprintf(ofp, "                               \"app_component:na*\"\n");
-	fprintf(ofp, "    --probe (addr | symbol | symbol+offset)\n");
+	fprintf(ofp, "    --probe [object@](addr | symbol | symbol+offset)\n");
 	fprintf(ofp, "                           Dynamic probe.\n");
-	fprintf(ofp, "                           Addr and offset can be octal (0NNN...),\n");
-	fprintf(ofp, "                           decimal (NNN...) or hexadecimal (0xNNN...)\n");
-	fprintf(ofp, "    --function (addr | symbol | symbol+offset)\n");
+	fprintf(ofp, "                           - userspace tracer requires specifying an object to instrument.\n");
+	fprintf(ofp, "                           - Addr and offset can be octal (0NNN...),\n");
+	fprintf(ofp, "                             decimal (NNN...) or hexadecimal (0xNNN...)\n");
+	fprintf(ofp, "    --function [object@](addr | symbol | symbol+offset)\n");
 	fprintf(ofp, "                           Dynamic function entry/return probe.\n");
-	fprintf(ofp, "                           Addr and offset can be octal (0NNN...),\n");
-	fprintf(ofp, "                           decimal (NNN...) or hexadecimal (0xNNN...)\n");
+	fprintf(ofp, "                           - userspace tracer requires specifying an object to instrument.\n");
+	fprintf(ofp, "                           - Addr and offset can be octal (0NNN...),\n");
+	fprintf(ofp, "                             decimal (NNN...) or hexadecimal (0xNNN...)\n");
 #if 0
 	fprintf(ofp, "    --function:entry symbol\n");
 	fprintf(ofp, "                           Function tracer event\n");
@@ -260,6 +262,58 @@ end:
 }
 
 /*
+ * Parse user-space probe options.
+ */
+static int parse_ust_probe_opts(struct lttng_event *ev, char *opt)
+{
+	char *pos;
+	int ret;
+
+	if (opt == NULL) {
+		ret = -1;
+		goto end;
+	}
+
+	/* Check for pathname */
+	/* TODO: support wildcard matching */
+	if ((pos = strrchr(opt, '@')) != NULL) {
+		struct lttng_event_target_attr *target;
+		char fullpath[PATH_MAX];
+		int path_len;
+
+		/* Process relative path */
+		if (opt[0] != '/') {
+			if (getcwd(fullpath, PATH_MAX) == NULL) {
+				goto error;
+			}
+			strncat(fullpath, "/", 1);
+			strncat(fullpath, opt, pos - opt);
+		} else {
+			strncpy(fullpath, opt, pos - opt);
+		}
+
+		path_len = strnlen(fullpath, PATH_MAX);
+		/* Include the tailing '\0' */
+		target = zmalloc(sizeof(struct lttng_event_target_attr) + path_len + 1);
+		target->path_len = path_len + 1;
+
+		strncpy(target->path, fullpath, path_len);
+		target->path[path_len] = '\0';
+		ev->target = target;
+		DBG("probe object %s", ev->target->path);
+		ret = parse_probe_opts(ev, pos+1);
+		goto end;
+	}
+
+error:
+	/* No match */
+	ret = -1;
+
+end:
+	return ret;
+}
+
+/*
  * Maps loglevel from string to value
  */
 static
@@ -556,7 +610,21 @@ static int enable_events(char *session_name)
 				ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
 				break;
 			case LTTNG_EVENT_PROBE:
+				ret = parse_ust_probe_opts(&ev, opt_probe);
+				if (ret < 0) {
+					ERR("Unable to parse probe options");
+					ret = 0;
+					goto error;
+				}
+				break;
 			case LTTNG_EVENT_FUNCTION:
+				ret = parse_ust_probe_opts(&ev, opt_function);
+				if (ret < 0) {
+					ERR("Unable to parse function probe options");
+					ret = 0;
+					goto error;
+				}
+				break;
 			case LTTNG_EVENT_FUNCTION_ENTRY:
 			case LTTNG_EVENT_SYSCALL:
 			default:
@@ -646,6 +714,10 @@ error:
 	}
 	lttng_destroy_handle(handle);
 
+	if (ev.target) {
+		free(ev.target);
+	}
+
 	return ret;
 }
 
diff --git a/src/bin/lttng/commands/list.c b/src/bin/lttng/commands/list.c
index 1c7085d..52fb84d 100644
--- a/src/bin/lttng/commands/list.c
+++ b/src/bin/lttng/commands/list.c
@@ -240,6 +240,7 @@ static void print_events(struct lttng_event *event)
 			MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
 			MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
 		}
+		/* TODO: add support to print instrument object path */
 		break;
 	case LTTNG_EVENT_PROBE:
 		MSG("%s%s (type: probe)%s%s", indent6,
@@ -251,6 +252,7 @@ static void print_events(struct lttng_event *event)
 			MSG("%soffset: 0x%" PRIx64, indent8, event->attr.probe.offset);
 			MSG("%ssymbol: %s", indent8, event->attr.probe.symbol_name);
 		}
+		/* TODO: add support to print instrument object path */
 		break;
 	case LTTNG_EVENT_FUNCTION_ENTRY:
 		MSG("%s%s (type: function)%s%s", indent6,
diff --git a/src/common/error.c b/src/common/error.c
index 42ed06f..d48e53a 100644
--- a/src/common/error.c
+++ b/src/common/error.c
@@ -112,6 +112,8 @@ static const char *error_string_array[] = {
 	[ ERROR_INDEX(LTTNG_ERR_SNAPSHOT_OUTPUT_EXIST) ] = "Snapshot output already exists",
 	[ ERROR_INDEX(LTTNG_ERR_START_SESSION_ONCE) ] = "Session needs to be started once",
 	[ ERROR_INDEX(LTTNG_ERR_SNAPSHOT_FAIL) ] = "Snapshot record failed",
+	[ ERROR_INDEX(LTTNG_ERR_TARGET_INVAL) ] = "Invalid instrument target",
+	[ ERROR_INDEX(LTTNG_ERR_TARGET_NOMEM) ] = "Not enough memory for instrument target",
 
 	/* Last element */
 	[ ERROR_INDEX(LTTNG_ERR_NR) ] = "Unknown error code"
diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h
index c52a6ca..294e185 100644
--- a/src/common/sessiond-comm/sessiond-comm.h
+++ b/src/common/sessiond-comm/sessiond-comm.h
@@ -224,6 +224,8 @@ struct lttcomm_session_msg {
 			struct lttng_event event;
 			/* Length of following bytecode for filter. */
 			uint32_t bytecode_len;
+			/* Length of following instrument target. */
+			uint32_t target_len;
 		} LTTNG_PACKED enable;
 		/* Create channel */
 		struct {
diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c
index daa4a73..695e9ee 100644
--- a/src/lib/lttng-ctl/lttng-ctl.c
+++ b/src/lib/lttng-ctl/lttng-ctl.c
@@ -699,6 +699,13 @@ int lttng_enable_event(struct lttng_handle *handle,
 	lttng_ctl_copy_string(lsm.session.name, handle->session_name,
 			sizeof(lsm.session.name));
 
+	if (ev->target) {
+		lsm.u.enable.target_len = ev->target->path_len
+			+ sizeof(struct lttng_event_target_attr);
+		return lttng_ctl_ask_sessiond_varlen(&lsm, ev->target,
+					lsm.u.enable.target_len, NULL);
+	}
+
 	return lttng_ctl_ask_sessiond(&lsm, NULL);
 }
 
-- 
1.8.4




More information about the lttng-dev mailing list