Example #1
0
struct bt_btr *bt_btr_create(struct bt_btr_cbs cbs, void *data)
{
	struct bt_btr *btr;

	BT_LOGD_STR("Creating binary type reader (BTR).");
	btr = g_new0(struct bt_btr, 1);
	if (!btr) {
		BT_LOGE_STR("Failed to allocate one binary type reader.");
		goto end;
	}

	btr->stack = stack_new();
	if (!btr->stack) {
		BT_LOGE_STR("Cannot create BTR's stack.");
		bt_btr_destroy(btr);
		btr = NULL;
		goto end;
	}

	btr->state = BTR_STATE_NEXT_FIELD;
	btr->user.cbs = cbs;
	btr->user.data = data;
	BT_LOGD("Created BTR: addr=%p", btr);

end:
	return btr;
}
Example #2
0
static
struct stack *stack_new(void)
{
	struct stack *stack = NULL;

	stack = g_new0(struct stack, 1);
	if (!stack) {
		BT_LOGE_STR("Failed to allocate one stack.");
		goto error;
	}

	stack->entries = g_ptr_array_new_with_free_func(stack_entry_free_func);
	if (!stack->entries) {
		BT_LOGE_STR("Failed to allocate a GPtrArray.");
		goto error;
	}

	BT_LOGD("Created stack: addr=%p", stack);
	return stack;

error:
	g_free(stack);

	return NULL;
}
Example #3
0
struct bt_value *bt_value_map_create(void)
{
	struct bt_value_map *map_obj;

	BT_LOGD_STR("Creating empty map value object.");
	map_obj = g_new0(struct bt_value_map, 1);
	if (!map_obj) {
		BT_LOGE_STR("Failed to allocate one map object.");
		goto end;
	}

	map_obj->base = bt_value_create_base(BT_VALUE_TYPE_MAP);
	map_obj->ght = g_hash_table_new_full(g_direct_hash, g_direct_equal,
		NULL, (GDestroyNotify) bt_object_put_ref);
	if (!map_obj->ght) {
		BT_LOGE_STR("Failed to allocate a GHashTable.");
		g_free(map_obj);
		map_obj = NULL;
		goto end;
	}

	BT_LOGD("Created map value object: addr=%p",
		map_obj);

end:
	return (void *) map_obj;
}
Example #4
0
struct bt_value *bt_value_string_create_init(const char *val)
{
	struct bt_value_string *string_obj = NULL;

	if (!val) {
		BT_LOGW_STR("Invalid parameter: value is NULL.");
		goto end;
	}

	BT_LOGD("Creating string value object: val-len=%zu", strlen(val));
	string_obj = g_new0(struct bt_value_string, 1);
	if (!string_obj) {
		BT_LOGE_STR("Failed to allocate one string object.");
		goto end;
	}

	string_obj->base = bt_value_create_base(BT_VALUE_TYPE_STRING);
	string_obj->gstr = g_string_new(val);
	if (!string_obj->gstr) {
		BT_LOGE_STR("Failed to allocate a GString.");
		g_free(string_obj);
		string_obj = NULL;
		goto end;
	}

	BT_LOGD("Created string value object: addr=%p",
		string_obj);

end:
	return (void *) string_obj;
}
Example #5
0
struct bt_value *bt_value_array_create(void)
{
	struct bt_value_array *array_obj;

	BT_LOGD_STR("Creating empty array value object.");
	array_obj = g_new0(struct bt_value_array, 1);
	if (!array_obj) {
		BT_LOGE_STR("Failed to allocate one array object.");
		goto end;
	}

	array_obj->base = bt_value_create_base(BT_VALUE_TYPE_ARRAY);
	array_obj->garray = bt_g_ptr_array_new_full(0,
		(GDestroyNotify) bt_object_put_ref);
	if (!array_obj->garray) {
		BT_LOGE_STR("Failed to allocate a GPtrArray.");
		g_free(array_obj);
		array_obj = NULL;
		goto end;
	}

	BT_LOGD("Created array value object: addr=%p",
		array_obj);

end:
	return (void *) array_obj;
}
Example #6
0
BT_HIDDEN
struct bt_value *bt_attributes_create(void)
{
	struct bt_value *attr_obj;

	/*
	 * Attributes: array value object of array value objects, each one
	 * containing two entries: a string value object (attributes
	 * field name), and a value object (attributes field value).
	 *
	 * Example (JSON representation):
	 *
	 *     [
	 *         ["hostname", "eeppdesk"],
	 *         ["sysname", "Linux"],
	 *         ["tracer_major", 2],
	 *         ["tracer_minor", 5]
	 *     ]
	 */
	BT_LOGD_STR("Creating attributes object.");
	attr_obj = bt_value_array_create();
	if (!attr_obj) {
		BT_LOGE_STR("Failed to create array value.");
	} else {
		BT_LOGD("Created attributes object: addr=%p",
			attr_obj);
	}

	return attr_obj;
}
Example #7
0
struct bt_ctf_event_class *bt_ctf_event_class_create(const char *name)
{
	struct bt_ctf_event_class *ctf_event_class = NULL;
	int ret;

	if (!name) {
		BT_LOGW_STR("Invalid parameter: name is NULL.");
		goto error;
	}

	BT_LOGD("Creating event class object: name=\"%s\"",
		name);
	ctf_event_class = g_new0(struct bt_ctf_event_class, 1);
	if (!ctf_event_class) {
		BT_LOGE_STR("Failed to allocate one event class.");
		goto error;
	}

	ret = bt_ctf_event_class_common_initialize(BT_CTF_TO_COMMON(ctf_event_class),
		name, bt_ctf_event_class_destroy,
		(bt_ctf_field_type_structure_create_func)
			bt_ctf_field_type_structure_create);
	if (ret) {
		goto error;
	}

	goto end;

error:
	bt_ctf_object_put_ref(ctf_event_class);

end:
	return ctf_event_class;
}
Example #8
0
static inline
struct bt_value *bt_value_integer_create_init(enum bt_value_type type,
		uint64_t uval)
{
	struct bt_value_integer *integer_obj;

	BT_ASSERT(type == BT_VALUE_TYPE_UNSIGNED_INTEGER ||
		type == BT_VALUE_TYPE_SIGNED_INTEGER);

	if (type == BT_VALUE_TYPE_UNSIGNED_INTEGER) {
		BT_LOGD("Creating unsigned integer value object: val=%" PRIu64,
			uval);
	} else {
		BT_LOGD("Creating signed integer value object: val=%" PRId64,
			(int64_t) uval);
	}

	integer_obj = g_new0(struct bt_value_integer, 1);
	if (!integer_obj) {
		BT_LOGE_STR("Failed to allocate one integer value object.");
		goto end;
	}

	integer_obj->base = bt_value_create_base(type);
	integer_obj->value.u = uval;
	BT_LOGD("Created %ssigned integer value object: addr=%p",
		type == BT_VALUE_TYPE_UNSIGNED_INTEGER ? "un" : "",
		integer_obj);

end:
	return (void *) integer_obj;
}
Example #9
0
BT_HIDDEN
struct bt_port *bt_port_create(struct bt_component *parent_component,
		enum bt_port_type type, const char *name, void *user_data)
{
	struct bt_port *port = NULL;

