uprobe: transmit binary file descritptor through lttng_payload
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 19 Jun 2020 22:44:56 +0000 (18:44 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 27 Jul 2020 20:31:40 +0000 (16:31 -0400)
Adapt the userspace probe objects to use the lttng_payload interface.
This streamlines the acquisition of the file descriptors when those
objects are serialized.

File descriptors are transmitted in both directions between liblttng-ctl
and the session daemon making it possible (and safe) to compare
userspace probe instances.

Currently the event listing API does not allow us to express userspace
probe locations that contain a file descriptor. This is an unfortunate
consequence of returning a "flat" array to list events.

Indeed, we can't store a file descriptor in the userspace probe
locations returned to the user in this API since the destructors of the
probe locations are never called. The user simply free()'s the returned
array, which would leak the file descriptors.

The consequence of this is that we can't allow the creation of event
rules using a probe location returned by an lttng_list_events() call.
This is not unsolvable, but I'm not sure if there really is a use-case
for this.

Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I0f710cbe9deabfd163206fd03618eba183f3d1d2

16 files changed:
include/lttng/userspace-probe-internal.h
src/bin/lttng-relayd/Makefile.am
src/bin/lttng-sessiond/client.c
src/bin/lttng-sessiond/cmd.c
src/bin/lttng-sessiond/cmd.h
src/bin/lttng-sessiond/trace-kernel.c
src/common/payload-view.c
src/common/payload-view.h
src/common/payload.c
src/common/payload.h
src/common/sessiond-comm/sessiond-comm.h
src/common/unix.c
src/common/unix.h
src/common/userspace-probe.c
src/lib/lttng-ctl/lttng-ctl-helper.h
src/lib/lttng-ctl/lttng-ctl.c

index fe356b9747d351cbe8229e37be8db04c8f05d20b..d9e5de254c6937cae82495c5e7a15a837b46476f 100644 (file)
 
 #include <lttng/userspace-probe.h>
 #include <common/macros.h>
-#include <common/dynamic-buffer.h>
-#include <common/buffer-view.h>
+#include <stdbool.h>
+
+struct lttng_payload;
+struct lttng_payload_view;
+struct lttng_dynamic_buffer;
 
 typedef bool (*userspace_probe_location_equal_cb)(
                const struct lttng_userspace_probe_location *a,
@@ -117,12 +120,11 @@ struct lttng_userspace_probe_location_tracepoint {
 LTTNG_HIDDEN
 int lttng_userspace_probe_location_serialize(
                const struct lttng_userspace_probe_location *location,
-               struct lttng_dynamic_buffer *buffer,
-               int *binary_fd);
+               struct lttng_payload *payload);
 
 LTTNG_HIDDEN
-int lttng_userspace_probe_location_create_from_buffer(
-               const struct lttng_buffer_view *buffer,
+int lttng_userspace_probe_location_create_from_payload(
+               struct lttng_payload_view *view,
                struct lttng_userspace_probe_location **probe_location);
 
 LTTNG_HIDDEN
index 80ee6a70b4d4a0df69c0b216def8c15ad7b2b2a3..9bc1523e0c04d0d1a83b55f277f2b8aecb13f443 100644 (file)
@@ -29,9 +29,9 @@ lttng_relayd_SOURCES = main.c lttng-relayd.h utils.h utils.c cmd.h \
 
 # link on liblttngctl for check if relayd is already alive.
 lttng_relayd_LDADD = -lurcu-common -lurcu \
+               $(top_builddir)/src/common/libcommon.la \
                $(top_builddir)/src/common/sessiond-comm/libsessiond-comm.la \
                $(top_builddir)/src/common/hashtable/libhashtable.la \
-               $(top_builddir)/src/common/libcommon.la \
                $(top_builddir)/src/common/compat/libcompat.la \
                $(top_builddir)/src/common/index/libindex.la \
                $(top_builddir)/src/common/health/libhealth.la \
index 0238538501b04117cae42280b01a57d3a3c647c3..74bbbe9b2e05e3be7f94a1cba1330aae6d7658ba 100644 (file)
@@ -14,6 +14,8 @@
 #include "common/payload.h"
 #include "common/payload-view.h"
 #include "common/sessiond-comm/sessiond-comm.h"
+#include "common/payload.h"
+#include "common/payload-view.h"
 #include "lttng/lttng-error.h"
 #include "lttng/tracker.h"
 #include <common/compat/getenv.h>
@@ -90,6 +92,7 @@ static int setup_lttng_msg(struct command_ctx *cmd_ctx,
        };
 
        lttng_dynamic_buffer_set_size(&cmd_ctx->reply_payload.buffer, 0);
+       lttng_dynamic_array_clear(&cmd_ctx->reply_payload._fds);
 
        cmd_ctx->lttng_msg_size = total_msg_size;
 
@@ -124,6 +127,48 @@ end:
        return ret;
 }
 
+static int setup_empty_lttng_msg(struct command_ctx *cmd_ctx)
+{
+       int ret;
+       const struct lttcomm_lttng_msg llm = {};
+
+       lttng_dynamic_buffer_set_size(&cmd_ctx->reply_payload.buffer, 0);
+
+       /* Append place-holder reply header. */
+       ret = lttng_dynamic_buffer_append(
+                       &cmd_ctx->reply_payload.buffer, &llm, sizeof(llm));
+       if (ret) {
+               goto end;
+       }
+
+       cmd_ctx->lttng_msg_size = sizeof(llm);
+end:
+       return ret;
+}
+
+static void update_lttng_msg(struct command_ctx *cmd_ctx, size_t cmd_header_len,
+               size_t payload_len)
+{
+       const size_t header_len = sizeof(struct lttcomm_lttng_msg);
+       const size_t total_msg_size = header_len + cmd_header_len + payload_len;
+       const struct lttcomm_lttng_msg llm = {
+               .cmd_type = cmd_ctx->lsm.cmd_type,
+               .pid = cmd_ctx->lsm.domain.attr.pid,
+               .cmd_header_size = cmd_header_len,
+               .data_size = payload_len,
+       };
+       struct lttcomm_lttng_msg *p_llm;
+
+       assert(cmd_ctx->reply_payload.buffer.size >= sizeof(llm));
+
+       p_llm = (typeof(p_llm)) cmd_ctx->reply_payload.buffer.data;
+
+       /* Update existing header. */
+       memcpy(p_llm, &llm, sizeof(llm));
+
+       cmd_ctx->lttng_msg_size = total_msg_size;
+}
+
 /*
  * Start the thread_manage_consumer. This must be done after a lttng-consumerd
  * exec or it will fail.
@@ -549,16 +594,15 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
 {
        int fd, ret;
        struct lttng_userspace_probe_location *probe_location;
-       const struct lttng_userspace_probe_location_lookup_method *lookup = NULL;
-       struct lttng_dynamic_buffer probe_location_buffer;
-       struct lttng_buffer_view buffer_view;
+       struct lttng_payload probe_location_payload;
 
        /*
-        * Create a buffer to store the serialized version of the probe
+        * Create a payload to store the serialized version of the probe
         * location.
         */
-       lttng_dynamic_buffer_init(&probe_location_buffer);
-       ret = lttng_dynamic_buffer_set_size(&probe_location_buffer,
+       lttng_payload_init(&probe_location_payload);
+
+       ret = lttng_dynamic_buffer_set_size(&probe_location_payload.buffer,
                        cmd_ctx->lsm.u.enable.userspace_probe_location_len);
        if (ret) {
                ret = LTTNG_ERR_NOMEM;
@@ -568,27 +612,11 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
        /*
         * Receive the probe location.
         */
-       ret = lttcomm_recv_unix_sock(sock, probe_location_buffer.data,
-                       probe_location_buffer.size);
+       ret = lttcomm_recv_unix_sock(sock, probe_location_payload.buffer.data,
+                       probe_location_payload.buffer.size);
        if (ret <= 0) {
                DBG("Nothing recv() from client var len data... continuing");
                *sock_error = 1;
-               lttng_dynamic_buffer_reset(&probe_location_buffer);
-               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
-               goto error;
-       }
-
-       buffer_view = lttng_buffer_view_from_dynamic_buffer(
-                       &probe_location_buffer, 0, probe_location_buffer.size);
-
-       /*
-        * Extract the probe location from the serialized version.
-        */
-       ret = lttng_userspace_probe_location_create_from_buffer(
-                               &buffer_view, &probe_location);
-       if (ret < 0) {
-               WARN("Failed to create a userspace probe location from the received buffer");
-               lttng_dynamic_buffer_reset( &probe_location_buffer);
                ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
                goto error;
        }
@@ -605,35 +633,23 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
                goto error;
        }
 
-       /*
-        * Set the file descriptor received from the client through the unix
-        * socket in the probe location.
-        */
-       lookup = lttng_userspace_probe_location_get_lookup_method(probe_location);
-       if (!lookup) {
-               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
+       ret = lttng_payload_push_fd(&probe_location_payload, fd);
+       if (ret) {
+               ERR("Failed to add userspace probe file descriptor to payload");
+               ret = LTTNG_ERR_NOMEM;
                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:
-               ret = lttng_userspace_probe_location_function_set_binary_fd(
-                               probe_location, fd);
-               break;
-       case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT:
-               ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
-                               probe_location, fd);
-               break;
-       default:
-               ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
-               goto error;
-       }
+       {
+               struct lttng_payload_view view = lttng_payload_view_from_payload(
+                       &probe_location_payload, 0, -1);
 
-       if (ret) {
+               /* Extract the probe location from the serialized version. */
+               ret = lttng_userspace_probe_location_create_from_payload(
+                               &view, &probe_location);
+       }
+       if (ret < 0) {
+               WARN("Failed to create a userspace probe location from the received buffer");
                ret = LTTNG_ERR_PROBE_LOCATION_INVAL;
                goto error;
        }
@@ -645,8 +661,8 @@ static int receive_userspace_probe(struct command_ctx *cmd_ctx, int sock,
                goto error;
        }
 
-       lttng_dynamic_buffer_reset(&probe_location_buffer);
 error:
+       lttng_payload_reset(&probe_location_payload);
        return ret;
 }
 
@@ -1739,32 +1755,34 @@ error_add_context:
        }
        case LTTNG_LIST_EVENTS:
        {
-               ssize_t nb_event;
-               struct lttng_event *events = NULL;
-               struct lttcomm_event_command_header cmd_header;
-               size_t total_size;
-
-               memset(&cmd_header, 0, sizeof(cmd_header));
-               /* Extended infos are included at the end of events */
-               nb_event = cmd_list_events(cmd_ctx->lsm.domain.type,
-                       cmd_ctx->session, cmd_ctx->lsm.u.list.channel_name,
-                       &events, &total_size);
-
-               if (nb_event < 0) {
-                       /* Return value is a negative lttng_error_code. */
-                       ret = -nb_event;
-                       goto error;
+               ssize_t list_ret;
+               struct lttcomm_event_command_header cmd_header = {};
+               size_t original_payload_size;
+               size_t payload_size;
+
+               ret = setup_empty_lttng_msg(cmd_ctx);
+               if (ret) {
+                       ret = LTTNG_ERR_NOMEM;
+                       goto setup_error;
                }
 
-               cmd_header.nb_events = nb_event;
-               ret = setup_lttng_msg(cmd_ctx, events, total_size,
-                       &cmd_header, sizeof(cmd_header));
-               free(events);
+               original_payload_size = cmd_ctx->reply_payload.buffer.size;
 
-               if (ret < 0) {
-                       goto setup_error;
+               /* Extended infos are included at the end of the payload. */
+               list_ret = cmd_list_events(cmd_ctx->lsm.domain.type,
+                               cmd_ctx->session,
+                               cmd_ctx->lsm.u.list.channel_name,
+                               &cmd_ctx->reply_payload);
+               if (list_ret < 0) {
+                       /* Return value is a negative lttng_error_code. */
+                       ret = -list_ret;
+                       goto error;
                }
 
+               payload_size = cmd_ctx->reply_payload.buffer.size -
+                               sizeof(cmd_header) - original_payload_size;
+               update_lttng_msg(cmd_ctx, sizeof(cmd_header), payload_size);
+
                ret = LTTNG_OK;
                break;
        }
@@ -2250,6 +2268,7 @@ static void *thread_manage_clients(void *data)
                cmd_ctx.session = NULL;
                lttng_dynamic_buffer_set_size(&cmd_ctx.reply_payload.buffer, 0);
                lttng_dynamic_array_clear(&cmd_ctx.reply_payload._fds);
+               cmd_ctx.lttng_msg_size = 0;
 
                DBG("Accepting client command ...");
 
@@ -2384,13 +2403,15 @@ static void *thread_manage_clients(void *data)
                                        lttng_payload_view_from_payload(
                                                        &cmd_ctx.reply_payload,
                                                        0, -1);
-                       const struct lttcomm_lttng_msg *llm = (typeof(
+                       struct lttcomm_lttng_msg *llm = (typeof(
                                        llm)) cmd_ctx.reply_payload.buffer.data;
 
                        assert(cmd_ctx.reply_payload.buffer.size >=
                               sizeof(llm));
                        assert(cmd_ctx.lttng_msg_size == cmd_ctx.reply_payload.buffer.size);
 
+                       llm->fd_count = lttng_payload_view_get_fd_count(&view);
+
                        DBG("Sending response (size: %d, retcode: %s (%d))",
                                        cmd_ctx.lttng_msg_size,
                                        lttng_strerror(-llm->ret_code),
index 8b78e627f88d545515fbd2125ffd7aa448e7efff..37c0e31ce9dfe73b9713088c83ed1427f83ad389 100644 (file)
@@ -395,95 +395,69 @@ end:
        }
 }
 
-static int increment_extended_len(const char *filter_expression,
-               struct lttng_event_exclusion *exclusion,
-               const struct lttng_userspace_probe_location *probe_location,
-               size_t *extended_len)
-{
-       int ret = 0;
-
-       *extended_len += sizeof(struct lttcomm_event_extended_header);
-
-       if (filter_expression) {
-               *extended_len += strlen(filter_expression) + 1;
-       }
-
-       if (exclusion) {
-               *extended_len += exclusion->count * LTTNG_SYMBOL_NAME_LEN;
-       }
-
-       if (probe_location) {
-               ret = lttng_userspace_probe_location_serialize(probe_location,
-                               NULL, NULL);
-               if (ret < 0) {
-                       goto end;
-               }
-               *extended_len += ret;
-       }
-       ret = 0;
-end:
-       return ret;
-}
-
 static int append_extended_info(const char *filter_expression,
                struct lttng_event_exclusion *exclusion,
                struct lttng_userspace_probe_location *probe_location,
-               void **extended_at)
+               struct lttng_payload *payload)
 {
        int ret = 0;
        size_t filter_len = 0;
        size_t nb_exclusions = 0;
        size_t userspace_probe_location_len = 0;
-       struct lttng_dynamic_buffer location_buffer;
-       struct lttcomm_event_extended_header extended_header;
+       struct lttcomm_event_extended_header extended_header = {};
+       struct lttcomm_event_extended_header *p_extended_header;
+       const size_t original_payload_size = payload->buffer.size;
+
+       ret = lttng_dynamic_buffer_append(&payload->buffer, &extended_header,
+                       sizeof(extended_header));
+       if (ret) {
+               goto end;
+       }
 
        if (filter_expression) {
                filter_len = strlen(filter_expression) + 1;
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
+                               filter_expression, filter_len);
+               if (ret) {
+                       goto end;
+               }
        }
 
        if (exclusion) {
+               const size_t len = exclusion->count * LTTNG_SYMBOL_NAME_LEN;
+
                nb_exclusions = exclusion->count;
+
+               ret = lttng_dynamic_buffer_append(
+                               &payload->buffer, &exclusion->names, len);
+               if (ret) {
+                       goto end;
+               }
        }
 
        if (probe_location) {
-               lttng_dynamic_buffer_init(&location_buffer);
+               const size_t size_before_probe = payload->buffer.size;
+
                ret = lttng_userspace_probe_location_serialize(probe_location,
-                               &location_buffer, NULL);
+                               payload);
                if (ret < 0) {
                        ret = -1;
                        goto end;
                }
-               userspace_probe_location_len = location_buffer.size;
+
+               userspace_probe_location_len =
+                               payload->buffer.size - size_before_probe;
        }
 
        /* Set header fields */
-       extended_header.filter_len = filter_len;
-       extended_header.nb_exclusions = nb_exclusions;
-       extended_header.userspace_probe_location_len = userspace_probe_location_len;
+       p_extended_header = (struct lttcomm_event_extended_header *)
+                       (payload->buffer.data + original_payload_size);
 
-       /* Copy header */
-       memcpy(*extended_at, &extended_header, sizeof(extended_header));
-       *extended_at += sizeof(extended_header);
+       p_extended_header->filter_len = filter_len;
+       p_extended_header->nb_exclusions = nb_exclusions;
+       p_extended_header->userspace_probe_location_len =
+                       userspace_probe_location_len;
 
-       /* Copy filter string */
-       if (filter_expression) {
-               memcpy(*extended_at, filter_expression, filter_len);
-               *extended_at += filter_len;
-       }
-
-       /* Copy exclusion names */
-       if (exclusion) {
-               size_t len = nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
-
-               memcpy(*extended_at, &exclusion->names, len);
-               *extended_at += len;
-       }
-
-       if (probe_location) {
-               memcpy(*extended_at, location_buffer.data, location_buffer.size);
-               *extended_at += location_buffer.size;
-               lttng_dynamic_buffer_reset(&location_buffer);
-       }
        ret = 0;
 end:
        return ret;
@@ -495,89 +469,55 @@ end:
  * Return number of events in list on success or else a negative value.
  */
 static int list_lttng_agent_events(struct agent *agt,
-               struct lttng_event **events, size_t *total_size)
+               struct lttng_payload *payload)
 {
-       int i = 0, ret = 0;
-       unsigned int nb_event = 0;
-       struct agent_event *event;
-       struct lttng_event *tmp_events = NULL;
+       int nb_events = 0, ret = 0;
+       const struct agent_event *agent_event;
        struct lttng_ht_iter iter;
-       size_t extended_len = 0;
-       void *extended_at;
 
        assert(agt);
-       assert(events);
 
        DBG3("Listing agent events");
 
        rcu_read_lock();
-       nb_event = lttng_ht_get_count(agt->events);
-       rcu_read_unlock();
-       if (nb_event == 0) {
-               ret = nb_event;
-               *total_size = 0;
-               goto error;
-       }
-
-       /* Compute required extended infos size */
-       extended_len = nb_event * sizeof(struct lttcomm_event_extended_header);
-
-       /*
-        * This is only valid because the commands which add events are
-        * processed in the same thread as the listing.
-        */
-       rcu_read_lock();
-       cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) {
-               ret = increment_extended_len(event->filter_expression, NULL, NULL,
-                               &extended_len);
+       cds_lfht_for_each_entry (
+                       agt->events->ht, &iter.iter, agent_event, node.node) {
+               struct lttng_event event = {
+                       .enabled = agent_event->enabled,
+                       .loglevel = agent_event->loglevel_value,
+                       .loglevel_type = agent_event->loglevel_type,
+               };
+
+               strncpy(event.name, agent_event->name, sizeof(event.name));
+               event.name[sizeof(event.name) - 1] = '\0';
+
+               ret = lttng_dynamic_buffer_append(
+                               &payload->buffer, &event, sizeof(event));
                if (ret) {
-                       DBG("Error computing the length of extended info message");
-                       ret = -LTTNG_ERR_FATAL;
-                       goto error;
+                       ERR("Failed to append event to payload");
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
                }
-       }
-       rcu_read_unlock();
 
-       *total_size = nb_event * sizeof(*tmp_events) + extended_len;
-       tmp_events = zmalloc(*total_size);
-       if (!tmp_events) {
-               PERROR("zmalloc agent events session");
-               ret = -LTTNG_ERR_FATAL;
-               goto error;
+               nb_events++;
        }
 
-       extended_at = ((uint8_t *) tmp_events) +
-               nb_event * sizeof(struct lttng_event);
-
-       rcu_read_lock();
-       cds_lfht_for_each_entry(agt->events->ht, &iter.iter, event, node.node) {
-               strncpy(tmp_events[i].name, event->name, sizeof(tmp_events[i].name));
-               tmp_events[i].name[sizeof(tmp_events[i].name) - 1] = '\0';
-               tmp_events[i].enabled = event->enabled;
-               tmp_events[i].loglevel = event->loglevel_value;
-               tmp_events[i].loglevel_type = event->loglevel_type;
-               i++;
-
-               /* Append extended info */
-               ret = append_extended_info(event->filter_expression, NULL, NULL,
-                               &extended_at);
+       cds_lfht_for_each_entry (
+               agt->events->ht, &iter.iter, agent_event, node.node) {
+               /* Append extended info. */
+               ret = append_extended_info(agent_event->filter_expression, NULL,
+                               NULL, payload);
                if (ret) {
-                       DBG("Error appending extended info message");
-                       ret = -LTTNG_ERR_FATAL;
-                       goto error;
+                       ERR("Failed to append extended event info to payload");
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
                }
        }
 
-       *events = tmp_events;
-       ret = nb_event;
-       assert(nb_event == i);
-
+       ret = nb_events;
 end:
        rcu_read_unlock();
        return ret;
-error:
-       free(tmp_events);
-       goto end;
 }
 
 /*
@@ -585,23 +525,20 @@ error:
  */
 static int list_lttng_ust_global_events(char *channel_name,
                struct ltt_ust_domain_global *ust_global,
-               struct lttng_event **events, size_t *total_size)
+               struct lttng_payload *payload)
 {
-       int i = 0, ret = 0;
-       unsigned int nb_event = 0;
+       int ret = 0;
+       unsigned int nb_events = 0;
        struct lttng_ht_iter iter;
-       struct lttng_ht_node_str *node;
-       struct ltt_ust_channel *uchan;
-       struct ltt_ust_event *uevent;
-       struct lttng_event *tmp;
-       size_t extended_len = 0;
-       void *extended_at;
+       const struct lttng_ht_node_str *node;
+       const struct ltt_ust_channel *uchan;
+       const struct ltt_ust_event *uevent;
 
        DBG("Listing UST global events for channel %s", channel_name);
 
        rcu_read_lock();
 
-       lttng_ht_lookup(ust_global->channels, (void *)channel_name, &iter);
+       lttng_ht_lookup(ust_global->channels, (void *) channel_name, &iter);
        node = lttng_ht_iter_get_node_str(&iter);
        if (node == NULL) {
                ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
@@ -610,99 +547,75 @@ static int list_lttng_ust_global_events(char *channel_name,
 
        uchan = caa_container_of(&node->node, struct ltt_ust_channel, node.node);
 
-       nb_event = lttng_ht_get_count(uchan->events);
-       if (nb_event == 0) {
-               ret = nb_event;
-               *total_size = 0;
-               goto end;
-       }
-
-       DBG3("Listing UST global %d events", nb_event);
+       DBG3("Listing UST global events");
 
-       /* Compute required extended infos size */
        cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
+               struct lttng_event event = {};
+
                if (uevent->internal) {
-                       nb_event--;
                        continue;
                }
 
-               ret = increment_extended_len(uevent->filter_expression,
-                       uevent->exclusion, NULL, &extended_len);
-               if (ret) {
-                       DBG("Error computing the length of extended info message");
-                       ret = -LTTNG_ERR_FATAL;
-                       goto end;
-               }
-       }
-       if (nb_event == 0) {
-               /* All events are internal, skip. */
-               ret = 0;
-               *total_size = 0;
-               goto end;
-       }
-
-       *total_size = nb_event * sizeof(struct lttng_event) + extended_len;
-       tmp = zmalloc(*total_size);
-       if (tmp == NULL) {
-               ret = -LTTNG_ERR_FATAL;
-               goto end;
-       }
-
-       extended_at = ((uint8_t *) tmp) + nb_event * sizeof(struct lttng_event);
+               strncpy(event.name, uevent->attr.name, sizeof(event.name));
+               event.name[sizeof(event.name) - 1] = '\0';
 
-       cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
-               if (uevent->internal) {
-                       /* This event should remain hidden from clients */
-                       continue;
-               }
-               strncpy(tmp[i].name, uevent->attr.name, LTTNG_SYMBOL_NAME_LEN);
-               tmp[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
-               tmp[i].enabled = uevent->enabled;
+               event.enabled = uevent->enabled;
 
                switch (uevent->attr.instrumentation) {
                case LTTNG_UST_TRACEPOINT:
-                       tmp[i].type = LTTNG_EVENT_TRACEPOINT;
+                       event.type = LTTNG_EVENT_TRACEPOINT;
                        break;
                case LTTNG_UST_PROBE:
-                       tmp[i].type = LTTNG_EVENT_PROBE;
+                       event.type = LTTNG_EVENT_PROBE;
                        break;
                case LTTNG_UST_FUNCTION:
-                       tmp[i].type = LTTNG_EVENT_FUNCTION;
+                       event.type = LTTNG_EVENT_FUNCTION;
                        break;
                }
 
-               tmp[i].loglevel = uevent->attr.loglevel;
+               event.loglevel = uevent->attr.loglevel;
                switch (uevent->attr.loglevel_type) {
                case LTTNG_UST_LOGLEVEL_ALL:
-                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
+                       event.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
                        break;
                case LTTNG_UST_LOGLEVEL_RANGE:
-                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
+                       event.loglevel_type = LTTNG_EVENT_LOGLEVEL_RANGE;
                        break;
                case LTTNG_UST_LOGLEVEL_SINGLE:
-                       tmp[i].loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
+                       event.loglevel_type = LTTNG_EVENT_LOGLEVEL_SINGLE;
                        break;
                }
+
                if (uevent->filter) {
-                       tmp[i].filter = 1;
+                       event.filter = 1;
                }
+
                if (uevent->exclusion) {
-                       tmp[i].exclusion = 1;
+                       event.exclusion = 1;
                }
-               i++;
 
-               /* Append extended info */
+               ret = lttng_dynamic_buffer_append(&payload->buffer, &event, sizeof(event));
+               if (ret) {
+                       ERR("Failed to append event to payload");
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+
+               nb_events++;
+       }
+
+       cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
+               /* Append extended info. */
                ret = append_extended_info(uevent->filter_expression,
-                       uevent->exclusion, NULL, &extended_at);
+                               uevent->exclusion, NULL, payload);
                if (ret) {
-                       DBG("Error appending extended info message");
+                       ERR("Failed to append extended event info to payload");
                        ret = -LTTNG_ERR_FATAL;
                        goto end;
                }
        }
 
-       ret = nb_event;
-       *events = tmp;
+       ret = nb_events;
 end:
        rcu_read_unlock();
        return ret;
@@ -713,14 +626,12 @@ end:
  */
 static int list_lttng_kernel_events(char *channel_name,
                struct ltt_kernel_session *kernel_session,
-               struct lttng_event **events, size_t *total_size)
+               struct lttng_payload *payload)
 {
-       int i = 0, ret;
+       int ret;
        unsigned int nb_event;
-       struct ltt_kernel_event *event;
-       struct ltt_kernel_channel *kchan;
-       size_t extended_len = 0;
-       void *extended_at;
+       const struct ltt_kernel_event *kevent;
+       const struct ltt_kernel_channel *kchan;
 
        kchan = trace_kernel_get_channel_by_name(channel_name, kernel_session);
        if (kchan == NULL) {
@@ -732,69 +643,42 @@ static int list_lttng_kernel_events(char *channel_name,
 
        DBG("Listing events for channel %s", kchan->channel->name);
 
-       if (nb_event == 0) {
-               *total_size = 0;
-               *events = NULL;
-               goto end;
-       }
-
-       /* Compute required extended infos size */
-       cds_list_for_each_entry(event, &kchan->events_list.head, list) {
-               ret = increment_extended_len(event->filter_expression, NULL,
-                       event->userspace_probe_location,
-                       &extended_len);
-               if (ret) {
-                       DBG("Error computing the length of extended info message");
-                       ret = -LTTNG_ERR_FATAL;
-                       goto error;
-               }
-       }
-
-       *total_size = nb_event * sizeof(struct lttng_event) + extended_len;
-       *events = zmalloc(*total_size);
-       if (*events == NULL) {
-               ret = -LTTNG_ERR_FATAL;
-               goto error;
-       }
+       /* Kernel channels */
+       cds_list_for_each_entry(kevent, &kchan->events_list.head , list) {
+               struct lttng_event event = {};
 
-       extended_at = ((void *) *events) +
-               nb_event * sizeof(struct lttng_event);
+               strncpy(event.name, kevent->event->name, sizeof(event.name));
+               event.name[sizeof(event.name) - 1] = '\0';
+               event.enabled = kevent->enabled;
+               event.filter = (unsigned char) !!kevent->filter_expression;
 
-       /* Kernel channels */
-       cds_list_for_each_entry(event, &kchan->events_list.head , list) {
-               strncpy((*events)[i].name, event->event->name, LTTNG_SYMBOL_NAME_LEN);
-               (*events)[i].name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
-               (*events)[i].enabled = event->enabled;
-               (*events)[i].filter =
-                               (unsigned char) !!event->filter_expression;
-
-               switch (event->event->instrumentation) {
+               switch (kevent->event->instrumentation) {
                case LTTNG_KERNEL_TRACEPOINT:
-                       (*events)[i].type = LTTNG_EVENT_TRACEPOINT;
+                       event.type = LTTNG_EVENT_TRACEPOINT;
                        break;
                case LTTNG_KERNEL_KRETPROBE:
-                       (*events)[i].type = LTTNG_EVENT_FUNCTION;
-                       memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe,
+                       event.type = LTTNG_EVENT_FUNCTION;
+                       memcpy(&event.attr.probe, &kevent->event->u.kprobe,
                                        sizeof(struct lttng_kernel_kprobe));
                        break;
                case LTTNG_KERNEL_KPROBE:
-                       (*events)[i].type = LTTNG_EVENT_PROBE;
-                       memcpy(&(*events)[i].attr.probe, &event->event->u.kprobe,
+                       event.type = LTTNG_EVENT_PROBE;
+                       memcpy(&event.attr.probe, &kevent->event->u.kprobe,
                                        sizeof(struct lttng_kernel_kprobe));
                        break;
                case LTTNG_KERNEL_UPROBE:
-                       (*events)[i].type = LTTNG_EVENT_USERSPACE_PROBE;
+                       event.type = LTTNG_EVENT_USERSPACE_PROBE;
                        break;
                case LTTNG_KERNEL_FUNCTION:
-                       (*events)[i].type = LTTNG_EVENT_FUNCTION;
-                       memcpy(&((*events)[i].attr.ftrace), &event->event->u.ftrace,
+                       event.type = LTTNG_EVENT_FUNCTION;
+                       memcpy(&event.attr.ftrace, &kevent->event->u.ftrace,
                                        sizeof(struct lttng_kernel_function));
                        break;
                case LTTNG_KERNEL_NOOP:
-                       (*events)[i].type = LTTNG_EVENT_NOOP;
+                       event.type = LTTNG_EVENT_NOOP;
                        break;
                case LTTNG_KERNEL_SYSCALL:
-                       (*events)[i].type = LTTNG_EVENT_SYSCALL;
+                       event.type = LTTNG_EVENT_SYSCALL;
                        break;
                case LTTNG_KERNEL_ALL:
                        /* fall-through. */
@@ -802,11 +686,20 @@ static int list_lttng_kernel_events(char *channel_name,
                        assert(0);
                        break;
                }
-               i++;
 
-               /* Append extended info */
-               ret = append_extended_info(event->filter_expression, NULL,
-                       event->userspace_probe_location, &extended_at);
+               ret = lttng_dynamic_buffer_append(
+                               &payload->buffer, &event, sizeof(event));
+               if (ret) {
+                       ERR("Failed to append event to payload");
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+       }
+
+       cds_list_for_each_entry(kevent, &kchan->events_list.head , list) {
+               /* Append extended info. */
+               ret = append_extended_info(kevent->filter_expression, NULL,
+                               kevent->userspace_probe_location, payload);
                if (ret) {
                        DBG("Error appending extended info message");
                        ret = -LTTNG_ERR_FATAL;
@@ -816,7 +709,6 @@ static int list_lttng_kernel_events(char *channel_name,
 
 end:
        return nb_event;
-
 error:
        return ret;
 }
@@ -3729,25 +3621,33 @@ end:
  */
 ssize_t cmd_list_events(enum lttng_domain_type domain,
                struct ltt_session *session, char *channel_name,
-               struct lttng_event **events, size_t *total_size)
+               struct lttng_payload *payload)
 {
        int ret = 0;
-       ssize_t nb_event = 0;
+       ssize_t nb_events = 0;
+       struct lttcomm_event_command_header cmd_header = {};
+       const size_t cmd_header_offset = payload->buffer.size;
+
+       ret = lttng_dynamic_buffer_append(
+                       &payload->buffer, &cmd_header, sizeof(cmd_header));
+       if (ret) {
+               ret = LTTNG_ERR_NOMEM;
+               goto error;
+       }
 
        switch (domain) {
        case LTTNG_DOMAIN_KERNEL:
                if (session->kernel_session != NULL) {
-                       nb_event = list_lttng_kernel_events(channel_name,
-                                       session->kernel_session, events,
-                                       total_size);
+                       nb_events = list_lttng_kernel_events(channel_name,
+                                       session->kernel_session, payload);
                }
                break;
        case LTTNG_DOMAIN_UST:
        {
                if (session->ust_session != NULL) {
-                       nb_event = list_lttng_ust_global_events(channel_name,
-                                       &session->ust_session->domain_global, events,
-                                       total_size);
+                       nb_events = list_lttng_ust_global_events(channel_name,
+                                       &session->ust_session->domain_global,
+                                       payload);
                }
                break;
        }
@@ -3762,9 +3662,8 @@ ssize_t cmd_list_events(enum lttng_domain_type domain,
                        cds_lfht_for_each_entry(session->ust_session->agents->ht,
                                        &iter.iter, agt, node.node) {
                                if (agt->domain == domain) {
-                                       nb_event = list_lttng_agent_events(
-                                                       agt, events,
-                                                       total_size);
+                                       nb_events = list_lttng_agent_events(
+                                                       agt, payload);
                                        break;
                                }
                        }
@@ -3776,7 +3675,10 @@ ssize_t cmd_list_events(enum lttng_domain_type domain,
                goto error;
        }
 
-       return nb_event;
+       ((struct lttcomm_event_command_header *) (payload->buffer.data +
+                        cmd_header_offset))->nb_events = (uint32_t) nb_events;
+
+       return nb_events;
 
 error:
        /* Return negative value to differentiate return code */
index 1be746031146962372c0d465de19e4adeb3753f4..76c53ea333da17c0fd09de321f435476183728c4 100644 (file)
@@ -111,7 +111,7 @@ ssize_t cmd_list_domains(struct ltt_session *session,
                struct lttng_domain **domains);
 ssize_t cmd_list_events(enum lttng_domain_type domain,
                struct ltt_session *session, char *channel_name,
-               struct lttng_event **events, size_t *total_size);
+               struct lttng_payload *payload);
 ssize_t cmd_list_channels(enum lttng_domain_type domain,
                struct ltt_session *session, struct lttng_channel **channels);
 ssize_t cmd_list_domains(struct ltt_session *session,
index 044fc98d2510ddd17c1bb36353e99f9780b8d933..dfdc9fd14e96b9b2124034983dc0d1db4525633a 100644 (file)
@@ -391,16 +391,10 @@ enum lttng_error_code trace_kernel_create_event(
 
                        /*
                         * Save a reference to the probe location used during
-                        * the listing of events. Close its FD since it won't
-                        * be needed for listing.
+                        * the listing of events.
                         */
                        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. */
@@ -409,15 +403,10 @@ enum lttng_error_code trace_kernel_create_event(
 
                        /*
                         * Save a reference to the probe location used during the listing of
-                        * events. Close its FD since it won't be needed for listing.
+                        * events.
                         */
                        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");
index 2daa7d3ee5e7221d86a9805a01215ab72bf83a6a..8c99c56efa5d9d122c8fb6571e887cf3c74469cd 100644 (file)
@@ -59,6 +59,16 @@ struct lttng_payload_view lttng_payload_view_from_buffer_view(
        };
 }
 
+LTTNG_HIDDEN
+struct lttng_payload_view lttng_payload_view_init_from_buffer(
+       const char *src, size_t offset, ptrdiff_t len)
+{
+       return (struct lttng_payload_view) {
+               .buffer = lttng_buffer_view_init(
+                       src, offset, len)
+       };
+}
+
 LTTNG_HIDDEN
 int lttng_payload_view_get_fd_count(struct lttng_payload_view *payload_view)
 {
index c7501bcdabaed038bea776b9d780f3a709994631..9e385842b208f1183c9842b1578fe1f3206c6858 100644 (file)
@@ -114,6 +114,21 @@ struct lttng_payload_view lttng_payload_view_from_buffer_view(
                const struct lttng_buffer_view *view, size_t offset,
                ptrdiff_t len);
 
+/**
+ * Return a payload view referencing a subset of the memory referenced by a raw
+ * pointer.
+ *
+ * @src                Source buffer to reference
+ * @offset     Offset to apply to the source memory buffer
+ * @len                Length of the memory contents to reference.
+ *
+ * Note that a payload view never assumes the ownership of the memory it
+ * references.
+ */
+LTTNG_HIDDEN
+struct lttng_payload_view lttng_payload_view_init_from_buffer(
+               const char *src, size_t offset, ptrdiff_t len);
+
 /**
  * Get the number of file descriptors left in a payload view.
  *
index 592964a519b13ce6996e178df222b50e3cd81e5a..635d3e3fbc65bdda94386ec1111ca92e45d01fb5 100644 (file)
@@ -6,6 +6,9 @@
  */
 
 #include "payload.h"
+#include <common/dynamic-array.h>
+#include <common/dynamic-buffer.h>
+#include <common/error.h>
 
 LTTNG_HIDDEN
 void lttng_payload_init(struct lttng_payload *payload)
@@ -15,6 +18,52 @@ void lttng_payload_init(struct lttng_payload *payload)
        lttng_dynamic_array_init(&payload->_fds, sizeof(int), NULL);
 }
 
+LTTNG_HIDDEN
+int lttng_payload_copy(const struct lttng_payload *src_payload,
+                      struct lttng_payload *dst_payload)
+{
+       int ret;
+       size_t i;
+
+       lttng_payload_init(dst_payload);
+       ret = lttng_dynamic_buffer_append_buffer(
+                       &dst_payload->buffer, &src_payload->buffer);
+       if (ret) {
+               goto error;
+       }
+
+       for (i = 0; i < lttng_dynamic_array_get_count(&src_payload->_fds);
+                       i++) {
+               int dst_fd;
+               const int src_fd = *((int *) lttng_dynamic_array_get_element(
+                                            &src_payload->_fds, i));
+
+               dst_fd = dup(src_fd);
+               if (dst_fd < 0) {
+                       PERROR("Failed to duplicate file descriptor while copying a payload");
+                       ret = dst_fd;
+                       goto error;
+               }
+
+               ret = lttng_payload_push_fd(dst_payload, dst_fd);
+               if (ret) {
+                       const int close_ret = close(dst_fd);
+
+                       if (close_ret < 0) {
+                               PERROR("Failed to close duplicated file descriptor while copying a payload");
+                       }
+
+                       goto error;
+               }
+       }
+
+end:
+       return ret;
+error:
+       lttng_payload_reset(dst_payload);
+       goto end;
+}
+
 LTTNG_HIDDEN
 void lttng_payload_reset(struct lttng_payload *payload)
 {
index 7548c16ec4468faa8aec5189159e7ed5c30feef0..465a097cfbcdac0b0530372b63eedc95b329cef6 100644 (file)
@@ -29,6 +29,11 @@ struct lttng_payload {
 LTTNG_HIDDEN
 void lttng_payload_init(struct lttng_payload *payload);
 
+/* Copy a payload. */
+LTTNG_HIDDEN
+int lttng_payload_copy(const struct lttng_payload *src_payload,
+               struct lttng_payload *dst_payload);
+
 /* Release any memory used by the payload. */
 LTTNG_HIDDEN
 void lttng_payload_reset(struct lttng_payload *payload);
index cca48d6abafdb6150fa06048e0f1610e26c904d6..fff9a5aaab7efc6de3016390f31ea24c19db0b06 100644 (file)
@@ -502,6 +502,7 @@ struct lttcomm_lttng_msg {
        uint32_t pid;           /* pid_t */
        uint32_t cmd_header_size;
        uint32_t data_size;
+       uint32_t fd_count;
 } LTTNG_PACKED;
 
 struct lttcomm_lttng_output_id {
index 0409750c3ff7ada10465c1d1ee92d878afb3309a..f50611b5b0eac52ad8ac92502826038eec10afeb 100644 (file)
@@ -771,7 +771,7 @@ end:
  * Returns the size of data sent, or negative error value.
  */
 LTTNG_HIDDEN
-ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len)
+ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len)
 {
        struct msghdr msg;
        struct iovec iov[1];
@@ -787,7 +787,7 @@ ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len)
 
        memset(&msg, 0, sizeof(msg));
 
-       iov[0].iov_base = buf;
+       iov[0].iov_base = (void *) buf;
        iov[0].iov_len = len;
        msg.msg_iov = iov;
        msg.msg_iovlen = 1;
index 0cce81b7fb1536c94ffd7dc95f7c08fcc4702a03..a975543b3cecc4134bff2f6f369aefc496e322e7 100644 (file)
@@ -49,7 +49,7 @@ LTTNG_HIDDEN
 ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len);
 
 LTTNG_HIDDEN
-ssize_t lttcomm_send_creds_unix_sock(int sock, void *buf, size_t len);
+ssize_t lttcomm_send_creds_unix_sock(int sock, const void *buf, size_t len);
 LTTNG_HIDDEN
 ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len,
                lttng_sock_cred *creds);
index e6c987c2326839e4c2577a1509919a3dd369230e..61ba309dfa38e2f863dd277ddb90590057720f2c 100644 (file)
@@ -5,6 +5,7 @@
  *
  */
 
+#include "lttng/lttng-error.h"
 #include <assert.h>
 #include <common/compat/string.h>
 #include <common/error.h>
@@ -931,7 +932,7 @@ lttng_userspace_probe_location_get_lookup_method(
 static
 int lttng_userspace_probe_location_lookup_method_serialize(
                struct lttng_userspace_probe_location_lookup_method *method,
-               struct lttng_dynamic_buffer *buffer)
+               struct lttng_payload *payload)
 {
        int ret;
        struct lttng_userspace_probe_location_lookup_method_comm
@@ -939,8 +940,8 @@ int lttng_userspace_probe_location_lookup_method_serialize(
 
        lookup_method_comm.type = (int8_t) (method ? method->type :
                        LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_DEFAULT);
-       if (buffer) {
-               ret = lttng_dynamic_buffer_append(buffer, &lookup_method_comm,
+       if (payload) {
+               ret = lttng_dynamic_buffer_append(&payload->buffer, &lookup_method_comm,
                                sizeof(lookup_method_comm));
                if (ret) {
                        goto end;
@@ -954,8 +955,7 @@ end:
 static
 int lttng_userspace_probe_location_function_serialize(
                const struct lttng_userspace_probe_location *location,
-               struct lttng_dynamic_buffer *buffer,
-               int *binary_fd)
+               struct lttng_payload *payload)
 {
        int ret;
        size_t function_name_len, binary_path_len;
@@ -974,15 +974,11 @@ int lttng_userspace_probe_location_function_serialize(
                goto end;
        }
 
-       if (binary_fd && location_function->binary_fd < 0) {
+       if (payload && location_function->binary_fd < 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       if (binary_fd) {
-               *binary_fd = location_function->binary_fd;
-       }
-
        function_name_len = strlen(location_function->function_name);
        if (function_name_len == 0) {
                ret = -LTTNG_ERR_INVALID;
@@ -997,28 +993,34 @@ int lttng_userspace_probe_location_function_serialize(
        location_function_comm.function_name_len = function_name_len + 1;
        location_function_comm.binary_path_len = binary_path_len + 1;
 
-       if (buffer) {
-               ret = lttng_dynamic_buffer_append(buffer,
+       if (payload) {
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                &location_function_comm,
                                sizeof(location_function_comm));
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_dynamic_buffer_append(buffer,
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                location_function->function_name,
                                location_function_comm.function_name_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_dynamic_buffer_append(buffer,
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                location_function->binary_path,
                                location_function_comm.binary_path_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
+               ret = lttng_payload_push_fd(
+                               payload, location_function->binary_fd);
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
        }
        ret = sizeof(location_function_comm) +
                        location_function_comm.function_name_len +
@@ -1030,8 +1032,7 @@ end:
 static
 int lttng_userspace_probe_location_tracepoint_serialize(
                const struct lttng_userspace_probe_location *location,
-               struct lttng_dynamic_buffer *buffer,
-               int *binary_fd)
+               struct lttng_payload *payload)
 {
        int ret;
        size_t probe_name_len, provider_name_len, binary_path_len;
@@ -1052,15 +1053,11 @@ int lttng_userspace_probe_location_tracepoint_serialize(
                goto end;
        }
 
-       if (binary_fd && location_tracepoint->binary_fd < 0) {
+       if (payload && location_tracepoint->binary_fd < 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       if (binary_fd) {
-               *binary_fd = location_tracepoint->binary_fd;
-       }
-
        probe_name_len = strlen(location_tracepoint->probe_name);
        if (probe_name_len == 0) {
                ret = -LTTNG_ERR_INVALID;
@@ -1083,36 +1080,43 @@ int lttng_userspace_probe_location_tracepoint_serialize(
        location_tracepoint_comm.provider_name_len = provider_name_len + 1;
        location_tracepoint_comm.binary_path_len = binary_path_len + 1;
 
-       if (buffer) {
-               ret = lttng_dynamic_buffer_append(buffer,
+       if (payload) {
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                &location_tracepoint_comm,
                                sizeof(location_tracepoint_comm));
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_dynamic_buffer_append(buffer,
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                location_tracepoint->probe_name,
                                location_tracepoint_comm.probe_name_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_dynamic_buffer_append(buffer,
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                location_tracepoint->provider_name,
                                location_tracepoint_comm.provider_name_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
-               ret = lttng_dynamic_buffer_append(buffer,
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
                                location_tracepoint->binary_path,
                                location_tracepoint_comm.binary_path_len);
                if (ret) {
                        ret = -LTTNG_ERR_INVALID;
                        goto end;
                }
+               ret = lttng_payload_push_fd(
+                               payload, location_tracepoint->binary_fd);
+               if (ret) {
+                       ret = -LTTNG_ERR_INVALID;
+                       goto end;
+               }
        }
+
        ret = sizeof(location_tracepoint_comm) +
                        location_tracepoint_comm.probe_name_len +
                        location_tracepoint_comm.provider_name_len +
@@ -1124,8 +1128,7 @@ end:
 LTTNG_HIDDEN
 int lttng_userspace_probe_location_serialize(
                const struct lttng_userspace_probe_location *location,
-               struct lttng_dynamic_buffer *buffer,
-               int *binary_fd)
+               struct lttng_payload *payload)
 {
        int ret, buffer_use = 0;
        struct lttng_userspace_probe_location_comm location_generic_comm;
@@ -1139,8 +1142,9 @@ int lttng_userspace_probe_location_serialize(
        memset(&location_generic_comm, 0, sizeof(location_generic_comm));
 
        location_generic_comm.type = (int8_t) location->type;
-       if (buffer) {
-               ret = lttng_dynamic_buffer_append(buffer, &location_generic_comm,
+       if (payload) {
+               ret = lttng_dynamic_buffer_append(&payload->buffer,
+                               &location_generic_comm,
                                sizeof(location_generic_comm));
                if (ret) {
                        goto end;
@@ -1151,11 +1155,11 @@ int lttng_userspace_probe_location_serialize(
        switch (lttng_userspace_probe_location_get_type(location)) {
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
                ret = lttng_userspace_probe_location_function_serialize(
-                               location, buffer, binary_fd);
+                               location, payload);
                break;
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
                ret = lttng_userspace_probe_location_tracepoint_serialize(
-                               location, buffer, binary_fd);
+                               location, payload);
                break;
        default:
                ERR("Unsupported probe location type");
@@ -1168,7 +1172,7 @@ int lttng_userspace_probe_location_serialize(
        buffer_use += ret;
 
        ret = lttng_userspace_probe_location_lookup_method_serialize(
-                       location->lookup_method, buffer);
+                       location->lookup_method, payload);
        if (ret < 0) {
                goto end;
        }
@@ -1178,32 +1182,42 @@ end:
 }
 
 static
-int lttng_userspace_probe_location_function_create_from_buffer(
-               const struct lttng_buffer_view *buffer,
+int lttng_userspace_probe_location_function_create_from_payload(
+               struct lttng_payload_view *view,
                struct lttng_userspace_probe_location **location)
 {
        struct lttng_userspace_probe_location_function_comm *location_function_comm;
        const char *function_name_src, *binary_path_src;
        char *function_name = NULL, *binary_path = NULL;
        int ret = 0;
+       size_t expected_size;
+       const int binary_fd = lttng_payload_view_pop_fd(view);
 
-       assert(buffer);
-       assert(buffer->data);
        assert(location);
 
+       if (binary_fd < 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (view->buffer.size < sizeof(*location_function_comm)) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
        location_function_comm =
-               (struct lttng_userspace_probe_location_function_comm *) buffer->data;
+                       (typeof(location_function_comm)) view->buffer.data;
 
-       const size_t expected_size = sizeof(*location_function_comm) +
+       expected_size = sizeof(*location_function_comm) +
                        location_function_comm->function_name_len +
                        location_function_comm->binary_path_len;
 
-       if (buffer->size < expected_size) {
+       if (view->buffer.size < expected_size) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       function_name_src = buffer->data + sizeof(*location_function_comm);
+       function_name_src = view->buffer.data + sizeof(*location_function_comm);
        binary_path_src = function_name_src +
                        location_function_comm->function_name_len;
 
@@ -1237,6 +1251,18 @@ int lttng_userspace_probe_location_function_create_from_buffer(
                goto end;
        }
 
+       ret = lttng_userspace_probe_location_function_set_binary_fd(
+                       *location, binary_fd);
+       if (ret) {
+               const int close_ret = close(binary_fd);
+
+               if (close_ret) {
+                       PERROR("Failed to close userspace probe function binary fd");
+               }
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
        ret = (int) expected_size;
 end:
        free(function_name);
@@ -1245,33 +1271,43 @@ end:
 }
 
 static
-int lttng_userspace_probe_location_tracepoint_create_from_buffer(
-               const struct lttng_buffer_view *buffer,
+int lttng_userspace_probe_location_tracepoint_create_from_payload(
+               struct lttng_payload_view *view,
                struct lttng_userspace_probe_location **location)
 {
        struct lttng_userspace_probe_location_tracepoint_comm *location_tracepoint_comm;
        const char *probe_name_src, *provider_name_src, *binary_path_src;
        char *probe_name = NULL, *provider_name = NULL, *binary_path = NULL;
        int ret = 0;
+       size_t expected_size;
+       const int binary_fd = lttng_payload_view_pop_fd(view);
 
-       assert(buffer);
-       assert(buffer->data);
        assert(location);
 
+       if (binary_fd < 0) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
+       if (view->buffer.size < sizeof(*location_tracepoint_comm)) {
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
        location_tracepoint_comm =
-               (struct lttng_userspace_probe_location_tracepoint_comm *) buffer->data;
+                       (typeof(location_tracepoint_comm)) view->buffer.data;
 
-       const size_t expected_size = sizeof(*location_tracepoint_comm) +
+       expected_size = sizeof(*location_tracepoint_comm) +
                        location_tracepoint_comm->probe_name_len +
                        location_tracepoint_comm->provider_name_len +
                        location_tracepoint_comm->binary_path_len;
 
-       if (buffer->size < expected_size) {
+       if (view->buffer.size < expected_size) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       probe_name_src = buffer->data + sizeof(*location_tracepoint_comm);
+       probe_name_src = view->buffer.data + sizeof(*location_tracepoint_comm);
        provider_name_src = probe_name_src +
                        location_tracepoint_comm->probe_name_len;
        binary_path_src = provider_name_src +
@@ -1316,6 +1352,18 @@ int lttng_userspace_probe_location_tracepoint_create_from_buffer(
                goto end;
        }
 
+       ret = lttng_userspace_probe_location_tracepoint_set_binary_fd(
+                       *location, binary_fd);
+       if (ret) {
+               const int close_ret = close(binary_fd);
+
+               if (close_ret) {
+                       PERROR("Failed to close userspace probe tracepoint binary fd");
+               }
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
+       }
+
        ret = (int) expected_size;
 end:
        free(probe_name);
@@ -1325,25 +1373,23 @@ end:
 }
 
 static
-int lttng_userspace_probe_location_lookup_method_create_from_buffer(
-               struct lttng_buffer_view *buffer,
+int lttng_userspace_probe_location_lookup_method_create_from_payload(
+               struct lttng_payload_view *view,
                struct lttng_userspace_probe_location_lookup_method **lookup_method)
 {
        int ret;
        struct lttng_userspace_probe_location_lookup_method_comm *lookup_comm;
        enum lttng_userspace_probe_location_lookup_method_type type;
 
-       assert(buffer);
-       assert(buffer->data);
+       assert(view);
        assert(lookup_method);
 
-       if (buffer->size < sizeof(*lookup_comm)) {
+       if (view->buffer.size < sizeof(*lookup_comm)) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       lookup_comm = (struct lttng_userspace_probe_location_lookup_method_comm *)
-                       buffer->data;
+       lookup_comm = (typeof(lookup_comm)) view->buffer.data;
        type = (enum lttng_userspace_probe_location_lookup_method_type)
                        lookup_comm->type;
        switch (type) {
@@ -1377,42 +1423,39 @@ end:
 }
 
 LTTNG_HIDDEN
-int lttng_userspace_probe_location_create_from_buffer(
-               const struct lttng_buffer_view *buffer,
+int lttng_userspace_probe_location_create_from_payload(
+               struct lttng_payload_view *view,
                struct lttng_userspace_probe_location **location)
 {
        struct lttng_userspace_probe_location_lookup_method *lookup_method;
        struct lttng_userspace_probe_location_comm *probe_location_comm;
        enum lttng_userspace_probe_location_type type;
-       struct lttng_buffer_view lookup_method_view;
        int consumed = 0;
        int ret;
 
-
-       assert(buffer);
-       assert(buffer->data);
+       assert(view);
        assert(location);
 
        lookup_method = NULL;
 
-       if (buffer->size <= sizeof(*probe_location_comm)) {
+       if (view->buffer.size <= sizeof(*probe_location_comm)) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       probe_location_comm =
-               (struct lttng_userspace_probe_location_comm *) buffer->data;
+       probe_location_comm = (typeof(probe_location_comm)) view->buffer.data;
        type = (enum lttng_userspace_probe_location_type) probe_location_comm->type;
        consumed += sizeof(*probe_location_comm);
 
        switch (type) {
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
        {
-               struct lttng_buffer_view view = lttng_buffer_view_from_view(
-                       buffer, consumed, buffer->size - consumed);
+               struct lttng_payload_view location_view =
+                               lttng_payload_view_from_view(
+                                               view, consumed, -1);
 
-               ret = lttng_userspace_probe_location_function_create_from_buffer(
-                               &view, location);
+               ret = lttng_userspace_probe_location_function_create_from_payload(
+                               &location_view, location);
                if (ret < 0) {
                        goto end;
                }
@@ -1420,11 +1463,11 @@ int lttng_userspace_probe_location_create_from_buffer(
        }
        case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
        {
-               struct lttng_buffer_view view = lttng_buffer_view_from_view(
-                       buffer, consumed, buffer->size - consumed);
+               struct lttng_payload_view location_view =
+                               lttng_payload_view_from_view(view, consumed, -1);
 
-               ret = lttng_userspace_probe_location_tracepoint_create_from_buffer(
-                               &view, location);
+               ret = lttng_userspace_probe_location_tracepoint_create_from_payload(
+                               &location_view, location);
                if (ret < 0) {
                        goto end;
                }
@@ -1436,15 +1479,19 @@ int lttng_userspace_probe_location_create_from_buffer(
        }
 
        consumed += ret;
-       if (buffer->size <= consumed) {
+       if (view->buffer.size <= consumed) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
        }
 
-       lookup_method_view = lttng_buffer_view_from_view(buffer, consumed,
-                       buffer->size - consumed);
-       ret = lttng_userspace_probe_location_lookup_method_create_from_buffer(
-                       &lookup_method_view, &lookup_method);
+       {
+               struct lttng_payload_view lookup_method_view =
+                               lttng_payload_view_from_view(
+                                               view, consumed, -1);
+
+               ret = lttng_userspace_probe_location_lookup_method_create_from_payload(
+                               &lookup_method_view, &lookup_method);
+       }
        if (ret < 0) {
                ret = -LTTNG_ERR_INVALID;
                goto end;
index f252bbbde3ba089669bc7a43681081cb6d99f608..d1c5aa865174b16b752a0d24ab19dc1323cec699 100644 (file)
@@ -37,6 +37,16 @@ int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
                void **user_payload_buf, void **user_cmd_header_buf,
                size_t *user_cmd_header_len);
 
+/*
+ * Sends the lttcomm message to the session daemon and fills the reply payload.
+ *
+ * Return the size of the received data on success or else a negative lttng
+ * error code.
+ */
+LTTNG_HIDDEN
+int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
+               struct lttng_payload *reply);
+
 /*
  * Calls lttng_ctl_ask_sessiond_fds_varlen() with no expected command header.
  */
index d1b2fdfd9482ed479872965425b629831a60fdef..b2f25ecd06ac58c471f94c4ea34daa2d30383cbb 100644 (file)
@@ -216,7 +216,7 @@ end:
  * Receive data from the sessiond socket.
  *
  * On success, returns the number of bytes received (>=0)
- * On error, returns -1 (recvmsg() error) or -ENOTCONN
+ * On error, returns a negative lttng_error_code.
  */
 static int recv_data_sessiond(void *buf, size_t len)
 {
@@ -236,6 +236,30 @@ end:
        return ret;
 }
 
+/*
+ * Receive a payload from the session daemon by appending to an existing
+ * payload.
+ * On success, returns the number of bytes received (>=0)
+ * On error, returns a negative lttng_error_code.
+ */
+static int recv_payload_sessiond(struct lttng_payload *payload, size_t len)
+{
+       int ret;
+       const size_t original_payload_size = payload->buffer.size;
+
+       ret = lttng_dynamic_buffer_set_size(
+                       &payload->buffer, payload->buffer.size + len);
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
+               goto end;
+       }
+
+       ret = recv_data_sessiond(
+                       payload->buffer.data + original_payload_size, len);
+end:
+       return ret;
+}
+
 /*
  * Check if we are in the specified group.
  *
@@ -544,7 +568,6 @@ int lttng_ctl_ask_sessiond_fds_varlen(struct lttcomm_session_msg *lsm,
                connected = 1;
        }
 
-       /* Send command to session daemon */
        ret = send_session_msg(lsm);
        if (ret < 0) {
                /* Ret value is a valid lttng error code. */
@@ -598,6 +621,104 @@ end:
        return ret;
 }
 
+LTTNG_HIDDEN
+int lttng_ctl_ask_sessiond_payload(struct lttng_payload_view *message,
+       struct lttng_payload *reply)
+{
+       int ret;
+       struct lttcomm_lttng_msg llm;
+
+       assert(reply->buffer.size == 0);
+       assert(reply->_fds.size == 0);
+
+       ret = connect_sessiond();
+       if (ret < 0) {
+               ret = -LTTNG_ERR_NO_SESSIOND;
+               goto end;
+       } else {
+               sessiond_socket = ret;
+               connected = 1;
+       }
+
+       /* Send command to session daemon */
+       ret = lttcomm_send_creds_unix_sock(sessiond_socket, message->buffer.data,
+                       message->buffer.size);
+       if (ret < 0) {
+               ret = -LTTNG_ERR_FATAL;
+               goto end;
+       }
+
+       if (lttng_payload_view_get_fd_count(message) > 0) {
+               ret = lttcomm_send_fds_unix_sock(sessiond_socket,
+                               (const int *) message->_fds.buffer.data,
+                               lttng_dynamic_array_get_count(&message->_fds));
+       }
+
+       /* Get header from data transmission */
+       ret = recv_payload_sessiond(reply, sizeof(llm));
+       if (ret < 0) {
+               /* Ret value is a valid lttng error code. */
+               goto end;
+       }
+
+       llm = *((typeof(llm) *) reply->buffer.data);
+
+       /* Check error code if OK */
+       if (llm.ret_code != LTTNG_OK) {
+               ret = -llm.ret_code;
+               goto end;
+       }
+
+       if (llm.cmd_header_size > 0) {
+               ret = recv_payload_sessiond(reply, llm.cmd_header_size);
+               if (ret < 0) {
+                       goto end;
+               }
+       }
+
+       /* Get command header from data transmission */
+       if (llm.data_size > 0) {
+               ret = recv_payload_sessiond(reply, llm.data_size);
+               if (ret < 0) {
+                       goto end;
+               }
+       }
+
+       if (llm.fd_count > 0) {
+               ret = lttng_dynamic_array_set_count(&reply->_fds, llm.fd_count);
+               if (ret) {
+                       ret = -LTTNG_ERR_NOMEM;
+                       goto end;
+               }
+
+               ret = lttcomm_recv_fds_unix_sock(sessiond_socket,
+                               (int *) reply->_fds.buffer.data, llm.fd_count);
+               if (ret > 0 && ret != llm.fd_count * sizeof(int)) {
+                       ret = -LTTNG_ERR_INVALID_PROTOCOL;
+                       goto end;
+               } else if (ret <= 0) {
+                       ret = -LTTNG_ERR_FATAL;
+                       goto end;
+               }
+       }
+
+       /* Don't return the llm header to the caller. */
+       memmove(reply->buffer.data, reply->buffer.data + sizeof(llm),
+                       reply->buffer.size - sizeof(llm));
+       ret = lttng_dynamic_buffer_set_size(
+                       &reply->buffer, reply->buffer.size - sizeof(llm));
+       if (ret) {
+               /* Can't happen as size is reduced. */
+               abort();
+       }
+
+       ret = reply->buffer.size;
+
+end:
+       disconnect_sessiond();
+       return ret;
+}
+
 /*
  * Create lttng handle and return pointer.
  *
@@ -1073,17 +1194,16 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                int exclusion_count, char **exclusion_list)
 {
        struct lttcomm_session_msg lsm;
-       struct lttng_dynamic_buffer send_buffer;
-       int ret = 0, i, fd_to_send = -1;
-       bool send_fd = false;
+       struct lttng_payload payload;
+       int ret = 0, i;
        unsigned int free_filter_expression = 0;
        struct filter_parser_ctx *ctx = NULL;
 
        /*
         * We have either a filter or some exclusions, so we need to set up
-        * a variable-length memory block from where to send the data.
+        * a variable-length payload from where to send the data.
         */
-       lttng_dynamic_buffer_init(&send_buffer);
+       lttng_payload_init(&payload);
 
        /*
         * Cast as non-const since we may replace the filter expression
@@ -1168,10 +1288,11 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                }
        }
 
-       ret = lttng_dynamic_buffer_set_capacity(&send_buffer,
-                       lsm.u.enable.bytecode_len
-                       + lsm.u.enable.expression_len
-                       + LTTNG_SYMBOL_NAME_LEN * exclusion_count);
+       ret = lttng_dynamic_buffer_set_capacity(&payload.buffer,
+                       lsm.u.enable.bytecode_len +
+                                       lsm.u.enable.expression_len +
+                                       LTTNG_SYMBOL_NAME_LEN *
+                                                       exclusion_count);
        if (ret) {
                ret = -LTTNG_ERR_EXCLUSION_NOMEM;
                goto mem_error;
@@ -1189,9 +1310,8 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                        goto mem_error;
                }
 
-               ret = lttng_dynamic_buffer_append(&send_buffer,
-                               *(exclusion_list + i),
-                               LTTNG_SYMBOL_NAME_LEN);
+               ret = lttng_dynamic_buffer_append(&payload.buffer,
+                               *(exclusion_list + i), LTTNG_SYMBOL_NAME_LEN);
                if (ret) {
                        goto mem_error;
                }
@@ -1199,7 +1319,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
 
        /* Add filter expression next. */
        if (filter_expression) {
-               ret = lttng_dynamic_buffer_append(&send_buffer,
+               ret = lttng_dynamic_buffer_append(&payload.buffer,
                                filter_expression, lsm.u.enable.expression_len);
                if (ret) {
                        goto mem_error;
@@ -1207,7 +1327,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
        }
        /* Add filter bytecode next. */
        if (ctx && lsm.u.enable.bytecode_len != 0) {
-               ret = lttng_dynamic_buffer_append(&send_buffer,
+               ret = lttng_dynamic_buffer_append(&payload.buffer,
                                &ctx->bytecode->b, lsm.u.enable.bytecode_len);
                if (ret) {
                        goto mem_error;
@@ -1223,13 +1343,11 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                         * number of bytes that was appended to the buffer.
                         */
                        ret = lttng_userspace_probe_location_serialize(
-                               ev_ext->probe_location, &send_buffer,
-                               &fd_to_send);
+                                       ev_ext->probe_location, &payload);
                        if (ret < 0) {
                                goto mem_error;
                        }
 
-                       send_fd = fd_to_send >= 0;
                        /*
                         * Set the size of the userspace probe location element
                         * of the buffer so that the receiving side knows where
@@ -1239,11 +1357,31 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle,
                }
        }
 
-       ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
-                       send_fd ? &fd_to_send : NULL,
-                       send_fd ? 1 : 0,
-                       send_buffer.size ? send_buffer.data : NULL,
-                       send_buffer.size, NULL, NULL, 0);
+       {
+               struct lttng_payload_view view = lttng_payload_view_from_payload(
+                       &payload, 0, -1);
+               int fd_count = lttng_payload_view_get_fd_count(&view);
+               int fd_to_send;
+
+               if (fd_count < 0) {
+                       goto mem_error;
+               }
+
+               assert(fd_count == 0 || fd_count == 1);
+               if (fd_count == 1) {
+                       ret = lttng_payload_view_pop_fd(&view);
+                       if (ret < 0) {
+                               goto mem_error;
+                       }
+
+                       fd_to_send = ret;
+               }
+
+               ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm,
+                               fd_count ? &fd_to_send : NULL, fd_count,
+                               view.buffer.size ? view.buffer.data : NULL,
+                               view.buffer.size, NULL, NULL, 0);
+       }
 
 mem_error:
        if (filter_expression && ctx) {
@@ -1265,7 +1403,7 @@ error:
         * Return directly to the caller and don't ask the sessiond since
         * something went wrong in the parsing of data above.
         */
-       lttng_dynamic_buffer_reset(&send_buffer);
+       lttng_payload_reset(&payload);
        return ret;
 
 ask_sessiond:
@@ -2187,21 +2325,31 @@ int lttng_list_events(struct lttng_handle *handle,
                const char *channel_name, struct lttng_event **events)
 {
        int ret;
-       struct lttcomm_session_msg lsm;
-       struct lttcomm_event_command_header *cmd_header = NULL;
-       size_t cmd_header_len;
+       struct lttcomm_session_msg lsm = {};
+       const struct lttcomm_event_command_header *cmd_header = NULL;
        uint32_t nb_events, i;
-       void *comm_ext_at;
-       char *reception_buffer = NULL;
+       const void *comm_ext_at;
        struct lttng_dynamic_buffer listing;
        size_t storage_req;
+       struct lttng_payload payload;
+       struct lttng_payload payload_copy;
+       struct lttng_payload_view lsm_view =
+                       lttng_payload_view_init_from_buffer(
+                               (const char *) &lsm, 0, sizeof(lsm));
+       struct lttng_buffer_view cmd_header_view;
+       struct lttng_buffer_view cmd_payload_view;
+       struct lttng_buffer_view flat_events_view;
+       struct lttng_buffer_view ext_view;
 
        /* Safety check. An handle and channel name are mandatory */
        if (handle == NULL || channel_name == NULL) {
-               return -LTTNG_ERR_INVALID;
+               ret = -LTTNG_ERR_INVALID;
+               goto end;
        }
 
-       memset(&lsm, 0, sizeof(lsm));
+       lttng_payload_init(&payload);
+       lttng_payload_init(&payload_copy);
+
        lsm.cmd_type = LTTNG_LIST_EVENTS;
        lttng_ctl_copy_string(lsm.session.name, handle->session_name,
                        sizeof(lsm.session.name));
@@ -2209,26 +2357,41 @@ int lttng_list_events(struct lttng_handle *handle,
                        sizeof(lsm.u.list.channel_name));
        COPY_DOMAIN_PACKED(lsm.domain, handle->domain);
 
-       ret = lttng_ctl_ask_sessiond_fds_varlen(&lsm, NULL, 0, NULL, 0,
-               (void **) &reception_buffer, (void **) &cmd_header,
-               &cmd_header_len);
+       ret = lttng_ctl_ask_sessiond_payload(&lsm_view, &payload);
        if (ret < 0) {
                goto end;
        }
 
-       if (!cmd_header) {
-               ret = -LTTNG_ERR_UNK;
+       /*
+        * A copy of the payload is performed since it will be
+        * consumed twice. Consuming the same payload twice is invalid since
+        * it will cause any received file descriptor to become "shared"
+        * between different instances of the resulting objects.
+        */
+       ret = lttng_payload_copy(&payload, &payload_copy);
+       if (ret) {
+               ret = -LTTNG_ERR_NOMEM;
                goto end;
        }
 
+       cmd_header_view = lttng_buffer_view_from_dynamic_buffer(
+               &payload.buffer, 0, sizeof(*cmd_header));
+       if (!cmd_header_view.data) {
+               ret = -LTTNG_ERR_INVALID_PROTOCOL;
+               goto end;
+       }
+
+       cmd_header = (typeof(cmd_header)) cmd_header_view.data;
+
        /* Set number of events and free command header */
        nb_events = cmd_header->nb_events;
        if (nb_events > INT_MAX) {
                ret = -LTTNG_ERR_OVERFLOW;
                goto end;
        }
-       free(cmd_header);
-       cmd_header = NULL;
+
+       cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
+                       &payload.buffer, sizeof(*cmd_header), -1);
 
        /*
         * The buffer that is returned must contain a "flat" version of
@@ -2252,58 +2415,68 @@ int lttng_list_events(struct lttng_handle *handle,
         *     - exclusions
         *     - padding to align to 64-bits
         */
-       comm_ext_at = reception_buffer +
-               (nb_events * sizeof(struct lttng_event));
+       ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
+                       nb_events * sizeof(struct lttng_event), -1);
+       comm_ext_at = ext_view.data;
        storage_req = nb_events * sizeof(struct lttng_event);
+       {
+               struct lttng_payload_view payload_view =
+                               lttng_payload_view_from_payload(&payload, 0, -1);
 
-       for (i = 0; i < nb_events; i++) {
-               struct lttcomm_event_extended_header *ext_comm =
-                       (struct lttcomm_event_extended_header *) comm_ext_at;
-               int probe_storage_req = 0;
-
-               comm_ext_at += sizeof(*ext_comm);
-               comm_ext_at += ext_comm->filter_len;
-               comm_ext_at +=
-                       ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
+               for (i = 0; i < nb_events; i++) {
+                       const struct lttcomm_event_extended_header *ext_comm =
+                                       (struct lttcomm_event_extended_header *)
+                                                       comm_ext_at;
+                       int probe_storage_req = 0;
 
-               if (ext_comm->userspace_probe_location_len) {
-                       struct lttng_userspace_probe_location *probe_location = NULL;
-                       struct lttng_buffer_view probe_location_view;
+                       comm_ext_at += sizeof(*ext_comm);
+                       comm_ext_at += ext_comm->filter_len;
+                       comm_ext_at += ext_comm->nb_exclusions *
+                                       LTTNG_SYMBOL_NAME_LEN;
+
+                       if (ext_comm->userspace_probe_location_len) {
+                               struct lttng_userspace_probe_location
+                                               *probe_location = NULL;
+                               struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
+                                               &payload_view,
+                                               (const char *) comm_ext_at -
+                                                               payload_view.buffer.data,
+                                               ext_comm->userspace_probe_location_len);
 
-                       probe_location_view = lttng_buffer_view_init(
-                                       comm_ext_at, 0,
-                                       ext_comm->userspace_probe_location_len);
+                               /*
+                                * Create a temporary userspace probe location
+                                * to determine the size needed by a "flattened"
+                                * version of that same probe location.
+                                */
+                               ret = lttng_userspace_probe_location_create_from_payload(
+                                               &probe_location_view,
+                                               &probe_location);
+                               if (ret < 0) {
+                                       ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                                       goto end;
+                               }
 
-                       /*
-                        * Create a temporary userspace probe location to
-                        * determine the size needed by a "flattened" version
-                        * of that same probe location.
-                        */
-                       ret = lttng_userspace_probe_location_create_from_buffer(
-                                       &probe_location_view, &probe_location);
-                       if (ret < 0) {
-                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
-                               goto end;
-                       }
+                               ret = lttng_userspace_probe_location_flatten(
+                                               probe_location, NULL);
+                               lttng_userspace_probe_location_destroy(
+                                               probe_location);
+                               if (ret < 0) {
+                                       ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                                       goto end;
+                               }
 
-                       ret = lttng_userspace_probe_location_flatten(
-                                       probe_location, NULL);
-                       lttng_userspace_probe_location_destroy(probe_location);
-                       if (ret < 0) {
-                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
-                               goto end;
+                               probe_storage_req = ret;
+                               comm_ext_at += ext_comm->userspace_probe_location_len;
                        }
 
-                       probe_storage_req = ret;
-                       comm_ext_at += ext_comm->userspace_probe_location_len;
+                       storage_req += sizeof(struct lttng_event_extended);
+                       storage_req += ext_comm->filter_len;
+                       storage_req += ext_comm->nb_exclusions *
+                                       LTTNG_SYMBOL_NAME_LEN;
+                       /* Padding to ensure the flat probe is aligned. */
+                       storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
+                       storage_req += probe_storage_req;
                }
-
-               storage_req += sizeof(struct lttng_event_extended);
-               storage_req += ext_comm->filter_len;
-               storage_req += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
-               /* Padding to ensure the flat probe is aligned. */
-               storage_req = ALIGN_TO(storage_req, sizeof(uint64_t));
-               storage_req += probe_storage_req;
        }
 
        lttng_dynamic_buffer_init(&listing);
@@ -2317,100 +2490,120 @@ int lttng_list_events(struct lttng_handle *handle,
                goto end;
        }
 
-       ret = lttng_dynamic_buffer_append(&listing, reception_buffer,
+       cmd_payload_view = lttng_buffer_view_from_dynamic_buffer(
+               &payload_copy.buffer, sizeof(*cmd_header), -1);
+       flat_events_view = lttng_buffer_view_from_view(&cmd_payload_view, 0,
                        nb_events * sizeof(struct lttng_event));
+       ret = lttng_dynamic_buffer_append_view(&listing, &flat_events_view);
        if (ret) {
                ret = -LTTNG_ERR_NOMEM;
                goto free_dynamic_buffer;
        }
 
-       comm_ext_at = reception_buffer +
-                       (nb_events * sizeof(struct lttng_event));
-       for (i = 0; i < nb_events; i++) {
-               struct lttng_event *event = (struct lttng_event *)
-                       (listing.data + (sizeof(struct lttng_event) * i));
-               struct lttcomm_event_extended_header *ext_comm =
-                       (struct lttcomm_event_extended_header *) comm_ext_at;
-               struct lttng_event_extended *event_extended =
-                       (struct lttng_event_extended *)
-                               (listing.data + listing.size);
-
-               /* Insert struct lttng_event_extended. */
-               ret = lttng_dynamic_buffer_set_size(&listing,
-                               listing.size + sizeof(*event_extended));
-               if (ret) {
-                       ret = -LTTNG_ERR_NOMEM;
-                       goto free_dynamic_buffer;
-               }
-               event->extended.ptr = event_extended;
-
-               comm_ext_at += sizeof(*ext_comm);
-
-               /* Insert filter expression. */
-               if (ext_comm->filter_len) {
-                       event_extended->filter_expression = listing.data +
-                                       listing.size;
-                       ret = lttng_dynamic_buffer_append(&listing, comm_ext_at,
-                                       ext_comm->filter_len);
+       ext_view = lttng_buffer_view_from_view(&cmd_payload_view,
+                       nb_events * sizeof(struct lttng_event), -1);
+       comm_ext_at = ext_view.data;
+
+       {
+               struct lttng_payload_view payload_copy_view =
+                               lttng_payload_view_from_payload(
+                                               &payload_copy, 0, -1);
+
+               for (i = 0; i < nb_events; i++) {
+                       struct lttng_event *event = (typeof(event))(
+                                       listing.data +
+                                       (sizeof(struct lttng_event) * i));
+                       const struct lttcomm_event_extended_header *ext_comm =
+                                       (typeof(ext_comm)) comm_ext_at;
+                       struct lttng_event_extended *event_extended =
+                                       (typeof(event_extended))(listing.data +
+                                                       listing.size);
+
+                       /* Insert struct lttng_event_extended. */
+                       ret = lttng_dynamic_buffer_set_size(&listing,
+                                       listing.size + sizeof(*event_extended));
                        if (ret) {
                                ret = -LTTNG_ERR_NOMEM;
                                goto free_dynamic_buffer;
                        }
-                       comm_ext_at += ext_comm->filter_len;
-               }
+                       event->extended.ptr = event_extended;
+
+                       comm_ext_at += sizeof(*ext_comm);
+
+                       /* Insert filter expression. */
+                       if (ext_comm->filter_len) {
+                               event_extended->filter_expression =
+                                               listing.data + listing.size;
+                               ret = lttng_dynamic_buffer_append(&listing,
+                                               comm_ext_at,
+                                               ext_comm->filter_len);
+                               if (ret) {
+                                       ret = -LTTNG_ERR_NOMEM;
+                                       goto free_dynamic_buffer;
+                               }
+                               comm_ext_at += ext_comm->filter_len;
+                       }
 
-               /* Insert exclusions. */
-               if (ext_comm->nb_exclusions) {
-                       event_extended->exclusions.count =
-                                       ext_comm->nb_exclusions;
-                       event_extended->exclusions.strings =
-                                       listing.data + listing.size;
+                       /* Insert exclusions. */
+                       if (ext_comm->nb_exclusions) {
+                               event_extended->exclusions.count =
+                                               ext_comm->nb_exclusions;
+                               event_extended->exclusions.strings =
+                                               listing.data + listing.size;
+
+                               ret = lttng_dynamic_buffer_append(&listing,
+                                               comm_ext_at,
+                                               ext_comm->nb_exclusions *
+                                                               LTTNG_SYMBOL_NAME_LEN);
+                               if (ret) {
+                                       ret = -LTTNG_ERR_NOMEM;
+                                       goto free_dynamic_buffer;
+                               }
+                               comm_ext_at += ext_comm->nb_exclusions *
+                                               LTTNG_SYMBOL_NAME_LEN;
+                       }
 
-                       ret = lttng_dynamic_buffer_append(&listing,
-                                       comm_ext_at,
-                                       ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN);
+                       /* Insert padding to align to 64-bits. */
+                       ret = lttng_dynamic_buffer_set_size(&listing,
+                                       ALIGN_TO(listing.size,
+                                                       sizeof(uint64_t)));
                        if (ret) {
                                ret = -LTTNG_ERR_NOMEM;
                                goto free_dynamic_buffer;
                        }
-                       comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN;
-               }
-
-               /* Insert padding to align to 64-bits. */
-               ret = lttng_dynamic_buffer_set_size(&listing,
-                               ALIGN_TO(listing.size, sizeof(uint64_t)));
-               if (ret) {
-                       ret = -LTTNG_ERR_NOMEM;
-                       goto free_dynamic_buffer;
-               }
-
-               /* Insert flattened userspace probe location. */
-               if (ext_comm->userspace_probe_location_len) {
-                       struct lttng_userspace_probe_location *probe_location = NULL;
-                       struct lttng_buffer_view probe_location_view;
 
-                       probe_location_view = lttng_buffer_view_init(
-                                       comm_ext_at, 0,
-                                       ext_comm->userspace_probe_location_len);
+                       /* Insert flattened userspace probe location. */
+                       if (ext_comm->userspace_probe_location_len) {
+                               struct lttng_userspace_probe_location
+                                               *probe_location = NULL;
+                               struct lttng_payload_view probe_location_view = lttng_payload_view_from_view(
+                                               &payload_copy_view,
+                                               (const char *) comm_ext_at -
+                                                               payload_copy_view.buffer.data,
+                                               ext_comm->userspace_probe_location_len);
+
+                               ret = lttng_userspace_probe_location_create_from_payload(
+                                               &probe_location_view,
+                                               &probe_location);
+                               if (ret < 0) {
+                                       ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                                       goto free_dynamic_buffer;
+                               }
 
-                       ret = lttng_userspace_probe_location_create_from_buffer(
-                                       &probe_location_view, &probe_location);
-                       if (ret < 0) {
-                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
-                               goto free_dynamic_buffer;
-                       }
+                               event_extended->probe_location = (struct lttng_userspace_probe_location
+                                                               *) (listing.data +
+                                               listing.size);
+                               ret = lttng_userspace_probe_location_flatten(
+                                               probe_location, &listing);
+                               lttng_userspace_probe_location_destroy(
+                                               probe_location);
+                               if (ret < 0) {
+                                       ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
+                                       goto free_dynamic_buffer;
+                               }
 
-                       event_extended->probe_location = (struct lttng_userspace_probe_location *)
-                                       (listing.data + listing.size);
-                       ret = lttng_userspace_probe_location_flatten(
-                                       probe_location, &listing);
-                       lttng_userspace_probe_location_destroy(probe_location);
-                       if (ret < 0) {
-                               ret = -LTTNG_ERR_PROBE_LOCATION_INVAL;
-                               goto free_dynamic_buffer;
+                               comm_ext_at += ext_comm->userspace_probe_location_len;
                        }
-
-                       comm_ext_at += ext_comm->userspace_probe_location_len;
                }
        }
 
@@ -2421,8 +2614,8 @@ int lttng_list_events(struct lttng_handle *handle,
 free_dynamic_buffer:
        lttng_dynamic_buffer_reset(&listing);
 end:
-       free(cmd_header);
-       free(reception_buffer);
+       lttng_payload_reset(&payload);
+       lttng_payload_reset(&payload_copy);
        return ret;
 }
 
This page took 0.065401 seconds and 5 git commands to generate.