/* * 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_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; }