	assert(name);
	assert(parent_component);
	assert(type == BT_PORT_TYPE_INPUT || type == BT_PORT_TYPE_OUTPUT);

	if (strlen(name) == 0) {
		BT_LOGW_STR("Invalid parameter: name is an empty string.");
		goto end;
	}

	port = g_new0(struct bt_port, 1);
	if (!port) {
		BT_LOGE_STR("Failed to allocate one port.");
		goto end;
	}

	BT_LOGD("Creating port for component: "
		"comp-addr=%p, comp-name=\"%s\", port-type=%s, "
		"port-name=\"%s\"",
		parent_component, bt_component_get_name(parent_component),
		bt_port_type_string(type), name);

	bt_object_init(port, bt_port_destroy);
	port->name = g_string_new(name);
	if (!port->name) {
		BT_LOGE_STR("Failed to allocate one GString.");
		BT_PUT(port);
		goto end;
	}

	port->type = type;
	port->user_data = user_data;
	bt_object_set_parent(port, &parent_component->base);
	BT_LOGD("Created port for component: "
		"comp-addr=%p, comp-name=\"%s\", port-type=%s, "
		"port-name=\"%s\", port-addr=%p",
		parent_component, bt_component_get_name(parent_component),
		bt_port_type_string(type), name, port);

end:
	return port;
}
Example #10
0
BT_HIDDEN
bt_self_message_iterator_status ctf_fs_iterator_init(
		bt_self_message_iterator *self_msg_iter,
		bt_self_component_source *self_comp,
		bt_self_component_port_output *self_port)
{
	struct ctf_fs_port_data *port_data;
	struct ctf_fs_msg_iter_data *msg_iter_data = NULL;
	bt_self_message_iterator_status ret =
		BT_SELF_MESSAGE_ITERATOR_STATUS_OK;

	port_data = bt_self_component_port_get_data(
		bt_self_component_port_output_as_self_component_port(
			self_port));
	BT_ASSERT(port_data);
	msg_iter_data = g_new0(struct ctf_fs_msg_iter_data, 1);
	if (!msg_iter_data) {
		ret = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
		goto error;
	}

	msg_iter_data->pc_msg_iter = self_msg_iter;
	msg_iter_data->msg_iter = bt_msg_iter_create(
		port_data->ds_file_group->ctf_fs_trace->metadata->tc,
		bt_common_get_page_size() * 8,
		ctf_fs_ds_file_medops, NULL);
	if (!msg_iter_data->msg_iter) {
		BT_LOGE_STR("Cannot create a CTF message iterator.");
		ret = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
		goto error;
	}

	msg_iter_data->ds_file_group = port_data->ds_file_group;
	if (ctf_fs_iterator_reset(msg_iter_data)) {
		ret = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
		goto error;
	}

	bt_self_message_iterator_set_data(self_msg_iter,
		msg_iter_data);
	if (ret != BT_SELF_MESSAGE_ITERATOR_STATUS_OK) {
		goto error;
	}

	msg_iter_data = NULL;
	goto end;

error:
	bt_self_message_iterator_set_data(self_msg_iter, NULL);

end:
	ctf_fs_msg_iter_data_destroy(msg_iter_data);
	return ret;
}
Example #11
0
static
struct bt_value *bt_value_array_copy(const struct bt_value *array_obj)
{
	int i;
	int ret;
	struct bt_value *copy_obj;
	struct bt_value_array *typed_array_obj;

	BT_LOGD("Copying array value: addr=%p", array_obj);
	typed_array_obj = BT_VALUE_TO_ARRAY(array_obj);
	copy_obj = bt_value_array_create();
	if (!copy_obj) {
		BT_LOGE_STR("Cannot create empty array value.");
		goto end;
	}

	for (i = 0; i < typed_array_obj->garray->len; ++i) {
		struct bt_value *element_obj_copy = NULL;
		const struct bt_value *element_obj =
			bt_value_array_borrow_element_by_index_const(
				array_obj, i);

		BT_ASSERT(element_obj);
		BT_LOGD("Copying array value's element: element-addr=%p, "
			"index=%d", element_obj, i);
		ret = bt_value_copy(element_obj, &element_obj_copy);
		if (ret) {
			BT_LOGE("Cannot copy array value's element: "
				"array-addr=%p, index=%d",
				array_obj, i);
			BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
			goto end;
		}

		BT_ASSERT(element_obj_copy);
		ret = bt_value_array_append_element(copy_obj,
			(void *) element_obj_copy);
		BT_OBJECT_PUT_REF_AND_RESET(element_obj_copy);
		if (ret) {
			BT_LOGE("Cannot append to array value: addr=%p",
				array_obj);
			BT_OBJECT_PUT_REF_AND_RESET(copy_obj);
			goto end;
		}
	}

	BT_LOGD("Copied array value: original-addr=%p, copy-addr=%p",
		array_obj, copy_obj);

end:
	return copy_obj;
}
Example #12
0
BT_HIDDEN
int bt_ctf_event_class_common_initialize(struct bt_ctf_event_class_common *event_class,
		const char *name, bt_ctf_object_release_func release_func,
		bt_ctf_field_type_structure_create_func ft_struct_create_func)
{
	int ret = 0;

	BT_LOGD("Initializing common event class object: name=\"%s\"",
		name);
	bt_ctf_object_init_shared_with_parent(&event_class->base, release_func);
	event_class->payload_field_type = ft_struct_create_func();
	if (!event_class->payload_field_type) {
		BT_LOGE_STR("Cannot create event class's initial payload field type object.");
		goto error;
	}

	event_class->id = -1;
	event_class->name = g_string_new(name);
	if (!event_class->name) {
		BT_LOGE_STR("Failed to allocate a GString.");
		goto error;
	}

	event_class->emf_uri = g_string_new(NULL);
	if (!event_class->emf_uri) {
		BT_LOGE_STR("Failed to allocate a GString.");
		goto error;
	}

	event_class->log_level = BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED;
	BT_LOGD("Initialized common event class object: addr=%p, name=\"%s\"",
		event_class, bt_ctf_event_class_common_get_name(event_class));
	return ret;

error:
	ret = -1;
	return ret;
}
Example #13
0
BT_HIDDEN
int bt_attributes_set_field_value(struct bt_value *attr_obj,
		const char *name, struct bt_value *value_obj)
{
	int ret = 0;
	struct bt_value *attr_field_obj = NULL;

	if (!attr_obj || !name || !value_obj) {
		BT_LOGW("Invalid parameter: attributes object, name, or value object is NULL: "
			"attr-value-addr=%p, name-addr=%p, value-addr=%p",
			attr_obj, name, value_obj);
		ret = -1;
		goto end;
	}

	attr_field_obj = bt_attributes_get_field_by_name(attr_obj, name);
	if (attr_field_obj) {
		ret = bt_value_array_set(attr_field_obj,
			BT_ATTR_VALUE_INDEX, value_obj);
		goto end;
	}

	attr_field_obj = bt_value_array_create();
	if (!attr_field_obj) {
		BT_LOGE_STR("Failed to create empty array value.");
		ret = -1;
		goto end;
	}

	ret = bt_value_array_append_string(attr_field_obj, name);
	ret |= bt_value_array_append(attr_field_obj, value_obj);
	if (ret) {
		BT_LOGE("Cannot append elements to array value: addr=%p",
			attr_field_obj);
		goto end;
	}

	ret = bt_value_array_append(attr_obj, attr_field_obj);
	if (ret) {
		BT_LOGE("Cannot append element to array value: "
			"array-value-addr=%p, element-value-addr=%p",
			attr_obj, attr_field_obj);
	}

end:
	BT_PUT(attr_field_obj);

	return ret;
}
Example #14
0
static
int set_trace_name(bt_trace *trace, const char *name_suffix)
{
	int ret = 0;
	const bt_trace_class *tc = bt_trace_borrow_class_const(trace);
	const bt_value *val;
	GString *name;

	name = g_string_new(NULL);
	if (!name) {
		BT_LOGE_STR("Failed to allocate a GString.");
		ret = -1;
		goto end;
	}

	/*
	 * Check if we have a trace environment string value named `hostname`.
	 * If so, use it as the trace name's prefix.
	 */
	val = bt_trace_class_borrow_environment_entry_value_by_name_const(
		tc, "hostname");
	if (val && bt_value_is_string(val)) {
		g_string_append(name, bt_value_string_get(val));

		if (name_suffix) {
			g_string_append_c(name, G_DIR_SEPARATOR);
		}
	}

	if (name_suffix) {
		g_string_append(name, name_suffix);
	}

	ret = bt_trace_set_name(trace, name->str);
	if (ret) {
		goto end;
	}

	goto end;

end:
	if (name) {
		g_string_free(name, TRUE);
	}

	return ret;
}
Example #15
0
struct bt_value *bt_value_bool_create_init(bt_bool val)
{
	struct bt_value_bool *bool_obj;

