diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-11-11 07:44:09 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-11-11 13:56:39 -0500 |
commit | 62605dc50c27bf0e4ff69b7b3166f226586aff02 (patch) | |
tree | e858c9a71749a3d280b25a7ab7928dcbeba51a73 | |
parent | ef503831d8d64e12c6dad5547875cfcd4c5d043c (diff) |
perf record: Synthesize non-exec MMAP records when --data used
When perf_event_attr.mmap_data is set the kernel will generate
PERF_RECORD_MMAP events when non-exec (data, SysV mem) mmaps are
created, so we need to synthesize from /proc/pid/maps for existing
threads, as we do for exec mmaps.
Right now just 'perf record' does it, but any other tool that uses
perf_event__synthesize_thread(s|map) can request it.
Reported-by: Don Zickus <dzickus@redhat.com>
Tested-by: Don Zickus <dzickus@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Bill Gray <bgray@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Don Zickus <dzickus@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Joe Mario <jmario@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Fowles <rfowles@redhat.com>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-ihwzraikx23ian9txinogvv2@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | tools/perf/builtin-kvm.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 6 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-trace.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/code-reading.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 50 | ||||
-rw-r--r-- | tools/perf/util/event.h | 4 |
7 files changed, 42 insertions, 32 deletions
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index cd9f92078aba..f36e8209c300 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c | |||
@@ -1550,10 +1550,10 @@ static int kvm_events_live(struct perf_kvm_stat *kvm, | |||
1550 | perf_event__synthesize_thread_map(&kvm->tool, | 1550 | perf_event__synthesize_thread_map(&kvm->tool, |
1551 | kvm->evlist->threads, | 1551 | kvm->evlist->threads, |
1552 | perf_event__process, | 1552 | perf_event__process, |
1553 | &kvm->session->machines.host); | 1553 | &kvm->session->machines.host, false); |
1554 | else | 1554 | else |
1555 | perf_event__synthesize_threads(&kvm->tool, perf_event__process, | 1555 | perf_event__synthesize_threads(&kvm->tool, perf_event__process, |
1556 | &kvm->session->machines.host); | 1556 | &kvm->session->machines.host, false); |
1557 | 1557 | ||
1558 | 1558 | ||
1559 | err = kvm_live_open_events(kvm); | 1559 | err = kvm_live_open_events(kvm); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 15280b5e5574..afb252cf6eca 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -482,11 +482,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) | |||
482 | 482 | ||
483 | if (perf_target__has_task(&opts->target)) | 483 | if (perf_target__has_task(&opts->target)) |
484 | err = perf_event__synthesize_thread_map(tool, evsel_list->threads, | 484 | err = perf_event__synthesize_thread_map(tool, evsel_list->threads, |
485 | process_synthesized_event, | 485 | process_synthesized_event, |
486 | machine); | 486 | machine, opts->sample_address); |
487 | else if (perf_target__has_cpu(&opts->target)) | 487 | else if (perf_target__has_cpu(&opts->target)) |
488 | err = perf_event__synthesize_threads(tool, process_synthesized_event, | 488 | err = perf_event__synthesize_threads(tool, process_synthesized_event, |
489 | machine); | 489 | machine, opts->sample_address); |
490 | else /* command specified */ | 490 | else /* command specified */ |
491 | err = 0; | 491 | err = 0; |
492 | 492 | ||
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 9acca8856ccb..cc96d753db96 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -953,10 +953,10 @@ static int __cmd_top(struct perf_top *top) | |||
953 | if (perf_target__has_task(&opts->target)) | 953 | if (perf_target__has_task(&opts->target)) |
954 | perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, | 954 | perf_event__synthesize_thread_map(&top->tool, top->evlist->threads, |
955 | perf_event__process, | 955 | perf_event__process, |
956 | &top->session->machines.host); | 956 | &top->session->machines.host, false); |
957 | else | 957 | else |
958 | perf_event__synthesize_threads(&top->tool, perf_event__process, | 958 | perf_event__synthesize_threads(&top->tool, perf_event__process, |
959 | &top->session->machines.host); | 959 | &top->session->machines.host, false); |
960 | 960 | ||
961 | ret = perf_top__start_counters(top); | 961 | ret = perf_top__start_counters(top); |
962 | if (ret) | 962 | if (ret) |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index 68943cad70d4..277c2367e0cf 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
@@ -1343,10 +1343,10 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) | |||
1343 | if (perf_target__has_task(&trace->opts.target)) { | 1343 | if (perf_target__has_task(&trace->opts.target)) { |
1344 | err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, | 1344 | err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads, |
1345 | trace__tool_process, | 1345 | trace__tool_process, |
1346 | trace->host); | 1346 | trace->host, false); |
1347 | } else { | 1347 | } else { |
1348 | err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, | 1348 | err = perf_event__synthesize_threads(&trace->tool, trace__tool_process, |
1349 | trace->host); | 1349 | trace->host, false); |
1350 | } | 1350 | } |
1351 | 1351 | ||
1352 | if (err) | 1352 | if (err) |
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index 49ccc3b2995e..6d9dc198a200 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c | |||
@@ -441,7 +441,7 @@ static int do_test_code_reading(bool try_kcore) | |||
441 | } | 441 | } |
442 | 442 | ||
443 | ret = perf_event__synthesize_thread_map(NULL, threads, | 443 | ret = perf_event__synthesize_thread_map(NULL, threads, |
444 | perf_event__process, machine); | 444 | perf_event__process, machine, false); |
445 | if (ret < 0) { | 445 | if (ret < 0) { |
446 | pr_debug("perf_event__synthesize_thread_map failed\n"); | 446 | pr_debug("perf_event__synthesize_thread_map failed\n"); |
447 | goto out_err; | 447 | goto out_err; |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index ec9ae1114ed4..6e3a846aed0e 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -170,7 +170,8 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
170 | union perf_event *event, | 170 | union perf_event *event, |
171 | pid_t pid, pid_t tgid, | 171 | pid_t pid, pid_t tgid, |
172 | perf_event__handler_t process, | 172 | perf_event__handler_t process, |
173 | struct machine *machine) | 173 | struct machine *machine, |
174 | bool mmap_data) | ||
174 | { | 175 | { |
175 | char filename[PATH_MAX]; | 176 | char filename[PATH_MAX]; |
176 | FILE *fp; | 177 | FILE *fp; |
@@ -188,10 +189,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
188 | } | 189 | } |
189 | 190 | ||
190 | event->header.type = PERF_RECORD_MMAP; | 191 | event->header.type = PERF_RECORD_MMAP; |
191 | /* | ||
192 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | ||
193 | */ | ||
194 | event->header.misc = PERF_RECORD_MISC_USER; | ||
195 | 192 | ||
196 | while (1) { | 193 | while (1) { |
197 | char bf[BUFSIZ]; | 194 | char bf[BUFSIZ]; |
@@ -215,9 +212,17 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, | |||
215 | 212 | ||
216 | if (n != 5) | 213 | if (n != 5) |
217 | continue; | 214 | continue; |
215 | /* | ||
216 | * Just like the kernel, see __perf_event_mmap in kernel/perf_event.c | ||
217 | */ | ||
218 | event->header.misc = PERF_RECORD_MISC_USER; | ||
218 | 219 | ||
219 | if (prot[2] != 'x') | 220 | if (prot[2] != 'x') { |
220 | continue; | 221 | if (!mmap_data || prot[0] != 'r') |
222 | continue; | ||
223 | |||
224 | event->header.misc |= PERF_RECORD_MISC_MMAP_DATA; | ||
225 | } | ||
221 | 226 | ||
222 | if (!strcmp(execname, "")) | 227 | if (!strcmp(execname, "")) |
223 | strcpy(execname, anonstr); | 228 | strcpy(execname, anonstr); |
@@ -304,20 +309,21 @@ static int __event__synthesize_thread(union perf_event *comm_event, | |||
304 | pid_t pid, int full, | 309 | pid_t pid, int full, |
305 | perf_event__handler_t process, | 310 | perf_event__handler_t process, |
306 | struct perf_tool *tool, | 311 | struct perf_tool *tool, |
307 | struct machine *machine) | 312 | struct machine *machine, bool mmap_data) |
308 | { | 313 | { |
309 | pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, | 314 | pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full, |
310 | process, machine); | 315 | process, machine); |
311 | if (tgid == -1) | 316 | if (tgid == -1) |
312 | return -1; | 317 | return -1; |
313 | return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, | 318 | return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, |
314 | process, machine); | 319 | process, machine, mmap_data); |
315 | } | 320 | } |
316 | 321 | ||
317 | int perf_event__synthesize_thread_map(struct perf_tool *tool, | 322 | int perf_event__synthesize_thread_map(struct perf_tool *tool, |
318 | struct thread_map *threads, | 323 | struct thread_map *threads, |
319 | perf_event__handler_t process, | 324 | perf_event__handler_t process, |
320 | struct machine *machine) | 325 | struct machine *machine, |
326 | bool mmap_data) | ||
321 | { | 327 | { |
322 | union perf_event *comm_event, *mmap_event; | 328 | union perf_event *comm_event, *mmap_event; |
323 | int err = -1, thread, j; | 329 | int err = -1, thread, j; |
@@ -334,7 +340,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, | |||
334 | for (thread = 0; thread < threads->nr; ++thread) { | 340 | for (thread = 0; thread < threads->nr; ++thread) { |
335 | if (__event__synthesize_thread(comm_event, mmap_event, | 341 | if (__event__synthesize_thread(comm_event, mmap_event, |
336 | threads->map[thread], 0, | 342 | threads->map[thread], 0, |
337 | process, tool, machine)) { | 343 | process, tool, machine, |
344 | mmap_data)) { | ||
338 | err = -1; | 345 | err = -1; |
339 | break; | 346 | break; |
340 | } | 347 | } |
@@ -356,10 +363,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool, | |||
356 | 363 | ||
357 | /* if not, generate events for it */ | 364 | /* if not, generate events for it */ |
358 | if (need_leader && | 365 | if (need_leader && |
359 | __event__synthesize_thread(comm_event, | 366 | __event__synthesize_thread(comm_event, mmap_event, |
360 | mmap_event, | 367 | comm_event->comm.pid, 0, |
361 | comm_event->comm.pid, 0, | 368 | process, tool, machine, |
362 | process, tool, machine)) { | 369 | mmap_data)) { |
363 | err = -1; | 370 | err = -1; |
364 | break; | 371 | break; |
365 | } | 372 | } |
@@ -374,7 +381,7 @@ out: | |||
374 | 381 | ||
375 | int perf_event__synthesize_threads(struct perf_tool *tool, | 382 | int perf_event__synthesize_threads(struct perf_tool *tool, |
376 | perf_event__handler_t process, | 383 | perf_event__handler_t process, |
377 | struct machine *machine) | 384 | struct machine *machine, bool mmap_data) |
378 | { | 385 | { |
379 | DIR *proc; | 386 | DIR *proc; |
380 | struct dirent dirent, *next; | 387 | struct dirent dirent, *next; |
@@ -404,7 +411,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool, | |||
404 | * one thread couldn't be synthesized. | 411 | * one thread couldn't be synthesized. |
405 | */ | 412 | */ |
406 | __event__synthesize_thread(comm_event, mmap_event, pid, 1, | 413 | __event__synthesize_thread(comm_event, mmap_event, pid, 1, |
407 | process, tool, machine); | 414 | process, tool, machine, mmap_data); |
408 | } | 415 | } |
409 | 416 | ||
410 | err = 0; | 417 | err = 0; |
@@ -528,19 +535,22 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused, | |||
528 | 535 | ||
529 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) | 536 | size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) |
530 | { | 537 | { |
531 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n", | 538 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n", |
532 | event->mmap.pid, event->mmap.tid, event->mmap.start, | 539 | event->mmap.pid, event->mmap.tid, event->mmap.start, |
533 | event->mmap.len, event->mmap.pgoff, event->mmap.filename); | 540 | event->mmap.len, event->mmap.pgoff, |
541 | (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', | ||
542 | event->mmap.filename); | ||
534 | } | 543 | } |
535 | 544 | ||
536 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) | 545 | size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) |
537 | { | 546 | { |
538 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 | 547 | return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 |
539 | " %02x:%02x %"PRIu64" %"PRIu64"]: %s\n", | 548 | " %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n", |
540 | event->mmap2.pid, event->mmap2.tid, event->mmap2.start, | 549 | event->mmap2.pid, event->mmap2.tid, event->mmap2.start, |
541 | event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, | 550 | event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj, |
542 | event->mmap2.min, event->mmap2.ino, | 551 | event->mmap2.min, event->mmap2.ino, |
543 | event->mmap2.ino_generation, | 552 | event->mmap2.ino_generation, |
553 | (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x', | ||
544 | event->mmap2.filename); | 554 | event->mmap2.filename); |
545 | } | 555 | } |
546 | 556 | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index f8d70f3003ab..30fec9901e44 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -208,10 +208,10 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, | |||
208 | int perf_event__synthesize_thread_map(struct perf_tool *tool, | 208 | int perf_event__synthesize_thread_map(struct perf_tool *tool, |
209 | struct thread_map *threads, | 209 | struct thread_map *threads, |
210 | perf_event__handler_t process, | 210 | perf_event__handler_t process, |
211 | struct machine *machine); | 211 | struct machine *machine, bool mmap_data); |
212 | int perf_event__synthesize_threads(struct perf_tool *tool, | 212 | int perf_event__synthesize_threads(struct perf_tool *tool, |
213 | perf_event__handler_t process, | 213 | perf_event__handler_t process, |
214 | struct machine *machine); | 214 | struct machine *machine, bool mmap_data); |
215 | int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, | 215 | int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, |
216 | perf_event__handler_t process, | 216 | perf_event__handler_t process, |
217 | struct machine *machine, | 217 | struct machine *machine, |