Пример #1
0
static void
process_function_graph_exit(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long depth;
	unsigned long long val;
	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 exit?");

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

	pid = val;

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

	current_pid = pid;

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

	func_depth = depth - 1;
}
Пример #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 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);
	}
}
static unsigned long long
get_value(struct event_format *event,
	  struct format_field *field, struct pevent_record *record)
{
	unsigned long long val;

	/* Handle our dummy "comm" field */
	if (field == &comm) {
		const char *name;

		name = get_comm(event, record);
		return (unsigned long)name;
	}

	pevent_read_number_field(field, record->data, &val);

	if (!(field->flags & FIELD_IS_SIGNED))
		return val;

	switch (field->size) {
	case 1:
		return (char)val;
	case 2:
		return (short)val;
	case 4:
		return (int)val;
	case 8:
		return (long long)val;
	}
	return val;
}
Пример #5
0
static void
process_record(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long val;
	int type;

	pevent_read_number_field(common_type_field, record->data, &val);
	type = val;

	if (type == function_type)
		return process_function(pevent, record);

	if (type == function_graph_entry_type)
		return process_function_graph_entry(pevent, record);

	if (type == function_graph_exit_type)
		return process_function_graph_exit(pevent, record);

	if (type == kernel_stack_type)
		return process_kernel_stack(pevent, record);

	if (type == sched_wakeup_type || type == sched_wakeup_new_type)
		process_sched_wakeup(pevent, record, type);

	else if (type == sched_switch_type)
		process_sched_switch(pevent, record);

	process_event(pevent, record, type);
}
Пример #6
0
static void
process_event(struct pevent *pevent, struct pevent_record *record, int type)
{
	struct event_format *event;
	const char *event_name;
	unsigned long long val;
	int pid;
	int ret;

	if (pending_pid >= 0) {
		save_call_chain(pending_pid, pending_ips, pending_ips_idx, 1);
		reset_pending_stack();
	}
		
	event = pevent_data_event_from_type(pevent, type);
	event_name = event->name;

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

	pid = val;

	/*
	 * Even if function or function graph tracer is running,
	 * if the user ran with stack traces on events, we want to use
	 * that instead. But unfortunately, that stack doesn't come
	 * until after the event. Thus, we only add the event into
	 * the pending stack.
	 */
	push_stack_func(event_name);
	copy_stack_to_pending(pid);
	pop_stack_func();
}
Пример #7
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);
}
Пример #8
0
gint get_wakeup_new_pid(TraceViewStore *store, struct pevent *pevent, struct record *record)
{
	unsigned long long val;
	int ret;

	ret = pevent_read_number_field(store->sched_wakeup_new_pid_field, record->data, &val);

	return val;
}
Пример #9
0
static void
process_kfree(struct pevent *pevent, struct pevent_record *record,
	      struct format_field *ptr_field)
{
	unsigned long long ptr;

	pevent_read_number_field(ptr_field, record->data, &ptr);

	remove_kmalloc(ptr);
}
Пример #10
0
static void
process_sched_switch(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long val;
	const char *comm;
	int pid;
	int ret;

	comm = (char *)(record->data + sched_switch_prev_field->offset);
	ret = pevent_read_number_field(sched_switch_prev_pid_field, record->data, &val);
	if (ret < 0)
		die("no prev_pid field in sched_switch?");
	pid = val;
	pevent_register_comm(pevent, comm, pid);

	comm = (char *)(record->data + sched_switch_next_field->offset);
	ret = pevent_read_number_field(sched_switch_next_pid_field, record->data, &val);
	if (ret < 0)
		die("no next_pid field in sched_switch?");
	pid = val;
	pevent_register_comm(pevent, comm, pid);
}
Пример #11
0
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data)
{
	struct format_field *field;
	unsigned long long val;

	field = pevent_find_any_field(event, name);
	if (!field)
		return 0ULL;

	pevent_read_number_field(field, data, &val);

	return val;
}
Пример #12
0
static void
process_sched_wakeup(struct pevent *pevent, struct pevent_record *record, int type)
{
	unsigned long long val;
	const char *comm;
	int pid;
	int ret;

	if (type == sched_wakeup_type) {
		comm = (char *)(record->data + sched_wakeup_comm_field->offset);
		ret = pevent_read_number_field(sched_wakeup_pid_field, record->data, &val);
		if (ret < 0)
			die("no pid field in sched_wakeup?");
	} else {
		comm = (char *)(record->data + sched_wakeup_new_comm_field->offset);
		ret = pevent_read_number_field(sched_wakeup_new_pid_field, record->data, &val);
		if (ret < 0)
			die("no pid field in sched_wakeup_new?");
	}

	pid = val;

	pevent_register_comm(pevent, comm, pid);
}
Пример #13
0
static void
process_record(struct pevent *pevent, struct pevent_record *record)
{
	unsigned long long val;
	int type;

	pevent_read_number_field(common_type_field, record->data, &val);
	type = val;

	if (type == kmalloc_type)
		return process_kmalloc(pevent, record,
				       kmalloc_callsite_field,
				       kmalloc_bytes_req_field,
				       kmalloc_bytes_alloc_field,
				       kmalloc_ptr_field);
	if (type == kmalloc_node_type)
		return process_kmalloc(pevent, record,
				       kmalloc_node_callsite_field,
				       kmalloc_node_bytes_req_field,
				       kmalloc_node_bytes_alloc_field,
				       kmalloc_node_ptr_field);
	if (type == kfree_type)
		return process_kfree(pevent, record, kfree_ptr_field);

	if (type == kmem_cache_alloc_type)
		return process_kmalloc(pevent, record,
				       kmem_cache_callsite_field,
				       kmem_cache_bytes_req_field,
				       kmem_cache_bytes_alloc_field,
				       kmem_cache_ptr_field);
	if (type == kmem_cache_alloc_node_type)
		return process_kmalloc(pevent, record,
				       kmem_cache_node_callsite_field,
				       kmem_cache_node_bytes_req_field,
				       kmem_cache_node_bytes_alloc_field,
				       kmem_cache_node_ptr_field);
	if (type == kmem_cache_free_type)
		return process_kfree(pevent, record, kmem_cache_free_ptr_field);
}
Пример #14
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);
}