	BT_LOGD("Creating boolean value object: val=%d", val);
	bool_obj = g_new0(struct bt_value_bool, 1);
	if (!bool_obj) {
		BT_LOGE_STR("Failed to allocate one boolean value object.");
		goto end;
	}

	bool_obj->base = bt_value_create_base(BT_VALUE_TYPE_BOOL);
	bool_obj->value = val;
	BT_LOGD("Created boolean value object: addr=%p", bool_obj);

end:
	return (void *) bool_obj;
}
Example #16
0
struct bt_value *bt_value_real_create_init(double val)
{
	struct bt_value_real *real_obj;

	BT_LOGD("Creating real number value object: val=%f", val);
	real_obj = g_new0(struct bt_value_real, 1);
	if (!real_obj) {
		BT_LOGE_STR("Failed to allocate one real number value object.");
		goto end;
	}

	real_obj->base = bt_value_create_base(BT_VALUE_TYPE_REAL);
	real_obj->value = val;
	BT_LOGD("Created real number value object: addr=%p",
		real_obj);

end:
	return (void *) real_obj;
}
Example #17
0
enum bt_value_status bt_value_copy(const struct bt_value *object,
		struct bt_value **copy_obj)
{
	enum bt_value_status status = BT_VALUE_STATUS_OK;

	BT_ASSERT_PRE_NON_NULL(object, "Value object");
	BT_ASSERT_PRE_NON_NULL(copy_obj, "Value object copy (output)");
	BT_LOGD("Copying value object: addr=%p", object);
	*copy_obj = copy_funcs[object->type](object);
	if (*copy_obj) {
		BT_LOGD("Copied value object: copy-value-addr=%p",
			copy_obj);
	} else {
		status = BT_VALUE_STATUS_NOMEM;
		*copy_obj = NULL;
		BT_LOGE_STR("Failed to copy value object.");
	}

	return status;
}
Example #18
0
static inline
void handle_lib_unload_event(FILE *err, struct debug_info *debug_info,
		struct bt_event *event)
{
	struct proc_debug_info_sources *proc_dbg_info_src;
	uint64_t baddr;
	int64_t vpid;
	gpointer key_ptr = NULL;
	int ret;

	ret = get_payload_unsigned_int_field_value(err,
			event, BADDR_FIELD_NAME, &baddr);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			BADDR_FIELD_NAME " field.");
		ret = -1;
		goto end;
	}

	ret = get_stream_event_context_int_field_value(err, event,
		VPID_FIELD_NAME, &vpid);
	if (ret) {
		goto end;
	}

	proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
			debug_info->vpid_to_proc_dbg_info_src, vpid);
	if (!proc_dbg_info_src) {
		goto end;
	}

	key_ptr = (gpointer) &baddr;
	(void) g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
			key_ptr);
end:
	return;
}
Example #19
0
BT_HIDDEN
struct bt_clock_snapshot *bt_clock_snapshot_new(
		struct bt_clock_class *clock_class)
{
	struct bt_clock_snapshot *ret = NULL;

	BT_ASSERT(clock_class);
	BT_LIB_LOGD("Creating clock snapshot object: %![cc-]+K=",
		clock_class);
	ret = g_new0(struct bt_clock_snapshot, 1);
	if (!ret) {
		BT_LOGE_STR("Failed to allocate one clock snapshot.");
		goto end;
	}

	bt_object_init_unique(&ret->base);
	ret->clock_class = clock_class;
	bt_object_get_no_null_check(clock_class);
	bt_clock_class_freeze(clock_class);
	BT_LIB_LOGD("Created clock snapshot object: %!+k", ret);

end:
	return ret;
}
Example #20
0
struct bt_event *bt_event_create(struct bt_event_class *event_class)
{
	int ret;
	enum bt_validation_flag validation_flags =
		BT_VALIDATION_FLAG_STREAM |
		BT_VALIDATION_FLAG_EVENT;
	struct bt_event *event = NULL;
	struct bt_trace *trace = NULL;
	struct bt_stream_class *stream_class = NULL;
	struct bt_field_type *packet_header_type = NULL;
	struct bt_field_type *packet_context_type = NULL;
	struct bt_field_type *event_header_type = NULL;
	struct bt_field_type *stream_event_ctx_type = NULL;
	struct bt_field_type *event_context_type = NULL;
	struct bt_field_type *event_payload_type = NULL;
	struct bt_field *event_header = NULL;
	struct bt_field *stream_event_context = NULL;
	struct bt_field *event_context = NULL;
	struct bt_field *event_payload = NULL;
	struct bt_value *environment = NULL;
	struct bt_validation_output validation_output = { 0 };
	int trace_valid = 0;

	BT_LOGD("Creating event object: event-class-addr=%p, "
		"event-class-name=\"%s\", event-class-id=%" PRId64,
		event_class, bt_event_class_get_name(event_class),
		bt_event_class_get_id(event_class));

	if (!event_class) {
		BT_LOGW_STR("Invalid parameter: event class is NULL.");
		goto error;
	}

	stream_class = bt_event_class_get_stream_class(event_class);

	/*
	 * We disallow the creation of an event if its event class has not been
	 * associated to a stream class.
	 */
	if (!stream_class) {
		BT_LOGW_STR("Event class is not part of a stream class.");
		goto error;
	}

	/* The event class was frozen when added to its stream class */
	assert(event_class->frozen);

	/* Validate the trace (if any), the stream class, and the event class */
	trace = bt_stream_class_get_trace(stream_class);
	if (trace) {
		BT_LOGD_STR("Event's class is part of a trace.");
		packet_header_type = bt_trace_get_packet_header_type(trace);
		trace_valid = trace->valid;
		assert(trace_valid);
		environment = trace->environment;
	}

