aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2011-05-27 16:28:43 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2011-06-02 12:28:34 -0400
commit787bef174f055343c69a9639e6e05a564980ed4c (patch)
treed37e4fae03454e74684798bc112ba161786f978a /tools
parent2cee77c4505fc581f41b44e18ffc0953b67a414c (diff)
perf script: "sym" field really means show IP data
Currently the "sym" output field is used to dump instruction pointers and callchain stack. Sample addresses can also be converted to symbols, so the meaning of "sym" needs to be fixed. This patch adds an "ip" option and if it is selected the user can also opt to dump symbols for them. If the user opts to dump IP without syms only the address is shown. 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> Link: http://lkml.kernel.org/r/1306528124-25861-2-git-send-email-dsahern@gmail.com Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-script.txt10
-rw-r--r--tools/perf/builtin-script.c31
-rw-r--r--tools/perf/util/session.c50
-rw-r--r--tools/perf/util/session.h5
4 files changed, 58 insertions, 38 deletions
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 86c87e214b11..67a4e5cbc880 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -115,10 +115,10 @@ 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, sym. Field 118 comm, tid, pid, time, cpu, event, trace, ip, sym. Field
119 list can be prepended with the type, trace, sw or hw, 119 list can be prepended with the type, trace, sw or hw,
120 to indicate to which event type the field list applies. 120 to indicate to which event type the field list applies.
121 e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace 121 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
122 122
123 perf script -f <fields> 123 perf script -f <fields>
124 124
@@ -132,17 +132,17 @@ OPTIONS
132 The arguments are processed in the order received. A later usage can 132 The arguments are processed in the order received. A later usage can
133 reset a prior request. e.g.: 133 reset a prior request. e.g.:
134 134
135 -f trace: -f comm,tid,time,sym 135 -f trace: -f comm,tid,time,ip,sym
136 136
137 The first -f suppresses trace events (field list is ""), but then the 137 The first -f suppresses trace events (field list is ""), but then the
138 second invocation sets the fields to comm,tid,time,sym. In this case a 138 second invocation sets the fields to comm,tid,time,ip,sym. In this case a
139 warning is given to the user: 139 warning is given to the user:
140 140
141 "Overriding previous field request for all events." 141 "Overriding previous field request for all events."
142 142
143 Alternativey, consider the order: 143 Alternativey, consider the order:
144 144
145 -f comm,tid,time,sym -f trace: 145 -f comm,tid,time,ip,sym -f trace:
146 146
147 The first -f sets the fields for all events and the second -f 147 The first -f sets the fields for all events and the second -f
148 suppresses trace events. The user is given a warning message about 148 suppresses trace events. The user is given a warning message about
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 22747de7234b..0852db2ea155 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -30,7 +30,8 @@ enum perf_output_field {
30 PERF_OUTPUT_CPU = 1U << 4, 30 PERF_OUTPUT_CPU = 1U << 4,
31 PERF_OUTPUT_EVNAME = 1U << 5, 31 PERF_OUTPUT_EVNAME = 1U << 5,
32 PERF_OUTPUT_TRACE = 1U << 6, 32 PERF_OUTPUT_TRACE = 1U << 6,
33 PERF_OUTPUT_SYM = 1U << 7, 33 PERF_OUTPUT_IP = 1U << 7,
34 PERF_OUTPUT_SYM = 1U << 8,
34}; 35};
35 36
36struct output_option { 37struct output_option {
@@ -44,6 +45,7 @@ struct output_option {
44 {.str = "cpu", .field = PERF_OUTPUT_CPU}, 45 {.str = "cpu", .field = PERF_OUTPUT_CPU},
45 {.str = "event", .field = PERF_OUTPUT_EVNAME}, 46 {.str = "event", .field = PERF_OUTPUT_EVNAME},
46 {.str = "trace", .field = PERF_OUTPUT_TRACE}, 47 {.str = "trace", .field = PERF_OUTPUT_TRACE},
48 {.str = "ip", .field = PERF_OUTPUT_IP},
47 {.str = "sym", .field = PERF_OUTPUT_SYM}, 49 {.str = "sym", .field = PERF_OUTPUT_SYM},
48}; 50};
49 51
@@ -60,7 +62,8 @@ static struct {
60 62
61 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 63 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 64 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 65 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
66 PERF_OUTPUT_SYM,
64 67
65 .invalid_fields = PERF_OUTPUT_TRACE, 68 .invalid_fields = PERF_OUTPUT_TRACE,
66 }, 69 },
@@ -70,7 +73,8 @@ static struct {
70 73
71 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 74 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
72 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 75 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
73 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 76 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
77 PERF_OUTPUT_SYM,
74 78
75 .invalid_fields = PERF_OUTPUT_TRACE, 79 .invalid_fields = PERF_OUTPUT_TRACE,
76 }, 80 },
@@ -88,7 +92,8 @@ static struct {
88 92
89 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 93 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
90 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 94 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
91 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 95 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
96 PERF_OUTPUT_SYM,
92 97
93 .invalid_fields = PERF_OUTPUT_TRACE, 98 .invalid_fields = PERF_OUTPUT_TRACE,
94 }, 99 },
@@ -157,15 +162,20 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
157 !perf_session__has_traces(session, "record -R")) 162 !perf_session__has_traces(session, "record -R"))
158 return -EINVAL; 163 return -EINVAL;
159 164
160 if (PRINT_FIELD(SYM)) { 165 if (PRINT_FIELD(IP)) {
161 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 166 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
162 PERF_OUTPUT_SYM)) 167 PERF_OUTPUT_IP))
163 return -EINVAL; 168 return -EINVAL;
164 169
165 if (!no_callchain && 170 if (!no_callchain &&
166 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN)) 171 !(attr->sample_type & PERF_SAMPLE_CALLCHAIN))
167 symbol_conf.use_callchain = false; 172 symbol_conf.use_callchain = false;
168 } 173 }
174 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP)) {
175 pr_err("Display of symbols requested but IP is not selected.\n"
176 "No addresses to convert to symbols.\n");
177 return -EINVAL;
178 }
169 179
170 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 180 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
171 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 181 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
@@ -230,7 +240,7 @@ static void print_sample_start(struct perf_sample *sample,
230 if (PRINT_FIELD(COMM)) { 240 if (PRINT_FIELD(COMM)) {
231 if (latency_format) 241 if (latency_format)
232 printf("%8.8s ", thread->comm); 242 printf("%8.8s ", thread->comm);
233 else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain) 243 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
234 printf("%s ", thread->comm); 244 printf("%s ", thread->comm);
235 else 245 else
236 printf("%16s ", thread->comm); 246 printf("%16s ", thread->comm);
@@ -288,12 +298,13 @@ static void process_event(union perf_event *event __unused,
288 print_trace_event(sample->cpu, sample->raw_data, 298 print_trace_event(sample->cpu, sample->raw_data,
289 sample->raw_size); 299 sample->raw_size);
290 300
291 if (PRINT_FIELD(SYM)) { 301 if (PRINT_FIELD(IP)) {
292 if (!symbol_conf.use_callchain) 302 if (!symbol_conf.use_callchain)
293 printf(" "); 303 printf(" ");
294 else 304 else
295 printf("\n"); 305 printf("\n");
296 perf_session__print_symbols(event, sample, session); 306 perf_session__print_ip(event, sample, session,
307 PRINT_FIELD(SYM));
297 } 308 }
298 309
299 printf("\n"); 310 printf("\n");
@@ -985,7 +996,7 @@ static const struct option options[] = {
985 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 996 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
986 "Look for files with symbols relative to this directory"), 997 "Look for files with symbols relative to this directory"),
987 OPT_CALLBACK('f', "fields", NULL, "str", 998 OPT_CALLBACK('f', "fields", NULL, "str",
988 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym", 999 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym",
989 parse_output_fields), 1000 parse_output_fields),
990 1001
991 OPT_END() 1002 OPT_END()
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index f5a8fbdd3f76..ad33650cdd41 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1202,9 +1202,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1202 return NULL; 1202 return NULL;
1203} 1203}
1204 1204
1205void perf_session__print_symbols(union perf_event *event, 1205void perf_session__print_ip(union perf_event *event,
1206 struct perf_sample *sample, 1206 struct perf_sample *sample,
1207 struct perf_session *session) 1207 struct perf_session *session,
1208 int print_sym)
1208{ 1209{
1209 struct addr_location al; 1210 struct addr_location al;
1210 const char *symname, *dsoname; 1211 const char *symname, *dsoname;
@@ -1233,32 +1234,39 @@ void perf_session__print_symbols(union perf_event *event,
1233 if (!node) 1234 if (!node)
1234 break; 1235 break;
1235 1236
1236 if (node->sym && node->sym->name) 1237 printf("\t%16" PRIx64, node->ip);
1237 symname = node->sym->name; 1238 if (print_sym) {
1238 else 1239 if (node->sym && node->sym->name)
1239 symname = ""; 1240 symname = node->sym->name;
1241 else
1242 symname = "";
1240 1243
1241 if (node->map && node->map->dso && node->map->dso->name) 1244 if (node->map && node->map->dso && node->map->dso->name)
1242 dsoname = node->map->dso->name; 1245 dsoname = node->map->dso->name;
1243 else 1246 else
1244 dsoname = ""; 1247 dsoname = "";
1245 1248
1246 printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname); 1249 printf(" %s (%s)", symname, dsoname);
1250 }
1251 printf("\n");
1247 1252
1248 callchain_cursor_advance(cursor); 1253 callchain_cursor_advance(cursor);
1249 } 1254 }
1250 1255
1251 } else { 1256 } else {
1252 if (al.sym && al.sym->name) 1257 printf("%16" PRIx64, al.addr);
1253 symname = al.sym->name; 1258 if (print_sym) {
1254 else 1259 if (al.sym && al.sym->name)
1255 symname = ""; 1260 symname = al.sym->name;
1261 else
1262 symname = "";
1256 1263
1257 if (al.map && al.map->dso && al.map->dso->name) 1264 if (al.map && al.map->dso && al.map->dso->name)
1258 dsoname = al.map->dso->name; 1265 dsoname = al.map->dso->name;
1259 else 1266 else
1260 dsoname = ""; 1267 dsoname = "";
1261 1268
1262 printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname); 1269 printf(" %s (%s)", symname, dsoname);
1270 }
1263 } 1271 }
1264} 1272}
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 66d4e1490879..d76af0f975d3 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -167,8 +167,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
167struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, 167struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
168 unsigned int type); 168 unsigned int type);
169 169
170void perf_session__print_symbols(union perf_event *event, 170void perf_session__print_ip(union perf_event *event,
171 struct perf_sample *sample, 171 struct perf_sample *sample,
172 struct perf_session *session); 172 struct perf_session *session,
173 int print_sym);
173 174
174#endif /* __PERF_SESSION_H */ 175#endif /* __PERF_SESSION_H */