aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-script.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 19:44:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-07-22 19:44:39 -0400
commit4d4abdcb1dee03a4f9d6d2021622ed07e14dfd17 (patch)
tree4ed4c74b70240451065165fda5fb2059f8c6b1e5 /tools/perf/builtin-script.c
parent0342cbcfced2ee937d7c8e1c63f3d3082da7c7dc (diff)
parent7fcfd1abd6480d3b9ef17f5759c175e036e835cf (diff)
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (123 commits) perf: Remove the nmi parameter from the oprofile_perf backend x86, perf: Make copy_from_user_nmi() a library function perf: Remove perf_event_attr::type check x86, perf: P4 PMU - Fix typos in comments and style cleanup perf tools: Make test use the preset debugfs path perf tools: Add automated tests for events parsing perf tools: De-opt the parse_events function perf script: Fix display of IP address for non-callchain path perf tools: Fix endian conversion reading event attr from file header perf tools: Add missing 'node' alias to the hw_cache[] array perf probe: Support adding probes on offline kernel modules perf probe: Add probed module in front of function perf probe: Introduce debuginfo to encapsulate dwarf information perf-probe: Move dwarf library routines to dwarf-aux.{c, h} perf probe: Remove redundant dwarf functions perf probe: Move strtailcmp to string.c perf probe: Rename DIE_FIND_CB_FOUND to DIE_FIND_CB_END tracing/kprobe: Update symbol reference when loading module tracing/kprobes: Support module init function probing kprobes: Return -ENOENT if probe point doesn't exist ...
Diffstat (limited to 'tools/perf/builtin-script.c')
-rw-r--r--tools/perf/builtin-script.c121
1 files changed, 111 insertions, 10 deletions
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 22747de7234b..09024ec2ab2e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -13,6 +13,7 @@
13#include "util/util.h" 13#include "util/util.h"
14#include "util/evlist.h" 14#include "util/evlist.h"
15#include "util/evsel.h" 15#include "util/evsel.h"
16#include <linux/bitmap.h>
16 17
17static char const *script_name; 18static char const *script_name;
18static char const *generate_script_lang; 19static char const *generate_script_lang;
@@ -21,6 +22,8 @@ static u64 last_timestamp;
21static u64 nr_unordered; 22static u64 nr_unordered;
22extern const struct option record_options[]; 23extern const struct option record_options[];
23static bool no_callchain; 24static bool no_callchain;
25static const char *cpu_list;
26static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
24 27
25enum perf_output_field { 28enum perf_output_field {
26 PERF_OUTPUT_COMM = 1U << 0, 29 PERF_OUTPUT_COMM = 1U << 0,
@@ -30,7 +33,10 @@ enum perf_output_field {
30 PERF_OUTPUT_CPU = 1U << 4, 33 PERF_OUTPUT_CPU = 1U << 4,
31 PERF_OUTPUT_EVNAME = 1U << 5, 34 PERF_OUTPUT_EVNAME = 1U << 5,
32 PERF_OUTPUT_TRACE = 1U << 6, 35 PERF_OUTPUT_TRACE = 1U << 6,
33 PERF_OUTPUT_SYM = 1U << 7, 36 PERF_OUTPUT_IP = 1U << 7,
37 PERF_OUTPUT_SYM = 1U << 8,
38 PERF_OUTPUT_DSO = 1U << 9,
39 PERF_OUTPUT_ADDR = 1U << 10,
34}; 40};
35 41
36struct output_option { 42struct output_option {
@@ -44,7 +50,10 @@ struct output_option {
44 {.str = "cpu", .field = PERF_OUTPUT_CPU}, 50 {.str = "cpu", .field = PERF_OUTPUT_CPU},
45 {.str = "event", .field = PERF_OUTPUT_EVNAME}, 51 {.str = "event", .field = PERF_OUTPUT_EVNAME},
46 {.str = "trace", .field = PERF_OUTPUT_TRACE}, 52 {.str = "trace", .field = PERF_OUTPUT_TRACE},
53 {.str = "ip", .field = PERF_OUTPUT_IP},
47 {.str = "sym", .field = PERF_OUTPUT_SYM}, 54 {.str = "sym", .field = PERF_OUTPUT_SYM},
55 {.str = "dso", .field = PERF_OUTPUT_DSO},
56 {.str = "addr", .field = PERF_OUTPUT_ADDR},
48}; 57};
49 58
50/* default set to maintain compatibility with current format */ 59/* default set to maintain compatibility with current format */
@@ -60,7 +69,8 @@ static struct {
60 69
61 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 70 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
62 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 71 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
63 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 72 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
73 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
64 74
65 .invalid_fields = PERF_OUTPUT_TRACE, 75 .invalid_fields = PERF_OUTPUT_TRACE,
66 }, 76 },
@@ -70,7 +80,8 @@ static struct {
70 80
71 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 81 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
72 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 82 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
73 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 83 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
84 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
74 85
75 .invalid_fields = PERF_OUTPUT_TRACE, 86 .invalid_fields = PERF_OUTPUT_TRACE,
76 }, 87 },
@@ -88,7 +99,8 @@ static struct {
88 99
89 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID | 100 .fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
90 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME | 101 PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
91 PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM, 102 PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
103 PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
92 104
93 .invalid_fields = PERF_OUTPUT_TRACE, 105 .invalid_fields = PERF_OUTPUT_TRACE,
94 }, 106 },
@@ -157,9 +169,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
157 !perf_session__has_traces(session, "record -R")) 169 !perf_session__has_traces(session, "record -R"))
158 return -EINVAL; 170 return -EINVAL;
159 171
160 if (PRINT_FIELD(SYM)) { 172 if (PRINT_FIELD(IP)) {
161 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP", 173 if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
162 PERF_OUTPUT_SYM)) 174 PERF_OUTPUT_IP))
163 return -EINVAL; 175 return -EINVAL;
164 176
165 if (!no_callchain && 177 if (!no_callchain &&
@@ -167,6 +179,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
167 symbol_conf.use_callchain = false; 179 symbol_conf.use_callchain = false;
168 } 180 }
169 181
182 if (PRINT_FIELD(ADDR) &&
183 perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
184 PERF_OUTPUT_ADDR))
185 return -EINVAL;
186
187 if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
188 pr_err("Display of symbols requested but neither sample IP nor "
189 "sample address\nis selected. Hence, no addresses to convert "
190 "to symbols.\n");
191 return -EINVAL;
192 }
193 if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
194 pr_err("Display of DSO requested but neither sample IP nor "
195 "sample address\nis selected. Hence, no addresses to convert "
196 "to DSO.\n");
197 return -EINVAL;
198 }
199
170 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) && 200 if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
171 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID", 201 perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
172 PERF_OUTPUT_TID|PERF_OUTPUT_PID)) 202 PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@@ -230,7 +260,7 @@ static void print_sample_start(struct perf_sample *sample,
230 if (PRINT_FIELD(COMM)) { 260 if (PRINT_FIELD(COMM)) {
231 if (latency_format) 261 if (latency_format)
232 printf("%8.8s ", thread->comm); 262 printf("%8.8s ", thread->comm);
233 else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain) 263 else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
234 printf("%s ", thread->comm); 264 printf("%s ", thread->comm);
235 else 265 else
236 printf("%16s ", thread->comm); 266 printf("%16s ", thread->comm);
@@ -271,6 +301,63 @@ static void print_sample_start(struct perf_sample *sample,
271 } 301 }
272} 302}
273 303
304static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
305{
306 if ((attr->type == PERF_TYPE_SOFTWARE) &&
307 ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
308 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
309 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
310 return true;
311
312 return false;
313}
314
315static void print_sample_addr(union perf_event *event,
316 struct perf_sample *sample,
317 struct perf_session *session,
318 struct thread *thread,
319 struct perf_event_attr *attr)
320{
321 struct addr_location al;
322 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
323 const char *symname, *dsoname;
324
325 printf("%16" PRIx64, sample->addr);
326
327 if (!sample_addr_correlates_sym(attr))
328 return;
329
330 thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
331 event->ip.pid, sample->addr, &al);
332 if (!al.map)
333 thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
334 event->ip.pid, sample->addr, &al);
335
336 al.cpu = sample->cpu;
337 al.sym = NULL;
338
339 if (al.map)
340 al.sym = map__find_symbol(al.map, al.addr, NULL);
341
342 if (PRINT_FIELD(SYM)) {
343 if (al.sym && al.sym->name)
344 symname = al.sym->name;
345 else
346 symname = "";
347
348 printf(" %16s", symname);
349 }
350
351 if (PRINT_FIELD(DSO)) {
352 if (al.map && al.map->dso && al.map->dso->name)
353 dsoname = al.map->dso->name;
354 else
355 dsoname = "";
356
357 printf(" (%s)", dsoname);
358 }
359}
360
274static void process_event(union perf_event *event __unused, 361static void process_event(union perf_event *event __unused,
275 struct perf_sample *sample, 362 struct perf_sample *sample,
276 struct perf_evsel *evsel, 363 struct perf_evsel *evsel,
@@ -288,12 +375,16 @@ static void process_event(union perf_event *event __unused,
288 print_trace_event(sample->cpu, sample->raw_data, 375 print_trace_event(sample->cpu, sample->raw_data,
289 sample->raw_size); 376 sample->raw_size);
290 377
291 if (PRINT_FIELD(SYM)) { 378 if (PRINT_FIELD(ADDR))
379 print_sample_addr(event, sample, session, thread, attr);
380
381 if (PRINT_FIELD(IP)) {
292 if (!symbol_conf.use_callchain) 382 if (!symbol_conf.use_callchain)
293 printf(" "); 383 printf(" ");
294 else 384 else
295 printf("\n"); 385 printf("\n");
296 perf_session__print_symbols(event, sample, session); 386 perf_session__print_ip(event, sample, session,
387 PRINT_FIELD(SYM), PRINT_FIELD(DSO));
297 } 388 }
298 389
299 printf("\n"); 390 printf("\n");
@@ -365,6 +456,10 @@ static int process_sample_event(union perf_event *event,
365 last_timestamp = sample->time; 456 last_timestamp = sample->time;
366 return 0; 457 return 0;
367 } 458 }
459
460 if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
461 return 0;
462
368 scripting_ops->process_event(event, sample, evsel, session, thread); 463 scripting_ops->process_event(event, sample, evsel, session, thread);
369 464
370 session->hists.stats.total_period += sample->period; 465 session->hists.stats.total_period += sample->period;
@@ -985,8 +1080,9 @@ static const struct option options[] = {
985 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1080 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
986 "Look for files with symbols relative to this directory"), 1081 "Look for files with symbols relative to this directory"),
987 OPT_CALLBACK('f', "fields", NULL, "str", 1082 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", 1083 "comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
989 parse_output_fields), 1084 parse_output_fields),
1085 OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
990 1086
991 OPT_END() 1087 OPT_END()
992}; 1088};
@@ -1167,6 +1263,11 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
1167 if (session == NULL) 1263 if (session == NULL)
1168 return -ENOMEM; 1264 return -ENOMEM;
1169 1265
1266 if (cpu_list) {
1267 if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
1268 return -1;
1269 }
1270
1170 if (!no_callchain) 1271 if (!no_callchain)
1171 symbol_conf.use_callchain = true; 1272 symbol_conf.use_callchain = true;
1172 else 1273 else