	packet_context_type = bt_stream_class_get_packet_context_type(
		stream_class);
	event_header_type = bt_stream_class_get_event_header_type(
		stream_class);
	stream_event_ctx_type = bt_stream_class_get_event_context_type(
		stream_class);
	event_context_type = bt_event_class_get_context_type(event_class);
	event_payload_type = bt_event_class_get_payload_type(event_class);
	ret = bt_validate_class_types(environment, packet_header_type,
		packet_context_type, event_header_type, stream_event_ctx_type,
		event_context_type, event_payload_type, trace_valid,
		stream_class->valid, event_class->valid,
		&validation_output, validation_flags);
	BT_PUT(packet_header_type);
	BT_PUT(packet_context_type);
	BT_PUT(event_header_type);
	BT_PUT(stream_event_ctx_type);
	BT_PUT(event_context_type);
	BT_PUT(event_payload_type);
	if (ret) {
		/*
		 * This means something went wrong during the validation
		 * process, not that the objects are invalid.
		 */
		BT_LOGE("Failed to validate event and parents: ret=%d", ret);
		goto error;
	}

	if ((validation_output.valid_flags & validation_flags) !=
			validation_flags) {
		/* Invalid trace/stream class/event class */
		BT_LOGW("Invalid trace, stream class, or event class: "
			"valid-flags=0x%x", validation_output.valid_flags);
		goto error;
	}

	/*
	 * At this point we know the trace (if associated to the stream
	 * class), the stream class, and the event class, with their
	 * current types, are valid. We may proceed with creating
	 * the event.
	 */
	event = g_new0(struct bt_event, 1);
	if (!event) {
		BT_LOGE_STR("Failed to allocate one event.");
		goto error;
	}

	bt_object_init(event, bt_event_destroy);

	/*
	 * event does not share a common ancestor with the event class; it has
	 * to guarantee its existence by holding a reference. This reference
	 * shall be released once the event is associated to a stream since,
	 * from that point, the event and its class will share the same
	 * lifetime.
	 */
	event->event_class = bt_get(event_class);
	event->clock_values = g_hash_table_new_full(g_direct_hash,
			g_direct_equal, bt_put, bt_put);

	if (validation_output.event_header_type) {
		BT_LOGD("Creating initial event header field: ft-addr=%p",
			validation_output.event_header_type);
		event_header =
			bt_field_create(validation_output.event_header_type);
		if (!event_header) {
			BT_LOGE_STR("Cannot create initial event header field object.");
			goto error;
		}
	}

	if (validation_output.stream_event_ctx_type) {
		BT_LOGD("Creating initial stream event context field: ft-addr=%p",
			validation_output.stream_event_ctx_type);
		stream_event_context = bt_field_create(
			validation_output.stream_event_ctx_type);
		if (!stream_event_context) {
			BT_LOGE_STR("Cannot create initial stream event context field object.");
			goto error;
		}
	}

	if (validation_output.event_context_type) {
		BT_LOGD("Creating initial event context field: ft-addr=%p",
			validation_output.event_context_type);
		event_context = bt_field_create(
			validation_output.event_context_type);
		if (!event_context) {
			BT_LOGE_STR("Cannot create initial event context field object.");
			goto error;
		}
	}

	if (validation_output.event_payload_type) {
		BT_LOGD("Creating initial event payload field: ft-addr=%p",
			validation_output.event_payload_type);
		event_payload = bt_field_create(
			validation_output.event_payload_type);
		if (!event_payload) {
			BT_LOGE_STR("Cannot create initial event payload field object.");
			goto error;
		}
	}

	/*
	 * At this point all the fields are created, potentially from
	 * validated copies of field types, so that the field types and
	 * fields can be replaced in the trace, stream class,
	 * event class, and created event.
	 */
	bt_validation_replace_types(trace, stream_class,
		event_class, &validation_output, validation_flags);
	BT_MOVE(event->event_header, event_header);
	BT_MOVE(event->stream_event_context, stream_event_context);
	BT_MOVE(event->context_payload, event_context);
	BT_MOVE(event->fields_payload, event_payload);

	/*
	 * Put what was not moved in bt_validation_replace_types().
	 */
	bt_validation_output_put_types(&validation_output);

	/*
	 * Freeze the stream class since the event header must not be changed
	 * anymore.
	 */
	bt_stream_class_freeze(stream_class);

	/*
	 * Mark stream class, and event class as valid since
	 * they're all frozen now.
	 */
	stream_class->valid = 1;
	event_class->valid = 1;

	/* Put stuff we borrowed from the event class */
	BT_PUT(stream_class);
	BT_PUT(trace);
	BT_LOGD("Created event object: addr=%p, event-class-name=\"%s\", "
		"event-class-id=%" PRId64,
		event, bt_event_class_get_name(event->event_class),
		bt_event_class_get_id(event_class));
	return event;

error:
	bt_validation_output_put_types(&validation_output);
	BT_PUT(event);
	BT_PUT(stream_class);
	BT_PUT(trace);
	BT_PUT(event_header);
	BT_PUT(stream_event_context);
	BT_PUT(event_context);
	BT_PUT(event_payload);
	assert(!packet_header_type);
	assert(!packet_context_type);
	assert(!event_header_type);
	assert(!stream_event_ctx_type);
	assert(!event_context_type);
	assert(!event_payload_type);

	return event;
}
G_MODULE_EXPORT
struct bt_plugin_set *bt_plugin_python_create_all_from_file(const char *path)
{
	struct bt_plugin_set *plugin_set = NULL;
	struct bt_plugin *plugin = NULL;
	PyObject *py_plugin_info = NULL;
	gchar *basename = NULL;
	size_t path_len;

	assert(path);

	if (python_state == PYTHON_STATE_CANNOT_INITIALIZE) {
		/*
		 * We do not even care about the rest of the function
		 * here because we already know Python cannot be fully
		 * initialized.
		 */
		goto error;
	}

	BT_LOGD("Creating all Python plugins from file: path=\"%s\"", path);
	path_len = strlen(path);

	/* File name ends with `.py` */
	if (strncmp(path + path_len - PYTHON_PLUGIN_FILE_EXT_LEN,
			PYTHON_PLUGIN_FILE_EXT,
			PYTHON_PLUGIN_FILE_EXT_LEN) != 0) {
		BT_LOGD("Skipping non-Python file: path=\"%s\"", path);
		goto error;
	}

	/* File name starts with `bt_plugin_` */
	basename = g_path_get_basename(path);
	if (!basename) {
		BT_LOGW("Cannot get path's basename: path=\"%s\"", path);
		goto error;
	}

	if (strncmp(basename, PYTHON_PLUGIN_FILE_PREFIX,
			PYTHON_PLUGIN_FILE_PREFIX_LEN) != 0) {
		BT_LOGD("Skipping Python file not starting with `%s`: "
			"path=\"%s\"", PYTHON_PLUGIN_FILE_PREFIX, path);
		goto error;
	}

