Example #1
0
static struct event_format *
update_event(struct pevent *pevent,
	     const char *sys, const char *name, int *id)
{
	struct event_format *event;

	event = pevent_find_event_by_name(pevent, sys, name);
	if (!event)
		return NULL;

	*id = event->id;

	return event;
}
Example #2
0
static int load_events(struct trace_capture *cap,
			   struct tracecmd_xml_handle *handle,
			   struct tracecmd_xml_system_node *node)
{
	struct shark_info *info = cap->info;
	struct tracecmd_xml_system_node *event_node;
	struct event_format *event;
	struct pevent *pevent = cap->pevent;
	const char *name;
	int *events = NULL;
	int event_len = 0;
	const char *system;
	const char *event_name;

	for (node = tracecmd_xml_node_child(node); node;
	     node = tracecmd_xml_node_next(node)) {
		name = tracecmd_xml_node_type(node);

		if (strcmp(name, "Event") != 0)
			continue;

		event_node = tracecmd_xml_node_child(node);
		if (!event_node)
			continue;

		name = tracecmd_xml_node_type(event_node);
		if (strcmp(name, "System") != 0)
			continue;
		system = tracecmd_xml_node_value(handle, event_node);

		event_node = tracecmd_xml_node_next(event_node);
		if (!event_node)
			continue;

		name = tracecmd_xml_node_type(event_node);
		if (strcmp(name, "Name") != 0)
			continue;
		event_name = tracecmd_xml_node_value(handle, event_node);

		event = pevent_find_event_by_name(pevent, system, event_name);

		if (!event)
			continue;

		events = tracecmd_add_id(events, event->id, event_len++);
	}

	info->cap_events = events;
	return 0;
}
/**
 * pevent_update_trivial - update the trivial filters with the given filter
 * @dest - the filter to update
 * @source - the filter as the source of the update
 * @type - the type of trivial filter to update.
 *
 * Scan dest for trivial events matching @type to replace with the source.
 *
 * Returns 0 on success and -1 if there was a problem updating, but
 *   events may have still been updated on error.
 */
int pevent_update_trivial(struct event_filter *dest, struct event_filter *source,
			  enum filter_trivial_type type)
{
	struct pevent *src_pevent;
	struct pevent *dest_pevent;
	struct event_format *event;
	struct filter_type *filter_type;
	struct filter_arg *arg;
	char *str;
	int i;

	src_pevent = source->pevent;
	dest_pevent = dest->pevent;

	/* Do nothing if either of the filters has nothing to filter */
	if (!dest->filters || !source->filters)
		return 0;

	for (i = 0; i < dest->filters; i++) {
		filter_type = &dest->event_filters[i];
		arg = filter_type->filter;
		if (arg->type != FILTER_ARG_BOOLEAN)
			continue;
		if ((arg->boolean.value && type == FILTER_TRIVIAL_FALSE) ||
		    (!arg->boolean.value && type == FILTER_TRIVIAL_TRUE))
			continue;

		event = filter_type->event;

		if (src_pevent != dest_pevent) {
			/* do a look up */
			event = pevent_find_event_by_name(src_pevent,
							  event->system,
							  event->name);
			if (!event)
				return -1;
		}

		str = pevent_filter_make_string(source, event->id);
		if (!str)
			continue;

		/* Don't bother if the filter is trivial too */
		if (strcmp(str, "TRUE") != 0 && strcmp(str, "FALSE") != 0)
			filter_event(dest, event, str, NULL);
		free(str);
	}
	return 0;
}
static int copy_filter_type(struct event_filter *filter,
			     struct event_filter *source,
			     struct filter_type *filter_type)
{
	struct filter_arg *arg;
	struct event_format *event;
	const char *sys;
	const char *name;
	char *str;

	/* Can't assume that the pevent's are the same */
	sys = filter_type->event->system;
	name = filter_type->event->name;
	event = pevent_find_event_by_name(filter->pevent, sys, name);
	if (!event)
		return -1;

	str = arg_to_str(source, filter_type->filter);
	if (!str)
		return -1;

	if (strcmp(str, "TRUE") == 0 || strcmp(str, "FALSE") == 0) {
		/* Add trivial event */
		arg = allocate_arg();
		arg->type = FILTER_ARG_BOOLEAN;
		if (strcmp(str, "TRUE") == 0)
			arg->boolean.value = 1;
		else
			arg->boolean.value = 0;

		filter_type = add_filter_type(filter, event->id);
		filter_type->filter = arg;

		free(str);
		return 0;
	}

	filter_event(filter, event, str, NULL);
	free(str);

