Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0230b2b authored by David Ahern's avatar David Ahern Committed by Arnaldo Carvalho de Melo
Browse files

perf script: Add support for dumping symbols



Add option to dump symbols found in events.

e.g., perf script -f comm,pid,tid,time,trace,sym

swapper     0/0       537.037184: prev_comm=swapper prev_pid=0 prev_prio=120...
        ffffffff81030350 perf_trace_sched_switch ([kernel.kallsyms])
        ffffffff81382ac5 schedule ([kernel.kallsyms])
        ffffffff8100134a cpu_idle ([kernel.kallsyms])
        ffffffff81370b39 rest_init ([kernel.kallsyms])
        ffffffff81696c23 start_kernel ([kernel.kallsyms].init.text)
        ffffffff816962af x86_64_start_reservations ([kernel.kallsyms].init.text)
        ffffffff816963b9 x86_64_start_kernel ([kernel.kallsyms].init.text)

sshd  1675/1675    537.037309: prev_comm=sshd prev_pid=1675 prev_prio=120...
        ffffffff81030350 perf_trace_sched_switch ([kernel.kallsyms])
        ffffffff81382ac5 schedule ([kernel.kallsyms])
        ffffffff813837aa schedule_hrtimeout_range_clock ([kernel.kallsyms])
        ffffffff81383886 schedule_hrtimeout_range ([kernel.kallsyms])
        ffffffff8110c4f9 poll_schedule_timeout ([kernel.kallsyms])
        ffffffff8110cd20 do_select ([kernel.kallsyms])
        ffffffff8110ced8 core_sys_select ([kernel.kallsyms])
        ffffffff8110d00d sys_select ([kernel.kallsyms])
        ffffffff81002bc2 system_call ([kernel.kallsyms])
            7f1647e56e93 __GI_select (/lib64/libc-2.12.90.so)

netstat  1692/1692    537.038664: prev_comm=netstat prev_pid=1692 prev_prio=...
        ffffffff81030350 perf_trace_sched_switch ([kernel.kallsyms])
        ffffffff81382ac5 schedule ([kernel.kallsyms])
        ffffffff81002c3a sysret_careful ([kernel.kallsyms])
            7f7a6cd1b210 __GI___libc_read (/lib64/libc-2.12.90.so)

Acked-by: default avatarFrederic Weisbecker <fweisbec@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <1299734608-5223-6-git-send-email-daahern@cisco.com>
Signed-off-by: default avatarDavid Ahern <daahern@cisco.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 745f43e3
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -115,7 +115,21 @@ OPTIONS
-f::
--fields
        Comma separated list of fields to print. Options are:
        comm, tid, pid, time, cpu, event, trace
        comm, tid, pid, time, cpu, event, trace, sym

-k::
--vmlinux=<file>::
        vmlinux pathname

--kallsyms=<file>::
        kallsyms pathname

--symfs=<directory>::
        Look for files with symbols relative to this directory.

-G::
--hide-call-graph::
        When printing symbols do not display call chain.

SEE ALSO
--------
+30 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ static bool debug_mode;
static u64			last_timestamp;
static u64			nr_unordered;
extern const struct option	record_options[];
static bool			no_callchain;