	/*
	 * Initialize Python now.
	 *
	 * This is not done in the library contructor because the
	 * interpreter is somewhat slow to initialize. If you don't
	 * have any potential Python plugins, you don't need to endure
	 * this waiting time everytime you load the library.
	 */
	init_python();
	if (python_state != PYTHON_STATE_FULLY_INITIALIZED) {
		/*
		 * For some reason we cannot initialize Python,
		 * import the required modules, and get the required
		 * attributes from them.
		 */
		BT_LOGI("Failed to initialize Python interpreter.");
		goto error;
	}

	/*
	 * Call bt2.py_plugin._try_load_plugin_module() with this path
	 * to get plugin info if the plugin is loadable and complete.
	 * This function returns None when there's an error, but just in
	 * case we also manually clear the last Python error state.
	 */
	BT_LOGD_STR("Getting Python plugin info object from Python module.");
	py_plugin_info = PyObject_CallFunction(py_try_load_plugin_module_func,
		"(s)", path);
	if (!py_plugin_info || py_plugin_info == Py_None) {
		BT_LOGW("Cannot load Python plugin: path=\"%s\"", path);
		print_python_traceback_warn();
		PyErr_Clear();
		goto error;
	}

	/*
	 * Get bt_plugin from plugin info object.
	 */
	plugin = bt_plugin_from_python_plugin_info(py_plugin_info);
	if (!plugin) {
		BT_LOGW("Cannot create plugin object from Python plugin info object: "
			"path=\"%s\", py-plugin-info-addr=%p",
			path, py_plugin_info);
		goto error;
	}

	bt_plugin_set_path(plugin, path);
	plugin_set = bt_plugin_set_create();
	if (!plugin_set) {
		BT_LOGE_STR("Cannot create empty plugin set.");
		goto error;
	}

	bt_plugin_set_add_plugin(plugin_set, plugin);
	BT_LOGD("Created all Python plugins from file: path=\"%s\", "
		"plugin-addr=%p, plugin-name=\"%s\"",
		path, plugin, bt_plugin_get_name(plugin));
	goto end;

error:
	BT_PUT(plugin_set);

end:
	bt_put(plugin);
	Py_XDECREF(py_plugin_info);
	g_free(basename);
	return plugin_set;
}
static
struct bt_plugin *bt_plugin_from_python_plugin_info(PyObject *plugin_info)
{
	struct bt_plugin *plugin = NULL;
	PyObject *py_name = NULL;
	PyObject *py_author = NULL;
	PyObject *py_description = NULL;
	PyObject *py_license = NULL;
	PyObject *py_version = NULL;
	PyObject *py_comp_class_addrs = NULL;
	const char *name = NULL;
	const char *author = NULL;
	const char *description = NULL;
	const char *license = NULL;
	unsigned int major = 0, minor = 0, patch = 0;
	const char *version_extra = NULL;
	int ret;