	return 0;
}
Example #5
0
int tracecmd_blk_hack(struct tracecmd_input *handle)
{
	struct pevent *pevent;
	struct event_format *event;
	struct format_field *field;
	char buf[4096]; /* way more than enough! */
	int id;
	int l;
	int r;

	pevent = tracecmd_get_pevent(handle);

	/*
	 * Unfortunately, the TRACE_BLK has changed a bit.
	 * We need to test if various events exist to try
	 * to guess what event id TRACE_BLK would be.
	 */

	/* It was originally behind the "power" event */
	event = pevent_find_event_by_name(pevent, "ftrace", "power");
	if (event) {
		id = event->id + 1;
		goto found;
	}

	/*
	 * But the power tracer is now in perf.
	 * Then it was after kmem_free
	 */
	event = pevent_find_event_by_name(pevent, "ftrace", "kmem_free");
	if (event) {
		id = event->id + 1;
		goto found;
	}

	/*
	 * But that then went away.
	 * Currently it should be behind the user stack.
	 */
	event = pevent_find_event_by_name(pevent, "ftrace", "user_stack");
	if (event) {
		id = event->id + 1;
		goto found;
	}
	/* Give up :( */
	return -1;

 found:
	/*
	 * Blk events are not exported in the events directory.
	 * This is a hack to attempt to create a block event
	 * that we can read.
	 *
	 * We'll make a format file to look like this:
	 *
	 * name: blktrace
	 * ID: 13
	 * format:
	 *	field:unsigned short common_type;	offset:0;	size:2;
	 *	field:unsigned char common_flags;	offset:2;	size:1;
	 *	field:unsigned char common_preempt_count;	offset:3;	size:1;
	 *	field:int common_pid;	offset:4;	size:4;
	 *	field:int common_lock_depth;	offset:8;	size:4;
	 *
	 *	field:u64 sector;	offset:16;	size:8;
	 *	field:int bytes;	offset:32;	size:4;
	 *	field:int action;	offset:36;	size:4;
	 *	field:int pid;	offset:40;	size:4;
	 *	field:int device;	offset:44;	size:4;
	 *	field:int cpu;	offset:48;	size:4;
	 *	field:short error;	offset:52;	size:2;
	 *	field:short pdu_len;	offset:54;	size:2;
	 *	field:void data;	offset:60;	size:0;
	 *
	 * print fmt: "%d", REC->pid
	 *
	 * Note: the struct blk_io_trace is used directly and
	 * just the first parts of the struct are not used in order
	 * to not write over the ftrace data.
	 */

	/* Make sure the common fields exist */
	field = pevent_find_common_field(event, "common_type");
	if (!field || field->offset != 0 || field->size != 2)
		goto fail;
	field = pevent_find_common_field(event, "common_flags");
	if (!field || field->offset != 2 || field->size != 1)
		goto fail;
	field = pevent_find_common_field(event, "common_preempt_count");
	if (!field || field->offset != 3 || field->size != 1)
		goto fail;
	field = pevent_find_common_field(event, "common_pid");
	if (!field || field->offset != 4 || field->size != 4)
		goto fail;
	r = sprintf(buf, blk_event_start, id);
	l = r;

	/* lock depth is optional */
	field = pevent_find_common_field(event, "common_lock_depth");
	if (field) {
		if (field->offset != 8 || field->size != 4)
			return -1;
		r = sprintf(buf+l, "\tfield:int common_lock_depth;\toffset:8;\tsize:4;\n");
		l += r;
	}

	r = sprintf(buf+l, blk_body);

	/* Parse this event */
	l += r;
	pevent_parse_event(pevent, buf, l, "ftrace");

	return 0;

 fail:
	return -1;
}
Example #6
0
static void update_filter_tasks(TraceViewStore *store)
{
	struct tracecmd_input *handle;
	struct pevent *pevent;
	struct record *record;
	gint pid;
	gint cpu;
	gint i;

	handle = store->handle;
	pevent = tracecmd_get_pevent(store->handle);

	if (!store->sched_switch_event) {
		store->sched_switch_event =
			pevent_find_event_by_name(pevent, "sched", "sched_switch");
		if (store->sched_switch_event)
			store->sched_switch_next_field =
				pevent_find_any_field(store->sched_switch_event,
						      "next_pid");
		store->sched_wakeup_event =
			pevent_find_event_by_name(pevent, "sched", "sched_wakeup");
		if (store->sched_wakeup_event)
			store->sched_wakeup_pid_field =
				pevent_find_any_field(store->sched_wakeup_event,
						      "pid");

		store->sched_wakeup_new_event =
			pevent_find_event_by_name(pevent, "sched", "sched_wakeup");
		if (store->sched_wakeup_new_event)
			store->sched_wakeup_new_pid_field =
				pevent_find_any_field(store->sched_wakeup_new_event,
						      "pid");
	}

	for (cpu = 0; cpu < store->cpus; cpu++) {
		record = tracecmd_read_cpu_first(handle, cpu);

		for (i = 0; i < store->cpu_items[cpu]; i++) {

			g_assert(record->offset == store->cpu_list[cpu][i].offset);

			/* The record may be filtered by the events */
			if (!store->all_events) {
				int ret;
				ret = pevent_filter_match(store->event_filter,
							  record);
				if (ret != FILTER_MATCH) {
					store->cpu_list[cpu][i].visible = 0;
					goto skip;
				}
			}

			pid = pevent_data_pid(pevent, record);
			if (show_task(store, pevent, record, pid))
				store->cpu_list[cpu][i].visible = 1;
			else
				store->cpu_list[cpu][i].visible = 0;

 skip:
			free_record(record);
			record = tracecmd_read_data(handle, cpu);
		}
		g_assert(record == NULL);
	}

	merge_sort_rows_ts(store);
}