Esempio n. 1
0
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;
}
Esempio n. 2
0
/*
 * 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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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));
}