	assert(plugin_info);
	assert(python_state == PYTHON_STATE_FULLY_INITIALIZED);
	py_name = PyObject_GetAttrString(plugin_info, "name");
	if (!py_name) {
		BT_LOGW("Cannot find `name` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	py_author = PyObject_GetAttrString(plugin_info, "author");
	if (!py_author) {
		BT_LOGW("Cannot find `author` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	py_description = PyObject_GetAttrString(plugin_info, "description");
	if (!py_description) {
		BT_LOGW("Cannot find `desciption` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	py_license = PyObject_GetAttrString(plugin_info, "license");
	if (!py_license) {
		BT_LOGW("Cannot find `license` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	py_version = PyObject_GetAttrString(plugin_info, "version");
	if (!py_version) {
		BT_LOGW("Cannot find `version` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	py_comp_class_addrs = PyObject_GetAttrString(plugin_info,
		"comp_class_addrs");
	if (!py_comp_class_addrs) {
		BT_LOGW("Cannot find `comp_class_addrs` attribute in Python plugin info object: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	if (PyUnicode_Check(py_name)) {
		name = PyUnicode_AsUTF8(py_name);
		if (!name) {
			BT_LOGW("Cannot decode Python plugin name string: "
				"py-plugin-info-addr=%p", plugin_info);
			goto error;
		}
	} else {
		/* Plugin name is mandatory */
		BT_LOGW("Plugin name is not a string: "
			"py-plugin-info-addr=%p", plugin_info);
		goto error;
	}

	if (PyUnicode_Check(py_author)) {
		author = PyUnicode_AsUTF8(py_author);
		if (!author) {
			BT_LOGW("Cannot decode Python plugin author string: "
				"py-plugin-info-addr=%p", plugin_info);
			goto error;
		}
	}

	if (PyUnicode_Check(py_description)) {
		description = PyUnicode_AsUTF8(py_description);
		if (!description) {
			BT_LOGW("Cannot decode Python plugin description string: "
				"py-plugin-info-addr=%p", plugin_info);
			goto error;
		}
	}

	if (PyUnicode_Check(py_license)) {
		license = PyUnicode_AsUTF8(py_license);
		if (!license) {
			BT_LOGW("Cannot decode Python plugin license string: "
				"py-plugin-info-addr=%p", plugin_info);
			goto error;
		}
	}

	if (PyTuple_Check(py_version)) {
		if (PyTuple_Size(py_version) >= 3) {
			PyObject *py_major = PyTuple_GetItem(py_version, 0);
			PyObject *py_minor = PyTuple_GetItem(py_version, 1);
			PyObject *py_patch = PyTuple_GetItem(py_version, 2);

			assert(py_major);
			assert(py_minor);
			assert(py_patch);

			if (PyLong_Check(py_major)) {
				major = PyLong_AsUnsignedLong(py_major);
			}

			if (PyLong_Check(py_minor)) {
				minor = PyLong_AsUnsignedLong(py_minor);
			}

			if (PyLong_Check(py_patch)) {
				patch = PyLong_AsUnsignedLong(py_patch);
			}

			if (PyErr_Occurred()) {
				/* Overflow error, most probably */
				BT_LOGW("Invalid Python plugin version format: "
					"py-plugin-info-addr=%p", plugin_info);
				goto error;
			}
		}

		if (PyTuple_Size(py_version) >= 4) {
			PyObject *py_extra = PyTuple_GetItem(py_version, 3);

			assert(py_extra);

			if (PyUnicode_Check(py_extra)) {
				version_extra = PyUnicode_AsUTF8(py_extra);
				if (!version_extra) {
				BT_LOGW("Cannot decode Python plugin version's extra string: "
					"py-plugin-info-addr=%p", plugin_info);
					goto error;
				}
			}
		}
	}

	plugin = bt_plugin_create_empty(BT_PLUGIN_TYPE_PYTHON);
	if (!plugin) {
		BT_LOGE_STR("Cannot create empty plugin object.");
		goto error;
	}

	bt_plugin_set_name(plugin, name);

	if (description) {
		bt_plugin_set_description(plugin, description);
	}

	if (author) {
		bt_plugin_set_author(plugin, author);
	}

	if (license) {
		bt_plugin_set_license(plugin, license);
	}

	bt_plugin_set_version(plugin, major, minor, patch, version_extra);

	if (PyList_Check(py_comp_class_addrs)) {
		size_t i;

		for (i = 0; i < PyList_Size(py_comp_class_addrs); i++) {
			struct bt_component_class *comp_class;
			PyObject *py_comp_class_addr;

			py_comp_class_addr =
				PyList_GetItem(py_comp_class_addrs, i);
			assert(py_comp_class_addr);
			if (PyLong_Check(py_comp_class_addr)) {
				comp_class = (struct bt_component_class *)
					PyLong_AsUnsignedLongLong(py_comp_class_addr);
			} else {
				BT_LOGW("Component class address is not an integer in Python plugin info object: "
					"py-plugin-info-addr=%p, index=%zu",
					plugin_info, i);
				continue;
			}

			ret = bt_plugin_add_component_class(plugin, comp_class);
			if (ret < 0) {
				BT_LOGE("Cannot add component class to plugin: "
					"py-plugin-info-addr=%p, "
					"plugin-addr=%p, plugin-name=\"%s\", "
					"comp-class-addr=%p, "
					"comp-class-name=\"%s\", "
					"comp-class-type=%s",
					plugin_info,
					plugin, bt_plugin_get_name(plugin),
					comp_class,
					bt_component_class_get_name(comp_class),
					bt_component_class_type_string(
						bt_component_class_get_type(comp_class)));
				continue;
			}
		}
	}

	bt_plugin_freeze(plugin);

	goto end;

error:
	print_python_traceback_warn();
	pyerr_clear();
	BT_PUT(plugin);

end:
	Py_XDECREF(py_name);
	Py_XDECREF(py_author);
	Py_XDECREF(py_description);
	Py_XDECREF(py_license);
	Py_XDECREF(py_version);
	Py_XDECREF(py_comp_class_addrs);
	return plugin;
}
Example #23
0
static inline
struct bt_message *create_discarded_items_message(
		struct bt_self_message_iterator *self_msg_iter,
		enum bt_message_type type, struct bt_stream *stream,
		bool with_cs,
		uint64_t beginning_raw_value, uint64_t end_raw_value)
{
	struct bt_message_discarded_items *message;
	struct bt_stream_class *stream_class;

	BT_ASSERT_PRE_NON_NULL(self_msg_iter, "Message iterator");
	BT_ASSERT_PRE_NON_NULL(stream, "Stream");
	stream_class = bt_stream_borrow_class(stream);
	BT_ASSERT(stream_class);
	BT_ASSERT_PRE((with_cs && stream_class->default_clock_class) ||
		(!with_cs && !stream_class->default_clock_class),
		"Creating a message with a default clock snapshot, but without "
		"a default clock class, or without a default clock snapshot, "
		"but with a default clock class: ",
		"type=%s, %![stream-]+s, %![sc-]+S, with-cs=%d, "
		"cs-begin-val=%" PRIu64 ", cs-end-val=%" PRIu64,
		bt_message_type_string(type), stream, stream_class,
		with_cs, beginning_raw_value, end_raw_value);
	BT_LIB_LOGD("Creating discarded items message object: "
		"type=%s, %![stream-]+s, %![sc-]+S, with-cs=%d, "
		"cs-begin-val=%" PRIu64 ", cs-end-val=%" PRIu64,
		bt_message_type_string(type), stream, stream_class,
		with_cs, beginning_raw_value, end_raw_value);
	message = g_new0(struct bt_message_discarded_items, 1);
	if (!message) {
		BT_LOGE_STR("Failed to allocate one discarded items message.");
		goto error;
	}

	bt_message_init(&message->parent, type,
		destroy_discarded_items_message, NULL);
	message->stream = stream;
	bt_object_get_no_null_check(message->stream);

	if (with_cs) {
		BT_ASSERT(stream_class->default_clock_class);
		message->default_begin_cs = bt_clock_snapshot_create(
			stream_class->default_clock_class);
		if (!message->default_begin_cs) {
			goto error;
		}

		bt_clock_snapshot_set_raw_value(message->default_begin_cs,
			beginning_raw_value);

		message->default_end_cs = bt_clock_snapshot_create(
			stream_class->default_clock_class);
		if (!message->default_end_cs) {
			goto error;
		}

		bt_clock_snapshot_set_raw_value(message->default_end_cs,
			end_raw_value);
	}

	bt_property_uint_init(&message->count,
		BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE, 0);
	BT_LIB_LOGD("Created discarded items message object: "
		"%![msg-]+n, %![stream-]+s, %![sc-]+S", message,
		stream, stream_class);

	return (void *) &message->parent;

error:
	return NULL;
}
Example #24
0
static
void handle_bin_info_event(FILE *err, struct debug_info *debug_info,
		struct bt_event *event, bool has_pic_field)
{
	struct proc_debug_info_sources *proc_dbg_info_src;
	struct bin_info *bin;
	uint64_t baddr, memsz;
	int64_t vpid;
	const char *path;
	gpointer key = NULL;
	bool is_pic;
	int ret;

	ret = get_payload_unsigned_int_field_value(err,
			event, BADDR_FIELD_NAME, &baddr);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			BADDR_FIELD_NAME " field.");
		goto end;
	}

	ret = get_payload_unsigned_int_field_value(err,
			event, MEMSZ_FIELD_NAME, &memsz);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			MEMSZ_FIELD_NAME " field.");
		goto end;
	}

	/*
	 * This field is not produced by the dlopen event emitted before
	 * lttng-ust 2.9.
	 */
	ret = get_payload_string_field_value(err,
			event, PATH_FIELD_NAME, &path);
	if (ret || !path) {
		goto end;
	}

	if (has_pic_field) {
		uint64_t tmp;

		ret = get_payload_unsigned_int_field_value(err,
				event, IS_PIC_FIELD_NAME, &tmp);
		if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			IS_PIC_FIELD_NAME " field.");
			ret = -1;
			goto end;
		}
		is_pic = (tmp == 1);
	} else {
		/*
		 * dlopen has no is_pic field, because the shared
		 * object is always PIC.
		 */
		is_pic = true;
	}

	ret = get_stream_event_context_int_field_value(err, event,
		VPID_FIELD_NAME, &vpid);
	if (ret) {
		goto end;
	}

	if (memsz == 0) {
		/* Ignore VDSO. */
		goto end;
	}

	proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
			debug_info->vpid_to_proc_dbg_info_src, vpid);
	if (!proc_dbg_info_src) {
		goto end;
	}

	key = g_new0(uint64_t, 1);
	if (!key) {
		goto end;
	}

	*((uint64_t *) key) = baddr;

	bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
			key);
	if (bin) {
		goto end;
	}

	bin = bin_info_create(path, baddr, memsz, is_pic,
		debug_info->comp->arg_debug_dir,
		debug_info->comp->arg_target_prefix);
	if (!bin) {
		goto end;
	}

	g_hash_table_insert(proc_dbg_info_src->baddr_to_bin_info,
			key, bin);
	/* Ownership passed to ht. */
	key = NULL;

end:
	g_free(key);
	return;
}
Example #25
0
static
void handle_statedump_debug_link_event(FILE *err, struct debug_info *debug_info,
		struct bt_event *event)
{
	struct proc_debug_info_sources *proc_dbg_info_src;
	struct bin_info *bin = NULL;
	int64_t vpid;
	uint64_t baddr;
	const char *filename = NULL;
	uint32_t crc32;
	uint64_t tmp;
	int ret;

	ret = get_stream_event_context_int_field_value(err, event,
			VPID_FIELD_NAME, &vpid);
	if (ret) {
		goto end;
	}

	ret = get_payload_unsigned_int_field_value(err,
			event, BADDR_FIELD_NAME, &baddr);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			BADDR_FIELD_NAME " field.");
		ret = -1;
		goto end;
	}

