From 56f0bc67599b5438a4b68bdbec596aaaa39b2e7e Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Tue, 17 Oct 2017 17:22:43 -0400 Subject: [PATCH] lttng-ctl: implement listing of userspace probe locations MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérémie Galarneau --- src/common/sessiond-comm/sessiond-comm.h | 5 + src/common/userspace-probe.c | 2 + src/lib/lttng-ctl/lttng-ctl.c | 173 ++++++++++++++++++----- 3 files changed, 145 insertions(+), 35 deletions(-) diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index 62224bd75..56c925973 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -410,6 +410,11 @@ struct lttcomm_event_extended_header { * character. */ uint32_t nb_exclusions; + + /* + * Size of the event's userspace probe location (if applicable). + */ + uint32_t userspace_probe_location_len; } LTTNG_PACKED; /* diff --git a/src/common/userspace-probe.c b/src/common/userspace-probe.c index 6776d4b78..106fdadf6 100644 --- a/src/common/userspace-probe.c +++ b/src/common/userspace-probe.c @@ -415,6 +415,8 @@ int lttng_userspace_probe_location_serialize( goto end; } + 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, diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 7df8d6de7..c79cc6dd5 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -1180,7 +1180,7 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, ret = lttng_userspace_probe_location_serialize( ev_ext->probe_location, &send_buffer, &fd_to_send); - if (ret) { + if (ret < 0) { goto mem_error; } @@ -1932,9 +1932,8 @@ int lttng_list_events(struct lttng_handle *handle, size_t cmd_header_len; uint32_t nb_events, i; void *comm_ext_at; - void *listing_at; char *reception_buffer = NULL; - char *listing = NULL; + struct lttng_dynamic_buffer listing; size_t storage_req; /* Safety check. An handle and channel name are mandatory */ @@ -1970,12 +1969,12 @@ int lttng_list_events(struct lttng_handle *handle, * The buffer that is returned must contain a "flat" version of * the events that are returned. In other words, all pointers * within an lttng_event must point to a location within the returned - * buffer so that the user may free by simply calling free() on the - * returned buffer. This is needed in order to maintain API + * buffer so that the user may free everything by simply calling free() + * on the returned buffer. This is needed in order to maintain API * compatibility. * - * A first pass is performed to figure the size of the buffer that - * must be returned. A second pass is then performed to setup + * A first pass is performed to compute the size of the buffer that + * must be allocated. A second pass is then performed to setup * the returned events so that their members always point within the * buffer. * @@ -1995,66 +1994,170 @@ int lttng_list_events(struct lttng_handle *handle, 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; + 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); + + /* + * 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; + } + + probe_storage_req = ret; + comm_ext_at += ext_comm->userspace_probe_location_len; + ret = 0; + } + storage_req += sizeof(struct lttng_event_extended); - /* TODO: missing size of flat userspace probe. */ storage_req += ext_comm->filter_len; storage_req += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; - storage_req += storage_req % 8; + /* Padding to ensure the flat probe is aligned. */ + storage_req = ALIGN_TO(storage_req, sizeof(uint64_t)); + storage_req += probe_storage_req; } - listing = zmalloc(storage_req); - if (!listing) { + lttng_dynamic_buffer_init(&listing); + /* + * We must ensure that "listing" is never resized so as to preserve + * the validity of the flattened objects. + */ + ret = lttng_dynamic_buffer_set_capacity(&listing, storage_req); + if (ret) { + ret = -LTTNG_ERR_NOMEM; goto end; } - memcpy(listing, reception_buffer, - nb_events * sizeof(struct lttng_event)); + + ret = lttng_dynamic_buffer_append(&listing, reception_buffer, + nb_events * sizeof(struct lttng_event)); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + goto free_dynamic_buffer; + } comm_ext_at = reception_buffer + - (nb_events * sizeof(struct lttng_event)); - listing_at = listing + - (nb_events * sizeof(struct lttng_event)); + (nb_events * sizeof(struct lttng_event)); for (i = 0; i < nb_events; i++) { struct lttng_event *event = (struct lttng_event *) - (listing + (sizeof(struct lttng_event) * i)); + (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_at; + (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; - listing_at += sizeof(*event_extended); + comm_ext_at += sizeof(*ext_comm); - /* Copy filter expression. */ - memcpy(listing_at, comm_ext_at, ext_comm->filter_len); - event_extended->filter_expression = listing_at; - comm_ext_at += ext_comm->filter_len; - listing_at += ext_comm->filter_len; + /* 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; + + ret = lttng_dynamic_buffer_append(&listing, + comm_ext_at, + ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN); + if (ret) { + ret = -LTTNG_ERR_NOMEM; + } + 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; - /* Copy exclusions. */ - event_extended->exclusions.count = ext_comm->nb_exclusions; - event_extended->exclusions.strings = listing_at; - memcpy(listing_at, comm_ext_at, - ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN); - listing_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; - comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + probe_location_view = lttng_buffer_view_init( + comm_ext_at, 0, + ext_comm->userspace_probe_location_len); - listing_at += ((uintptr_t) listing_at) % 8; + 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; + } + + comm_ext_at += ext_comm->userspace_probe_location_len; + } } - *events = (struct lttng_event *) listing; - listing = NULL; + /* Don't reset listing buffer as we return its content. */ + *events = (struct lttng_event *) listing.data; + lttng_dynamic_buffer_init(&listing); ret = (int) nb_events; +free_dynamic_buffer: + lttng_dynamic_buffer_reset(&listing); end: free(cmd_header); free(reception_buffer); - free(listing); return ret; } -- 2.34.1