X-Git-Url: http://git.efficios.com/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Flib%2Flttng-ctl%2Flttng-ctl.c;h=b57be223a73afce55723c858c66a5aedfa245b24;hp=197e52e8f7a1d6befe81a03ed07541a69c4dc631;hb=2c2de71ef6dae09fa1a61f02051b68f60b0a1750;hpb=de453daa7054455a39fac38fb74306fc12349f54 diff --git a/src/lib/lttng-ctl/lttng-ctl.c b/src/lib/lttng-ctl/lttng-ctl.c index 197e52e8f..b57be223a 100644 --- a/src/lib/lttng-ctl/lttng-ctl.c +++ b/src/lib/lttng-ctl/lttng-ctl.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include "filter/filter-ast.h" #include "filter/filter-parser.h" @@ -1026,10 +1028,14 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, int exclusion_count, char **exclusion_list) { struct lttcomm_session_msg lsm; - char *varlen_data; - int ret = 0; + struct lttng_dynamic_buffer send_buffer; + int ret = 0, i, fd_to_send = -1; + bool send_fd = false; unsigned int free_filter_expression = 0; struct filter_parser_ctx *ctx = NULL; + + memset(&send_buffer, 0, sizeof(send_buffer)); + /* * Cast as non-const since we may replace the filter expression * by a dynamically allocated string. Otherwise, the original @@ -1078,22 +1084,11 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, lsm.u.enable.exclusion_count = exclusion_count; lsm.u.enable.bytecode_len = 0; - /* - * For the JUL domain, a filter is enforced except for the enable all - * event. This is done to avoid having the event in all sessions thus - * filtering by logger name. - */ - if (exclusion_count == 0 && filter_expression == NULL && - (handle->domain.type != LTTNG_DOMAIN_JUL && - handle->domain.type != LTTNG_DOMAIN_LOG4J && - handle->domain.type != LTTNG_DOMAIN_PYTHON)) { - goto ask_sessiond; - } - /* * 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. */ + lttng_dynamic_buffer_init(&send_buffer); /* Parse filter expression. */ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL @@ -1131,41 +1126,82 @@ int lttng_enable_event_with_exclusions(struct lttng_handle *handle, } } - varlen_data = zmalloc(lsm.u.enable.bytecode_len + ret = lttng_dynamic_buffer_set_capacity(&send_buffer, + lsm.u.enable.bytecode_len + lsm.u.enable.expression_len + LTTNG_SYMBOL_NAME_LEN * exclusion_count); - if (!varlen_data) { + if (ret) { ret = -LTTNG_ERR_EXCLUSION_NOMEM; goto mem_error; } /* Put exclusion names first in the data. */ - while (exclusion_count--) { - strncpy(varlen_data + LTTNG_SYMBOL_NAME_LEN * exclusion_count, - *(exclusion_list + exclusion_count), - LTTNG_SYMBOL_NAME_LEN - 1); + for (i = 0; i < exclusion_count; i++) { + size_t exclusion_len; + + exclusion_len = lttng_strnlen(*(exclusion_list + i), + LTTNG_SYMBOL_NAME_LEN); + if (exclusion_len == LTTNG_SYMBOL_NAME_LEN) { + /* Exclusion is not NULL-terminated. */ + ret = -LTTNG_ERR_INVALID; + goto mem_error; + } + + ret = lttng_dynamic_buffer_append(&send_buffer, + *(exclusion_list + i), + LTTNG_SYMBOL_NAME_LEN); + if (ret) { + goto mem_error; + } } + /* Add filter expression next. */ - if (lsm.u.enable.expression_len != 0) { - memcpy(varlen_data - + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count, - filter_expression, - lsm.u.enable.expression_len); + if (filter_expression) { + ret = lttng_dynamic_buffer_append(&send_buffer, + filter_expression, lsm.u.enable.expression_len); + if (ret) { + goto mem_error; + } } /* Add filter bytecode next. */ if (ctx && lsm.u.enable.bytecode_len != 0) { - memcpy(varlen_data - + LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count - + lsm.u.enable.expression_len, - &ctx->bytecode->b, - lsm.u.enable.bytecode_len); + ret = lttng_dynamic_buffer_append(&send_buffer, + &ctx->bytecode->b, lsm.u.enable.bytecode_len); + if (ret) { + goto mem_error; + } } + if (ev->extended.ptr) { + struct lttng_event_extended *ev_ext = + (struct lttng_event_extended *) ev->extended.ptr; + + if (ev_ext->probe_location) { + /* + * lttng_userspace_probe_location_serialize returns the + * number of bytes that was appended to the buffer. + */ + ret = lttng_userspace_probe_location_serialize( + ev_ext->probe_location, &send_buffer, + &fd_to_send); + if (ret < 0) { + goto mem_error; + } - ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(&lsm, varlen_data, - (LTTNG_SYMBOL_NAME_LEN * lsm.u.enable.exclusion_count) + - lsm.u.enable.bytecode_len + lsm.u.enable.expression_len, - NULL); - free(varlen_data); + 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 + * to split it. + */ + lsm.u.enable.userspace_probe_location_len = ret; + } + } + + 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); mem_error: if (filter_expression && ctx) { @@ -1187,6 +1223,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); return ret; ask_sessiond: @@ -1898,9 +1935,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 */ @@ -1923,6 +1959,11 @@ int lttng_list_events(struct lttng_handle *handle, goto end; } + if (!cmd_header) { + ret = -LTTNG_ERR_UNK; + goto end; + } + /* Set number of events and free command header */ nb_events = cmd_header->nb_events; if (nb_events > INT_MAX) { @@ -1936,12 +1977,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. * @@ -1961,66 +2002,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; + } + 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; + goto free_dynamic_buffer; + } + comm_ext_at += ext_comm->nb_exclusions * LTTNG_SYMBOL_NAME_LEN; + } - /* 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; + /* 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); + + 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; + } - listing_at += ((uintptr_t) listing_at) % 8; + 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; } @@ -2582,7 +2727,7 @@ int lttng_list_tracker_pids(struct lttng_handle *handle, int enabled = 1; struct lttcomm_session_msg lsm; size_t nr_pids; - int32_t *pids; + int32_t *pids = NULL; if (handle == NULL) { return -LTTNG_ERR_INVALID; @@ -2599,6 +2744,9 @@ int lttng_list_tracker_pids(struct lttng_handle *handle, return ret; } nr_pids = ret / sizeof(int32_t); + if (nr_pids > 0 && !pids) { + return -LTTNG_ERR_UNK; + } if (nr_pids == 1 && pids[0] == -1) { free(pids); pids = NULL; @@ -2745,50 +2893,6 @@ end: return ret; } -int lttng_session_get_current_archive_location(const char *session_name, - char **chunk_path) -{ - struct lttcomm_session_msg lsm; - struct lttng_session_get_current_output_return *output_return = NULL; - int ret; - size_t path_len; - - memset(&lsm, 0, sizeof(lsm)); - lsm.cmd_type = LTTNG_SESSION_GET_CURRENT_OUTPUT; - ret = lttng_strncpy(lsm.session.name, session_name, - sizeof(lsm.session.name)); - if (ret) { - ret = -LTTNG_ERR_INVALID; - goto end; - } - - ret = lttng_ctl_ask_sessiond(&lsm, (void **) &output_return); - if (ret < 0) { - ret = -1; - goto end; - } - - path_len = lttng_strnlen(output_return->path, - sizeof(output_return->path)); - if (path_len == 0 || path_len == sizeof(output_return->path)) { - ret = -LTTNG_ERR_NO_SESSION_OUTPUT; - goto end; - } - - *chunk_path = zmalloc(path_len + 1); - if (!*chunk_path) { - ret = -1; - goto end; - } - memcpy(*chunk_path, output_return->path, path_len); - - ret = 0; - -end: - free(output_return); - return ret; -} - /* * lib constructor. */