	ret = get_payload_unsigned_int_field_value(err, event, CRC32_FIELD_NAME,
		&tmp);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			CRC32_FIELD_NAME " field.");
		ret = -1;
		goto end;
	}
	crc32 = (uint32_t) tmp;

	ret = get_payload_string_field_value(err,
			event, FILENAME_FIELD_NAME, &filename);
	if (ret) {
		BT_LOGE_STR("Failed to get string value for "
			FILENAME_FIELD_NAME " field.");
		ret = -1;
		goto end;
	}

	proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
			debug_info->vpid_to_proc_dbg_info_src, vpid);
	if (!proc_dbg_info_src) {
		goto end;
	}

	bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
			(gpointer) &baddr);
	if (!bin) {
		/*
		 * The debug_link event comes after the bin has been
		 * created. If it isn't found, just ignore this event.
		 */
		goto end;
	}

	bin_info_set_debug_link(bin, filename, crc32);

end:
	return;
}
Example #26
0
static
void handle_statedump_build_id_event(FILE *err, struct debug_info *debug_info,
		struct bt_event *event)
{
	struct proc_debug_info_sources *proc_dbg_info_src;
	struct bin_info *bin = NULL;
	int ret;
	int64_t vpid;
	uint64_t baddr;
	uint64_t build_id_len;

	ret = get_stream_event_context_int_field_value(err,
			event, VPID_FIELD_NAME, &vpid);
	if (ret) {
		goto end;
	}

	ret = get_payload_unsigned_int_field_value(err,
			event, BADDR_FIELD_NAME, &baddr);
	if (ret) {
		BT_LOGE_STR("Failed to get unsigned int value for "
			VPID_FIELD_NAME " field.");
		goto end;
	}

	proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
			debug_info->vpid_to_proc_dbg_info_src, vpid);
	if (!proc_dbg_info_src) {
		goto end;
	}

	bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
			(gpointer) &baddr);
	if (!bin) {
		/*
		 * The build_id event comes after the bin has been
		 * created. If it isn't found, just ignore this event.
		 */
		goto end;
	}

	ret = get_payload_build_id_field_value(err, event, BUILD_ID_FIELD_NAME,
			&bin->build_id, &build_id_len);
	if (ret) {
		BT_LOGE_STR("Failed to get " BUILD_ID_FIELD_NAME
			" field value.");
		goto end;
	}
	if (build_id_len > SIZE_MAX) {
		bin->build_id_len = (size_t) build_id_len;
	}

	/*
	 * Reset the is_elf_only flag in case it had been set
	 * previously, because we might find separate debug info using
	 * the new build id information.
	 */
	bin->is_elf_only = false;

	// TODO
	//	bin_info_set_build_id(bin, build_id, build_id_len);

end:
	return;
}
Example #27
0
BT_HIDDEN
struct ctf_metadata_decoder *ctf_metadata_decoder_create(
		const struct ctf_metadata_decoder_config *config,
		const char *name)
{
	struct ctf_metadata_decoder *mdec =
		g_new0(struct ctf_metadata_decoder, 1);
	struct ctf_metadata_decoder_config default_config = {
		.clock_class_offset_s = 0,
		.clock_class_offset_ns = 0,
	};

	if (!config) {
		config = &default_config;
	}

	BT_LOGD("Creating CTF metadata decoder: "
		"clock-class-offset-s=%" PRId64 ", "
		"clock-class-offset-ns=%" PRId64 ", name=\"%s\"",
		config->clock_class_offset_s, config->clock_class_offset_ns,
		name);

	if (!mdec) {
		BT_LOGE_STR("Failed to allocate one CTF metadata decoder.");
		goto end;
	}

	mdec->config = *config;
	mdec->visitor = ctf_visitor_generate_ir_create(config, name);
	if (!mdec->visitor) {
		BT_LOGE("Failed to create a CTF IR metadata AST visitor: "
			"mdec-addr=%p", mdec);
		ctf_metadata_decoder_destroy(mdec);
		mdec = NULL;
		goto end;
	}

	BT_LOGD("Creating CTF metadata decoder: "
		"clock-class-offset-s=%" PRId64 ", "
		"clock-class-offset-ns=%" PRId64 ", "
		"name=\"%s\", addr=%p",
		config->clock_class_offset_s, config->clock_class_offset_ns,
		name, mdec);

end:
	return mdec;
}

BT_HIDDEN
void ctf_metadata_decoder_destroy(struct ctf_metadata_decoder *mdec)
{
	if (!mdec) {
		return;
	}

	BT_LOGD("Destroying CTF metadata decoder: addr=%p", mdec);
	ctf_visitor_generate_ir_destroy(mdec->visitor);
	g_free(mdec);
}

BT_HIDDEN
enum ctf_metadata_decoder_status ctf_metadata_decoder_decode(
		struct ctf_metadata_decoder *mdec, FILE *fp)
{
	enum ctf_metadata_decoder_status status =
		CTF_METADATA_DECODER_STATUS_OK;
	int ret;
	struct ctf_scanner *scanner = NULL;
	char *buf = NULL;
	bool close_fp = false;

	assert(mdec);

	if (ctf_metadata_decoder_is_packetized(fp, &mdec->bo)) {
		BT_LOGD("Metadata stream is packetized: mdec-addr=%p", mdec);
		ret = ctf_metadata_decoder_packetized_file_stream_to_buf_with_mdec(
			mdec, fp, &buf, mdec->bo);
		if (ret) {
			BT_LOGE("Cannot decode packetized metadata packets to metadata text: "
				"mdec-addr=%p, ret=%d", mdec, ret);
			status = CTF_METADATA_DECODER_STATUS_ERROR;
			goto end;
		}

		if (strlen(buf) == 0) {
			/* An empty metadata packet is OK. */
			goto end;
		}

		/* Convert the real file pointer to a memory file pointer */
		fp = bt_fmemopen(buf, strlen(buf), "rb");
		close_fp = true;
		if (!fp) {
			BT_LOGE("Cannot memory-open metadata buffer: %s: "
				"mdec-addr=%p", strerror(errno), mdec);
			status = CTF_METADATA_DECODER_STATUS_ERROR;
			goto end;
		}
	} else {
		unsigned int major, minor;
		ssize_t nr_items;
		const long init_pos = ftell(fp);

		BT_LOGD("Metadata stream is plain text: mdec-addr=%p", mdec);

		if (init_pos < 0) {
			BT_LOGE_ERRNO("Failed to get current file position", ".");
			status = CTF_METADATA_DECODER_STATUS_ERROR;
			goto end;
		}

		/* Check text-only metadata header and version */
		nr_items = fscanf(fp, "/* CTF %10u.%10u", &major, &minor);
		if (nr_items < 2) {
			BT_LOGW("Missing \"/* CTF major.minor\" signature in plain text metadata file stream: "
				"mdec-addr=%p", mdec);
		}

		BT_LOGD("Found metadata stream version in signature: version=%u.%u", major, minor);

		if (!is_version_valid(major, minor)) {
			BT_LOGE("Invalid metadata version found in plain text signature: "
				"version=%u.%u, mdec-addr=%p", major, minor,
				mdec);
			status = CTF_METADATA_DECODER_STATUS_INVAL_VERSION;
			goto end;
		}

		if (fseek(fp, init_pos, SEEK_SET)) {
			BT_LOGE("Cannot seek metadata file stream to initial position: %s: "
				"mdec-addr=%p", strerror(errno), mdec);
			status = CTF_METADATA_DECODER_STATUS_ERROR;
			goto end;
		}
	}

