Exemple #1
0
void bt_event_destroy(struct bt_object *obj)
{
	struct bt_event *event;

	event = container_of(obj, struct bt_event, base);
	BT_LOGD("Destroying event: 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->event_class));

	if (!event->base.parent) {
		/*
		 * Event was keeping a reference to its class since it shared no
		 * common ancestor with it to guarantee they would both have the
		 * same lifetime.
		 */
		bt_put(event->event_class);
	}
	g_hash_table_destroy(event->clock_values);
	BT_LOGD_STR("Putting event's header field.");
	bt_put(event->event_header);
	BT_LOGD_STR("Putting event's stream event context field.");
	bt_put(event->stream_event_context);
	BT_LOGD_STR("Putting event's context field.");
	bt_put(event->context_payload);
	BT_LOGD_STR("Putting event's payload field.");
	bt_put(event->fields_payload);
	BT_LOGD_STR("Putting event's packet.");
	bt_put(event->packet);
	g_free(event);
}
Exemple #2
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;
}
Exemple #3
0
BT_HIDDEN
bool ctf_metadata_decoder_is_packetized(FILE *fp, int *byte_order)
{
	uint32_t magic;
	size_t len;
	int ret = 0;

	len = fread(&magic, sizeof(magic), 1, fp);
	if (len != 1) {
		BT_LOGD_STR("Cannot reade first metadata packet header: assuming the stream is not packetized.");
		goto end;
	}

	if (byte_order) {
		if (magic == TSDL_MAGIC) {
			ret = 1;
			*byte_order = BYTE_ORDER;
		} else if (magic == GUINT32_SWAP_LE_BE(TSDL_MAGIC)) {
			ret = 1;
			*byte_order = BYTE_ORDER == BIG_ENDIAN ?
				LITTLE_ENDIAN : BIG_ENDIAN;
		}
	}

end:
	rewind(fp);

	return ret;
}
Exemple #4
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;
}
Exemple #5
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;
}
Exemple #6
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;
}
Exemple #7
0
BT_HIDDEN
void bt_ctf_event_class_common_freeze(struct bt_ctf_event_class_common *event_class)
{
	BT_ASSERT(event_class);

	if (event_class->frozen) {
		return;
	}

	BT_LOGD("Freezing event class: addr=%p, name=\"%s\", id=%" PRId64,
		event_class, bt_ctf_event_class_common_get_name(event_class),
		bt_ctf_event_class_common_get_id(event_class));
	event_class->frozen = 1;
	BT_LOGD_STR("Freezing event class's context field type.");
	bt_ctf_field_type_common_freeze(event_class->context_field_type);
	BT_LOGD_STR("Freezing event class's payload field type.");
	bt_ctf_field_type_common_freeze(event_class->payload_field_type);
}
Exemple #8
0
BT_HIDDEN
void bt_ctf_event_class_common_finalize(struct bt_ctf_object *obj)
{
	struct bt_ctf_event_class_common *event_class;

	event_class = container_of(obj, struct bt_ctf_event_class_common, base);
	BT_LOGD("Finalizing common event class: addr=%p, name=\"%s\", id=%" PRId64,
		event_class, bt_ctf_event_class_common_get_name(event_class),
		bt_ctf_event_class_common_get_id(event_class));

	if (event_class->name) {
		g_string_free(event_class->name, TRUE);
	}

	if (event_class->emf_uri) {
		g_string_free(event_class->emf_uri, TRUE);
	}

	BT_LOGD_STR("Putting context field type.");
	bt_ctf_object_put_ref(event_class->context_field_type);
	BT_LOGD_STR("Putting payload field type.");
	bt_ctf_object_put_ref(event_class->payload_field_type);
}
Exemple #9
0
BT_HIDDEN
void bt_event_freeze(struct bt_event *event)
{
	assert(event);

	if (event->frozen) {
		return;
	}

	BT_LOGD("Freezing event: 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->event_class));
	bt_packet_freeze(event->packet);
	BT_LOGD_STR("Freezing event's header field.");
	bt_field_freeze(event->event_header);
	BT_LOGD_STR("Freezing event's stream event context field.");
	bt_field_freeze(event->stream_event_context);
	BT_LOGD_STR("Freezing event's context field.");
	bt_field_freeze(event->context_payload);
	BT_LOGD_STR("Freezing event's payload field.");
	bt_field_freeze(event->fields_payload);
	event->frozen = 1;
}
Exemple #10
0
BT_HIDDEN
int bin_info_lookup_function_name(struct bin_info *bin,
		uint64_t addr, char **func_name)
{
	int ret = 0;
	char *_func_name = NULL;

	if (!bin || !func_name) {
		goto error;
	}

	/* Set DWARF info if it hasn't been accessed yet. */
	if (!bin->dwarf_info && !bin->is_elf_only) {
		ret = bin_info_set_dwarf_info(bin);
		if (ret) {
			BT_LOGD_STR("Failed to set bin dwarf info, falling back to ELF lookup.");
			/* Failed to set DWARF info, fallback to ELF. */
			bin->is_elf_only = true;
		}
	}

	if (!bin_info_has_address(bin, addr)) {
		goto error;
	}

	/*
	 * Addresses in ELF and DWARF are relative to base address for
	 * PIC, so make the address argument relative too if needed.
	 */
	if (bin->is_pic) {
		addr -= bin->low_addr;
	}

	if (bin->is_elf_only) {
		ret = bin_info_lookup_elf_function_name(bin, addr, &_func_name);
		BT_LOGD("Failed to lookup function name (ELF): ret=%d", ret);
	} else {
		ret = bin_info_lookup_dwarf_function_name(bin, addr, &_func_name);
		BT_LOGD("Failed to lookup function name (DWARF): ret=%d", ret);
	}

	*func_name = _func_name;
	return 0;

error:
	return -1;
}
Exemple #11
0
static
void bt_value_destroy(struct bt_object *obj)
{
	struct bt_value *value;

	value = container_of(obj, struct bt_value, base);
	BT_LOGD("Destroying value: addr=%p", value);

	if (bt_value_is_null(value)) {
		BT_LOGD_STR("Not destroying the null value singleton.");
		return;
	}

	if (destroy_funcs[value->type]) {
		destroy_funcs[value->type](value);
	}

	g_free(value);
}
Exemple #12
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;
}
Exemple #14
0
BT_HIDDEN
int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
		struct metadata_context *context)
{
	int ret = 0;
	struct bt_ctf_value *attr_value = NULL;