enum perf_output_field {
	PERF_OUTPUT_COMM            = 1U << 0,
@@ -28,6 +29,7 @@ enum perf_output_field {
	PERF_OUTPUT_CPU             = 1U << 4,
	PERF_OUTPUT_EVNAME          = 1U << 5,
	PERF_OUTPUT_TRACE           = 1U << 6,
	PERF_OUTPUT_SYM             = 1U << 7,
};

struct output_option {
@@ -41,6 +43,7 @@ struct output_option {
	{.str = "cpu",   .field = PERF_OUTPUT_CPU},
	{.str = "event", .field = PERF_OUTPUT_EVNAME},
	{.str = "trace", .field = PERF_OUTPUT_TRACE},
	{.str = "sym",   .field = PERF_OUTPUT_SYM},
};

/* default set to maintain compatibility with current format */
@@ -65,6 +68,8 @@ static void print_sample_start(struct perf_sample *sample,
	if (PRINT_FIELD(COMM)) {
		if (latency_format)
			printf("%8.8s ", thread->comm);
		else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
			printf("%s ", thread->comm);
		else
			printf("%16s ", thread->comm);
	}
@@ -112,6 +117,14 @@ static void process_event(union perf_event *event __unused,
		print_trace_event(sample->cpu, sample->raw_data,
				  sample->raw_size);

	if (PRINT_FIELD(SYM)) {
		if (!symbol_conf.use_callchain)
			printf(" ");
		else
			printf("\n");
		perf_session__print_symbols(event, sample, session);
	}

	printf("\n");
}

@@ -190,7 +203,10 @@ static int process_sample_event(union perf_event *event,

static struct perf_event_ops event_ops = {
	.sample		 = process_sample_event,
	.mmap		 = perf_event__process_mmap,
	.comm		 = perf_event__process_comm,
	.exit		 = perf_event__process_task,
	.fork		 = perf_event__process_task,
	.attr		 = perf_event__process_attr,
	.event_type	 = perf_event__process_event_type,
	.tracing_data	 = perf_event__process_tracing_data,
@@ -722,8 +738,16 @@ static const struct option options[] = {
		    "input file name"),
	OPT_BOOLEAN('d', "debug-mode", &debug_mode,
		   "do various checks like samples ordering and lost events"),
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
	OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
		   "file", "kallsyms pathname"),
	OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
		    "When printing symbols do not display call chain"),
	OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
		    "Look for files with symbols relative to this directory"),
	OPT_CALLBACK('f', "fields", NULL, "str",
		     "comma separated output fields. Options: comm,tid,pid,time,cpu,event,trace",
		     "comma separated output fields. Options: comm,tid,pid,time,cpu,event,trace,sym",
		     parse_output_fields),

	OPT_END()
@@ -905,6 +929,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
	if (session == NULL)
		return -ENOMEM;

	if (!no_callchain && (session->sample_type & PERF_SAMPLE_CALLCHAIN))
		symbol_conf.use_callchain = true;
	else
		symbol_conf.use_callchain = false;

	if (strcmp(input_name, "-") &&
	    !perf_session__has_traces(session, "record -R"))
		return -EINVAL;
+61 −0
Original line number Diff line number Diff line
@@ -1134,3 +1134,64 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)

	return ret;
}

void perf_session__print_symbols(union perf_event *event,
				struct perf_sample *sample,
				struct perf_session *session)
{
	struct addr_location al;
	const char *symname, *dsoname;
	struct callchain_cursor *cursor = &session->callchain_cursor;
	struct callchain_cursor_node *node;

	if (perf_event__preprocess_sample(event, session, &al, sample,
					  NULL) < 0) {
		error("problem processing %d event, skipping it.\n",
			event->header.type);
		return;
	}

	if (symbol_conf.use_callchain && sample->callchain) {

		if (perf_session__resolve_callchain(session, al.thread,
						sample->callchain, NULL) != 0) {
			if (verbose)
				error("Failed to resolve callchain. Skipping\n");
			return;
		}
		callchain_cursor_commit(cursor);

		while (1) {
			node = callchain_cursor_current(cursor);
			if (!node)
				break;

			if (node->sym && node->sym->name)
				symname = node->sym->name;
			else
				symname = "";

			if (node->map && node->map->dso && node->map->dso->name)
				dsoname = node->map->dso->name;
			else
				dsoname = "";

			printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);

			callchain_cursor_advance(cursor);
		}

	} else {
		if (al.sym && al.sym->name)
			symname = al.sym->name;
		else
			symname = "";

		if (al.map && al.map->dso && al.map->dso->name)
			dsoname = al.map->dso->name;
		else
			dsoname = "";

		printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
	}
}
+4 −0
Original line number Diff line number Diff line
@@ -159,4 +159,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
					session->sample_id_all, sample);
}

void perf_session__print_symbols(union perf_event *event,
				 struct perf_sample *sample,
				 struct perf_session *session);

#endif /* __PERF_SESSION_H */