	if (BT_LOG_ON_VERBOSE) {
		yydebug = 1;
	}

	/* Allocate a scanner and append the metadata text content */
	scanner = ctf_scanner_alloc();
	if (!scanner) {
		BT_LOGE("Cannot allocate a metadata lexical scanner: "
			"mdec-addr=%p", mdec);
		status = CTF_METADATA_DECODER_STATUS_ERROR;
		goto end;
	}

	assert(fp);
	ret = ctf_scanner_append_ast(scanner, fp);
	if (ret) {
		BT_LOGE("Cannot create the metadata AST out of the metadata text: "
			"mdec-addr=%p", mdec);
		status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
		goto end;
	}

	ret = ctf_visitor_semantic_check(0, &scanner->ast->root);
	if (ret) {
		BT_LOGE("Validation of the metadata semantics failed: "
			"mdec-addr=%p", mdec);
		status = CTF_METADATA_DECODER_STATUS_ERROR;
		goto end;
	}

	ret = ctf_visitor_generate_ir_visit_node(mdec->visitor,
		&scanner->ast->root);
	switch (ret) {
	case 0:
		/* Success */
		break;
	case -EINCOMPLETE:
		BT_LOGD("While visiting metadata AST: incomplete data: "
			"mdec-addr=%p", mdec);
		status = CTF_METADATA_DECODER_STATUS_INCOMPLETE;
		goto end;
	default:
		BT_LOGE("Failed to visit AST node to create CTF IR objects: "
			"mdec-addr=%p, ret=%d", mdec, ret);
		status = CTF_METADATA_DECODER_STATUS_IR_VISITOR_ERROR;
		goto end;
	}

end:
	if (scanner) {
		ctf_scanner_free(scanner);
	}

	yydebug = 0;

	if (fp && close_fp) {
		if (fclose(fp)) {
			BT_LOGE("Cannot close metadata file stream: "
				"mdec-addr=%p", mdec);
		}
	}

	if (buf) {
		free(buf);
	}

	return status;
}

BT_HIDDEN
struct bt_trace *ctf_metadata_decoder_get_trace(
		struct ctf_metadata_decoder *mdec)
{
	return ctf_visitor_generate_ir_get_trace(mdec->visitor);
}
Example #28
0
static
int add_ds_file_to_ds_file_group(struct ctf_fs_trace *ctf_fs_trace,
		const char *path)
{
	int64_t stream_instance_id = -1;
	int64_t begin_ns = -1;
	struct ctf_fs_ds_file_group *ds_file_group = NULL;
	bool add_group = false;
	int ret;
	size_t i;
	struct ctf_fs_ds_file *ds_file = NULL;
	struct ctf_fs_ds_index *index = NULL;
	struct bt_msg_iter *msg_iter = NULL;
	struct ctf_stream_class *sc = NULL;
	struct bt_msg_iter_packet_properties props;

	msg_iter = bt_msg_iter_create(ctf_fs_trace->metadata->tc,
		bt_common_get_page_size() * 8, ctf_fs_ds_file_medops, NULL);
	if (!msg_iter) {
		BT_LOGE_STR("Cannot create a CTF message iterator.");
		goto error;
	}

	ds_file = ctf_fs_ds_file_create(ctf_fs_trace, NULL, msg_iter,
		NULL, path);
	if (!ds_file) {
		goto error;
	}

	ret = bt_msg_iter_get_packet_properties(ds_file->msg_iter, &props);
	if (ret) {
		BT_LOGE("Cannot get stream file's first packet's header and context fields (`%s`).",
			path);
		goto error;
	}

	sc = ctf_trace_class_borrow_stream_class_by_id(ds_file->metadata->tc,
		props.stream_class_id);
	BT_ASSERT(sc);
	stream_instance_id = props.data_stream_id;

	if (props.snapshots.beginning_clock != UINT64_C(-1)) {
		BT_ASSERT(sc->default_clock_class);
		ret = bt_util_clock_cycles_to_ns_from_origin(
			props.snapshots.beginning_clock,
			sc->default_clock_class->frequency,
			sc->default_clock_class->offset_seconds,
			sc->default_clock_class->offset_cycles, &begin_ns);
		if (ret) {
			BT_LOGE("Cannot convert clock cycles to nanoseconds from origin (`%s`).",
				path);
			goto error;
		}
	}

	index = ctf_fs_ds_file_build_index(ds_file);
	if (!index) {
		BT_LOGW("Failed to index CTF stream file \'%s\'",
			ds_file->file->path->str);
	}

	if (begin_ns == -1) {
		/*
		 * No beggining timestamp to sort the stream files
		 * within a stream file group, so consider that this
		 * file must be the only one within its group.
		 */
		stream_instance_id = -1;
	}

	if (stream_instance_id == -1) {
		/*
		 * No stream instance ID or no beginning timestamp:
		 * create a unique stream file group for this stream
		 * file because, even if there's a stream instance ID,
		 * there's no timestamp to order the file within its
		 * group.
		 */
		ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace,
			sc, UINT64_C(-1));
		if (!ds_file_group) {
			goto error;
		}

		ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group,
			path, begin_ns, index);
		/* Ownership of index is transferred. */
		index = NULL;
		if (ret) {
			goto error;
		}

		add_group = true;
		goto end;
	}

	BT_ASSERT(stream_instance_id != -1);
	BT_ASSERT(begin_ns != -1);

	/* Find an existing stream file group with this ID */
	for (i = 0; i < ctf_fs_trace->ds_file_groups->len; i++) {
		ds_file_group = g_ptr_array_index(
			ctf_fs_trace->ds_file_groups, i);

		if (ds_file_group->sc == sc &&
				ds_file_group->stream_id ==
				stream_instance_id) {
			break;
		}

		ds_file_group = NULL;
	}

	if (!ds_file_group) {
		ds_file_group = ctf_fs_ds_file_group_create(ctf_fs_trace,
			sc, stream_instance_id);
		if (!ds_file_group) {
			goto error;
		}

		add_group = true;
	}

	ret = ctf_fs_ds_file_group_add_ds_file_info(ds_file_group, path,
		begin_ns, index);
	index = NULL;
	if (ret) {
		goto error;
	}

	goto end;

error:
	ctf_fs_ds_file_group_destroy(ds_file_group);
	ds_file_group = NULL;
	ret = -1;

end:
	if (add_group && ds_file_group) {
		g_ptr_array_add(ctf_fs_trace->ds_file_groups, ds_file_group);
	}

	ctf_fs_ds_file_destroy(ds_file);

	if (msg_iter) {
		bt_msg_iter_destroy(msg_iter);
	}

	ctf_fs_ds_index_destroy(index);
	return ret;
}