LTTNG_HIDDEN int lttng_userspace_probe_location_serialize( const struct lttng_userspace_probe_location *location, struct lttng_dynamic_buffer *buffer, int *binary_fd) { int ret, buffer_use = 0; struct lttng_userspace_probe_location_comm location_generic_comm; if (!location) { ERR("Invalid argument(s)"); ret = -LTTNG_ERR_INVALID; 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, sizeof(location_generic_comm)); if (ret) { goto end; } } buffer_use += sizeof(location_generic_comm); 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); break; case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT: ret = lttng_userspace_probe_location_tracepoint_serialize( location, buffer, binary_fd); break; default: ERR("Unsupported probe location type"); ret = -LTTNG_ERR_INVALID; goto end; } if (ret < 0) { goto end; } buffer_use += ret; ret = lttng_userspace_probe_location_lookup_method_serialize( location->lookup_method, buffer); if (ret < 0) { goto end; } ret += buffer_use; end: return ret; }
/* * Populates the reception buffer with the next complete message. * The caller must acquire the client's lock. */ static int receive_message(struct lttng_notification_channel *channel) { ssize_t ret; struct lttng_notification_channel_message msg; ret = lttng_dynamic_buffer_set_size(&channel->reception_buffer, 0); if (ret) { goto error; } ret = lttcomm_recv_unix_sock(channel->socket, &msg, sizeof(msg)); if (ret <= 0) { ret = -1; goto error; } if (msg.size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) { ret = -1; goto error; } /* Add message header at buffer's start. */ ret = lttng_dynamic_buffer_append(&channel->reception_buffer, &msg, sizeof(msg)); if (ret) { goto error; } /* Reserve space for the payload. */ ret = lttng_dynamic_buffer_set_size(&channel->reception_buffer, channel->reception_buffer.size + msg.size); if (ret) { goto error; } /* Receive message payload. */ ret = lttcomm_recv_unix_sock(channel->socket, channel->reception_buffer.data + sizeof(msg), msg.size); if (ret < (ssize_t) msg.size) { ret = -1; goto error; } ret = 0; end: return ret; error: if (lttng_dynamic_buffer_set_size(&channel->reception_buffer, 0)) { ret = -1; } goto end; }
static int lttng_userspace_probe_location_lookup_method_serialize( struct lttng_userspace_probe_location_lookup_method *method, struct lttng_dynamic_buffer *buffer) { int ret; struct lttng_userspace_probe_location_lookup_method_comm lookup_method_comm; 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, sizeof(lookup_method_comm)); if (ret) { goto end; } } ret = sizeof(lookup_method_comm); end: return ret; }
static int lttng_userspace_probe_location_tracepoint_serialize( const struct lttng_userspace_probe_location *location, struct lttng_dynamic_buffer *buffer, int *binary_fd) { int ret; size_t probe_name_len, provider_name_len, binary_path_len; struct lttng_userspace_probe_location_tracepoint *location_tracepoint; struct lttng_userspace_probe_location_tracepoint_comm location_tracepoint_comm; assert(location); assert(lttng_userspace_probe_location_get_type(location) == LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT); location_tracepoint = container_of(location, struct lttng_userspace_probe_location_tracepoint, parent); if (!location_tracepoint->probe_name || !location_tracepoint->provider_name || !location_tracepoint->binary_path) { ret = -LTTNG_ERR_INVALID; goto end; } if (binary_fd && 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; goto end; } provider_name_len = strlen(location_tracepoint->provider_name); if (provider_name_len == 0) { ret = -LTTNG_ERR_INVALID; goto end; } binary_path_len = strlen(location_tracepoint->binary_path); if (binary_path_len == 0) { ret = -LTTNG_ERR_INVALID; goto end; } location_tracepoint_comm.probe_name_len = probe_name_len + 1; 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, &location_tracepoint_comm, sizeof(location_tracepoint_comm)); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } ret = lttng_dynamic_buffer_append(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, location_tracepoint->provider_name, location_tracepoint_comm.provider_name_len); if (ret) { ret = -LTTNG_ERR_INVALID; goto end; } ret = lttng_dynamic_buffer_append(buffer, location_tracepoint->binary_path, location_tracepoint_comm.binary_path_len); 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 + location_tracepoint_comm.binary_path_len; end: return ret; }
static int lttng_userspace_probe_location_tracepoint_flatten( const struct lttng_userspace_probe_location *location, struct lttng_dynamic_buffer *buffer) { struct lttng_userspace_probe_location_lookup_method_sdt flat_lookup_method; struct lttng_userspace_probe_location_tracepoint *probe_tracepoint; struct lttng_userspace_probe_location_tracepoint flat_probe; size_t probe_name_len, provider_name_len, binary_path_len; size_t padding_needed = 0; int storage_needed = 0; char *flat_probe_start; int ret = 0; assert(location); /* Only SDT tracepoints are supported at the moment */ if (location->lookup_method && location->lookup_method->type != LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT) { ret = -LTTNG_ERR_INVALID; goto end; } probe_tracepoint = container_of(location, struct lttng_userspace_probe_location_tracepoint, parent); assert(probe_tracepoint->probe_name); assert(probe_tracepoint->provider_name); assert(probe_tracepoint->binary_path); /* Compute the storage space needed to flatten the probe location */ storage_needed += sizeof(struct lttng_userspace_probe_location_tracepoint); probe_name_len = strlen(probe_tracepoint->probe_name) + 1; provider_name_len = strlen(probe_tracepoint->provider_name) + 1; binary_path_len = strlen(probe_tracepoint->binary_path) + 1; storage_needed += probe_name_len + provider_name_len + binary_path_len; /* * The lookup method is aligned to 64-bit within the buffer. * This is needed even if there is no lookup method since * the next structure in the buffer probably needs to be * aligned too (depending on the arch). */ padding_needed = ALIGN_TO(storage_needed, sizeof(uint64_t)) - storage_needed; storage_needed += padding_needed; if (location->lookup_method) { /* NOTE: elf look-up method is assumed here. */ storage_needed += sizeof(struct lttng_userspace_probe_location_lookup_method_elf); } /* * If the caller set buffer to NULL, return the size of the needed buffer. */ if (!buffer) { ret = storage_needed; goto end; } if (lttng_dynamic_buffer_get_capacity_left(buffer) < storage_needed) { ret = lttng_dynamic_buffer_set_capacity(buffer, buffer->size + storage_needed); if (ret) { goto end; } } memset(&flat_probe, 0, sizeof(flat_probe)); flat_probe_start = buffer->data + buffer->size; flat_probe.parent.type = location->type; /* * The lookup method, if present, is the last element in the flat * representation of the probe. */ if (location->lookup_method) { flat_probe.parent.lookup_method = (struct lttng_userspace_probe_location_lookup_method *) (flat_probe_start + sizeof(flat_probe) + probe_name_len + provider_name_len + binary_path_len + padding_needed); } else { flat_probe.parent.lookup_method = NULL; } flat_probe.probe_name = flat_probe_start + sizeof(flat_probe); flat_probe.provider_name = flat_probe.probe_name + probe_name_len; flat_probe.binary_path = flat_probe.provider_name + provider_name_len; flat_probe.binary_fd = -1; ret = lttng_dynamic_buffer_append(buffer, &flat_probe, sizeof(flat_probe)); if (ret) { goto end; } /* Append all the fields to the buffer */ ret = lttng_dynamic_buffer_append(buffer, probe_tracepoint->probe_name, probe_name_len); if (ret) { goto end; } ret = lttng_dynamic_buffer_append(buffer, probe_tracepoint->provider_name, provider_name_len); if (ret) { goto end; } ret = lttng_dynamic_buffer_append(buffer, probe_tracepoint->binary_path, binary_path_len); if (ret) { goto end; } /* Insert padding before the lookup method. */ ret = lttng_dynamic_buffer_set_size(buffer, buffer->size + padding_needed); if (ret) { goto end; } if (!location->lookup_method) { /* Not an error, the default method is used. */ ret = storage_needed; goto end; } memset(&flat_lookup_method, 0, sizeof(flat_lookup_method)); flat_lookup_method.parent.type = LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT; ret = lttng_dynamic_buffer_append(buffer, &flat_lookup_method, sizeof(flat_lookup_method)); if (ret) { goto end; } ret = storage_needed; end: return ret; }
LTTNG_HIDDEN int lttng_session_descriptor_serialize( const struct lttng_session_descriptor *descriptor, struct lttng_dynamic_buffer *buffer) { int ret, i; /* There are, at most, two URIs to serialize. */ struct lttng_uri *uris[2] = {}; size_t uri_count = 0; /* The live header is a superset of all headers. */ struct lttng_session_descriptor_live_comm header = { .base.type = (uint8_t) descriptor->type, .base.output_type = (uint8_t) descriptor->output_type, .base.name_len = descriptor->name ? strlen(descriptor->name) + 1 : 0, }; const void *header_ptr = NULL; size_t header_size; switch (descriptor->output_type) { case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NONE: break; case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_LOCAL: uris[0] = descriptor->output.local; break; case LTTNG_SESSION_DESCRIPTOR_OUTPUT_TYPE_NETWORK: uris[0] = descriptor->output.network.control; uris[1] = descriptor->output.network.data; break; default: ret = -1; goto end; } uri_count += !!uris[0]; uri_count += !!uris[1]; header.base.uri_count = uri_count; if (descriptor->type == LTTNG_SESSION_DESCRIPTOR_TYPE_LIVE) { const struct lttng_session_descriptor_live *live = container_of(descriptor, typeof(*live), base); header.live_timer_us = live->live_timer_us; header_ptr = &header; header_size = sizeof(header); } else { header_ptr = &header.base; header_size = sizeof(header.base); } ret = lttng_dynamic_buffer_append(buffer, header_ptr, header_size); if (ret) { goto end; } if (header.base.name_len) { ret = lttng_dynamic_buffer_append(buffer, descriptor->name, header.base.name_len); if (ret) { goto end; } } for (i = 0; i < uri_count; i++) { ret = lttng_dynamic_buffer_append(buffer, uris[i], sizeof(struct lttng_uri)); if (ret) { goto end; } } end: return ret; } LTTNG_HIDDEN enum lttng_session_descriptor_type lttng_session_descriptor_get_type( const struct lttng_session_descriptor *descriptor) { return descriptor->type; } LTTNG_HIDDEN enum lttng_session_descriptor_output_type lttng_session_descriptor_get_output_type( const struct lttng_session_descriptor *descriptor) { return descriptor->output_type; } LTTNG_HIDDEN void lttng_session_descriptor_get_local_output_uri( const struct lttng_session_descriptor *descriptor, struct lttng_uri *local_uri) { memcpy(local_uri, descriptor->output.local, sizeof(*local_uri)); }