Пример #1
0
static void
process_function(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long parent_ip;
	unsigned long long ip;
	unsigned long long val;
	const char *parent;
	const char *func;
	int pid;
	int ret;

	ret = pevent_read_number_field(common_pid_field, record->data, &val);
	if (ret < 0)
		die("no pid field for function?");

	ret = pevent_read_number_field(function_ip_field, record->data, &ip);
	if (ret < 0)
		die("no ip field for function?");

	ret = pevent_read_number_field(function_parent_ip_field, record->data, &parent_ip);
	if (ret < 0)
		die("no parent ip field for function?");

	pid = val;

	func = pevent_find_function(pevent, ip);
	parent = pevent_find_function(pevent, parent_ip);

	if (current_pid >= 0 && pid != current_pid) {
		save_stack();
		restore_stack(pid);
	}

	current_pid = pid;

	if (ips_idx) {
		if (ips[ips_idx - 1] == parent)
			push_stack_func(func);
		else {
			save_call_chain(pid, ips, ips_idx, 0);
			while (ips_idx) {
				pop_stack_func();
				if (ips[ips_idx - 1] == parent) {
					push_stack_func(func);
					break;
				}
			}
		}
	}

	/* The above check can set ips_idx to zero again */
	if (!ips_idx) {
		push_stack_func(parent);
		push_stack_func(func);
	}
}
Пример #2
0
static void
process_kmalloc(struct pevent *pevent, struct pevent_record *record,
		struct format_field *callsite_field,
		struct format_field *bytes_req_field,
		struct format_field *bytes_alloc_field,
		struct format_field *ptr_field)
{
	unsigned long long callsite;
	unsigned long long val;
	unsigned long long ptr;
	unsigned int req;
	int alloc;
	const char *func;

	pevent_read_number_field(callsite_field, record->data, &callsite);
	pevent_read_number_field(bytes_req_field, record->data, &val);
	req = val;
	pevent_read_number_field(bytes_alloc_field, record->data, &val);
	alloc = val;
	pevent_read_number_field(ptr_field, record->data, &ptr);

	func = pevent_find_function(pevent, callsite);

	add_kmalloc(func, ptr, req, alloc);
}
Пример #3
0
static int function_handler(struct trace_seq *s, struct pevent_record *record,
			    struct event_format *event, void *context)
{
	struct pevent *pevent = event->pevent;
	unsigned long long function;
	unsigned long long pfunction;
	const char *func;
	const char *parent;
	int index;

	if (pevent_get_field_val(s, event, "ip", record, &function, 1))
		return trace_seq_putc(s, '!');

	func = pevent_find_function(pevent, function);

	if (pevent_get_field_val(s, event, "parent_ip", record, &pfunction, 1))
		return trace_seq_putc(s, '!');

	parent = pevent_find_function(pevent, pfunction);

	index = add_and_get_index(parent, func, record->cpu);

	trace_seq_printf(s, "%*s", index*3, "");

	if (func)
		trace_seq_printf(s, "%s", func);
	else
		trace_seq_printf(s, "0x%llx", function);

	trace_seq_printf(s, " <-- ");
	if (parent)
		trace_seq_printf(s, "%s", parent);
	else
		trace_seq_printf(s, "0x%llx", pfunction);

	return 0;
}
Пример #4
0
static void
process_function_graph_entry(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long depth;
	unsigned long long ip;
	unsigned long long val;
	const char *func;
	int pid;
	int ret;

	ret = pevent_read_number_field(common_pid_field, record->data, &val);
	if (ret < 0)
		die("no pid field for function graph entry?");

	ret = pevent_read_number_field(function_graph_entry_func_field,
				       record->data, &ip);
	if (ret < 0)
		die("no ip field for function graph entry?");

	ret = pevent_read_number_field(function_graph_entry_depth_field,
				       record->data, &depth);
	if (ret < 0)
		die("no parent ip field for function entry?");

	pid = val;

	func = pevent_find_function(pevent, ip);

	if (current_pid >= 0 && pid != current_pid) {
		save_stack();
		restore_stack(pid);
	}

	current_pid = pid;

	if (depth != ips_idx) {
		save_call_chain(pid, ips, ips_idx, 0);
		while (ips_idx > depth)
			pop_stack_func();
	}

	func_depth = depth;

	push_stack_func(func);
}
static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
{
	struct event_format *event;
	struct pevent *pevent;
	unsigned long long addr;
	const char *val = NULL;
	char hex[64];

	/* If the field is not a string convert it */
	if (arg->str.field->flags & FIELD_IS_STRING) {
		val = record->data + arg->str.field->offset;

		/*
		 * We need to copy the data since we can't be sure the field
		 * is null terminated.
		 */
		if (*(val + arg->str.field->size - 1)) {
			/* copy it */
			memcpy(arg->str.buffer, val, arg->str.field->size);
			/* the buffer is already NULL terminated */
			val = arg->str.buffer;
		}

	} else {
		event = arg->str.field->event;
		pevent = event->pevent;
		addr = get_value(event, arg->str.field, record);

		if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
			/* convert to a kernel symbol */
			val = pevent_find_function(pevent, addr);

		if (val == NULL) {
			/* just use the hex of the string name */
			snprintf(hex, 64, "0x%llx", addr);
			val = hex;
		}
	}

	return val;
}
Пример #6
0
static void
process_kernel_stack(struct pevent *pevent, struct pevent_record *record)
{
	struct format_field *field = kernel_stack_caller_field;
	unsigned long long val;
	void *data = record->data;
	int do_restore = 0;
	int pid;
	int ret;

	ret = pevent_read_number_field(common_pid_field, record->data, &val);
	if (ret < 0)
		die("no pid field for function?");
	pid = val;

	if (pending_pid >= 0 && pid != pending_pid) {
		reset_pending_stack();
		return;
	}

	if (!field)
		die("no caller field for kernel stack?");

	if (pending_pid >= 0) {
		if (current_pid >= 0) {
			save_stack();
			do_restore = 1;
		}
	} else {
		/* function stack trace? */
		if (current_pid >= 0) {
			copy_stack_to_pending(current_pid);
			free(ips);
			reset_stack();
		}
	}

	current_pid = pid;

	/* Need to start at the end of the callers and work up */
	for (data += field->offset; data < record->data + record->size;
	     data += long_size) {
		unsigned long long addr;

		addr = pevent_read_number(pevent, data, long_size);

		if ((long_size == 8 && addr == (unsigned long long)-1) ||
		    ((int)addr == -1))
			break;
	}

	for (data -= long_size; data >= record->data + field->offset; data -= long_size) {
		unsigned long long addr;
		const char *func;

		addr = pevent_read_number(pevent, data, long_size);
		func = pevent_find_function(pevent, addr);
		if (func)
			push_stack_func(func);
	}

	if (pending_pid >= 0) {
		push_stack_func(pending_ips[pending_ips_idx - 1]);
		reset_pending_stack();
	}
	save_call_chain(current_pid, ips, ips_idx, 1);
	if (do_restore)
		restore_stack(current_pid);
}