aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <daahern@cisco.com>2011-03-10 00:23:27 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-03-14 16:06:50 -0400
commitc0230b2bfbd16e42d937c34aed99e5d6493eb5e4 (patch)
tree352cbe720b4b0bbe65c302c4a3977e21ba722a78
parent745f43e3433a7939bd9c351c8106e0c1db2044c6 (diff)
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: Frederic 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: David Ahern <daahern@cisco.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-script.txt16
-rw-r--r--tools/perf/builtin-script.c31
-rw-r--r--tools/perf/util/session.c61
-rw-r--r--tools/perf/util/session.h4
4 files changed, 110 insertions, 2 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index b73cf589c109..c64118a4de49 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,7 +115,21 @@ OPTIONS
115-f:: 115-f::
116--fields 116--fields
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace 118 comm, tid, pid, time, cpu, event, trace, sym
119
120-k::
121--vmlinux=<file>::
122 vmlinux pathname
123
124--kallsyms=<file>::
125 kallsyms pathname
126
127--symfs=<directory>::
128 Look for files with symbols relative to this directory.
129
130-G::
131--hide-call-graph::
132 When printing symbols do not display call chain.
119 133
120SEE ALSO 134SEE ALSO
121-------- 135--------
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index c046e6e8600a..b45b09c13f7a 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -19,6 +19,7 @@ static bool debug_mode;
19static u64 last_timestamp; 19static u64 last_timestamp;
20static u64 nr_unordered; 20static u64 nr_unordered;
21extern const struct option record_options[]; 21extern const struct option record_options[];
22static bool no_callchain;
22 23
23enum perf_output_field { 24enum perf_output_field {
24 PERF_OUTPUT_COMM = 1U << 0, 25 PERF_OUTPUT_COMM = 1U << 0,
@@ -28,6 +29,7 @@ enum perf_output_field {
28 PERF_OUTPUT_CPU = 1U << 4, 29 PERF_OUTPUT_CPU = 1U << 4,
29 PERF_OUTPUT_EVNAME = 1U << 5, 30 PERF_OUTPUT_EVNAME = 1U << 5,
30 PERF_OUTPUT_TRACE = 1U << 6, 31 PERF_OUTPUT_TRACE = 1U << 6,
32 PERF_OUTPUT_SYM = 1U << 7,
31}; 33};
32 34
33struct output_option { 35struct output_option {
@@ -41,6 +43,7 @@ struct output_option {
41 {.str = "cpu", .field = PERF_OUTPUT_CPU}, 43 {.str = "cpu", .field = PERF_OUTPUT_CPU},
42 {.str = "event", .field = PERF_OUTPUT_EVNAME}, 44 {.str = "event", .field = PERF_OUTPUT_EVNAME},
43 {.str = "trace", .field = PERF_OUTPUT_TRACE}, 45 {.str = "trace", .field = PERF_OUTPUT_TRACE},
46 {.str = "sym", .field = PERF_OUTPUT_SYM},
44}; 47};
45 48
46/* default set to maintain compatibility with current format */ 49/* default set to maintain compatibility with current format */
@@ -65,6 +68,8 @@ static void print_sample_start(struct perf_sample *sample,
65 if (PRINT_FIELD(COMM)) { 68 if (PRINT_FIELD(COMM)) {
66 if (latency_format) 69 if (latency_format)
67 printf("%8.8s ", thread->comm); 70 printf("%8.8s ", thread->comm);
71 else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
72 printf("%s ", thread->comm);
68 else 73 else
69 printf("%16s ", thread->comm); 74 printf("%16s ", thread->comm);
70 } 75 }
@@ -112,6 +117,14 @@ static void process_event(union perf_event *event __unused,
112 print_trace_event(sample->cpu, sample->raw_data, 117 print_trace_event(sample->cpu, sample->raw_data,
113 sample->raw_size); 118 sample->raw_size);
114 119
120 if (PRINT_FIELD(SYM)) {
121 if (!symbol_conf.use_callchain)
122 printf(" ");
123 else
124 printf("\n");
125 perf_session__print_symbols(event, sample, session);
126 }
127
115 printf("\n"); 128 printf("\n");
116} 129}
117 130
@@ -190,7 +203,10 @@ static int process_sample_event(union perf_event *event,
190 203
191static struct perf_event_ops event_ops = { 204static struct perf_event_ops event_ops = {
192 .sample = process_sample_event, 205 .sample = process_sample_event,
206 .mmap = perf_event__process_mmap,
193 .comm = perf_event__process_comm, 207 .comm = perf_event__process_comm,
208 .exit = perf_event__process_task,
209 .fork = perf_event__process_task,
194 .attr = perf_event__process_attr, 210 .attr = perf_event__process_attr,
195 .event_type = perf_event__process_event_type, 211 .event_type = perf_event__process_event_type,
196 .tracing_data = perf_event__process_tracing_data, 212 .tracing_data = perf_event__process_tracing_data,
@@ -722,8 +738,16 @@ static const struct option options[] = {
722 "input file name"), 738 "input file name"),
723 OPT_BOOLEAN('d', "debug-mode", &debug_mode, 739 OPT_BOOLEAN('d', "debug-mode", &debug_mode,
724 "do various checks like samples ordering and lost events"), 740 "do various checks like samples ordering and lost events"),
741 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
742 "file", "vmlinux pathname"),
743 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
744 "file", "kallsyms pathname"),
745 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
746 "When printing symbols do not display call chain"),
747 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
748 "Look for files with symbols relative to this directory"),
725 OPT_CALLBACK('f', "fields", NULL, "str", 749 OPT_CALLBACK('f', "fields", NULL, "str",
726 "comma separated output fields. Options: comm,tid,pid,time,cpu,event,trace", 750 "comma separated output fields. Options: comm,tid,pid,time,cpu,event,trace,sym",
727 parse_output_fields), 751 parse_output_fields),
728 752
729 OPT_END() 753 OPT_END()
@@ -905,6 +929,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
905 if (session == NULL) 929 if (session == NULL)
906 return -ENOMEM; 930 return -ENOMEM;
907 931
932 if (!no_callchain && (session->sample_type & PERF_SAMPLE_CALLCHAIN))
933 symbol_conf.use_callchain = true;
934 else
935 symbol_conf.use_callchain = false;
936
908 if (strcmp(input_name, "-") && 937 if (strcmp(input_name, "-") &&
909 !perf_session__has_traces(session, "record -R")) 938 !perf_session__has_traces(session, "record -R"))
910 return -EINVAL; 939 return -EINVAL;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f26639fa0fb3..c68cf40764f9 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1134,3 +1134,64 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
1134 1134
1135 return ret; 1135 return ret;
1136} 1136}
1137
1138void perf_session__print_symbols(union perf_event *event,
1139 struct perf_sample *sample,
1140 struct perf_session *session)
1141{
1142 struct addr_location al;
1143 const char *symname, *dsoname;
1144 struct callchain_cursor *cursor = &session->callchain_cursor;
1145 struct callchain_cursor_node *node;
1146
1147 if (perf_event__preprocess_sample(event, session, &al, sample,
1148 NULL) < 0) {
1149 error("problem processing %d event, skipping it.\n",
1150 event->header.type);
1151 return;
1152 }
1153
1154 if (symbol_conf.use_callchain && sample->callchain) {
1155
1156 if (perf_session__resolve_callchain(session, al.thread,
1157 sample->callchain, NULL) != 0) {
1158 if (verbose)
1159 error("Failed to resolve callchain. Skipping\n");
1160 return;
1161 }
1162 callchain_cursor_commit(cursor);
1163
1164 while (1) {
1165 node = callchain_cursor_current(cursor);
1166 if (!node)
1167 break;
1168
1169 if (node->sym && node->sym->name)
1170 symname = node->sym->name;
1171 else
1172 symname = "";
1173
1174 if (node->map && node->map->dso && node->map->dso->name)
1175 dsoname = node->map->dso->name;
1176 else
1177 dsoname = "";
1178
1179 printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
1180
1181 callchain_cursor_advance(cursor);
1182 }
1183
1184 } else {
1185 if (al.sym && al.sym->name)
1186 symname = al.sym->name;
1187 else
1188 symname = "";
1189
1190 if (al.map && al.map->dso && al.map->dso->name)
1191 dsoname = al.map->dso->name;
1192 else
1193 dsoname = "";
1194
1195 printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
1196 }
1197}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index b5b148b0aaca..0b3c9afecaa9 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -159,4 +159,8 @@ static inline int perf_session__parse_sample(struct perf_session *session,
159 session->sample_id_all, sample); 159 session->sample_id_all, sample);
160} 160}
161 161
162void perf_session__print_symbols(union perf_event *event,
163 struct perf_sample *sample,
164 struct perf_session *session);
165
162#endif /* __PERF_SESSION_H */ 166#endif /* __PERF_SESSION_H */