	BT_ASSERT(event_class);
	BT_ASSERT(context);
	BT_LOGD("Serializing event class's metadata: "
		"event-class-addr=%p, event-class-name=\"%s\", "
		"event-class-id=%" PRId64 ", metadata-context-addr=%p",
		event_class, bt_ctf_event_class_get_name(event_class),
		bt_ctf_event_class_get_id(event_class), context);
	context->current_indentation_level = 1;
	g_string_assign(context->field_name, "");
	g_string_append(context->string, "event {\n");

	/* Serialize attributes */
	g_string_append_printf(context->string, "\tname = \"%s\";\n",
		event_class->common.name->str);
	BT_ASSERT(event_class->common.id >= 0);
	g_string_append_printf(context->string, "\tid = %" PRId64 ";\n",
		event_class->common.id);
	g_string_append_printf(context->string, "\tstream_id = %" PRId64 ";\n",
		bt_ctf_stream_class_common_get_id(
			bt_ctf_event_class_common_borrow_stream_class(
				BT_CTF_TO_COMMON(event_class))));

	if (event_class->common.log_level !=
			BT_CTF_EVENT_CLASS_LOG_LEVEL_UNSPECIFIED) {
		g_string_append_printf(context->string, "\tloglevel = %d;\n",
			(int) event_class->common.log_level);
	}

	if (event_class->common.emf_uri->len > 0) {
		g_string_append_printf(context->string, "\tmodel.emf.uri = \"%s\";\n",
			event_class->common.emf_uri->str);
	}

	/* Serialize context field type */
	if (event_class->common.context_field_type) {
		g_string_append(context->string, "\tcontext := ");
		BT_LOGD_STR("Serializing event class's context field type metadata.");
		ret = bt_ctf_field_type_serialize_recursive(
			(void *) event_class->common.context_field_type,
			context);
		if (ret) {
			BT_LOGW("Cannot serialize event class's context field type's metadata: "
				"ret=%d", ret);
			goto end;
		}
		g_string_append(context->string, ";\n");
	}

	/* Serialize payload field type */
	if (event_class->common.payload_field_type) {
		g_string_append(context->string, "\tfields := ");
		BT_LOGD_STR("Serializing event class's payload field type metadata.");
		ret = bt_ctf_field_type_serialize_recursive(
			(void *) event_class->common.payload_field_type,
			context);
		if (ret) {
			BT_LOGW("Cannot serialize event class's payload field type's metadata: "
				"ret=%d", ret);
			goto end;
		}
		g_string_append(context->string, ";\n");
	}

	g_string_append(context->string, "};\n\n");

end:
	context->current_indentation_level = 0;
	BT_CTF_OBJECT_PUT_REF_AND_RESET(attr_value);
	return ret;
}