aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2013-11-11 07:44:09 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-11-11 13:56:39 -0500
commit62605dc50c27bf0e4ff69b7b3166f226586aff02 (patch)
treee858c9a71749a3d280b25a7ab7928dcbeba51a73
parentef503831d8d64e12c6dad5547875cfcd4c5d043c (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.c4
-rw-r--r--tools/perf/builtin-record.c6
-rw-r--r--tools/perf/builtin-top.c4
-rw-r--r--tools/perf/builtin-trace.c4
-rw-r--r--tools/perf/tests/code-reading.c2
-rw-r--r--tools/perf/util/event.c50
-rw-r--r--tools/perf/util/event.h4
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
317int perf_event__synthesize_thread_map(struct perf_tool *tool, 322int 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
375int perf_event__synthesize_threads(struct perf_tool *tool, 382int 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
529size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp) 536size_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
536size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp) 545size_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,
208int perf_event__synthesize_thread_map(struct perf_tool *tool, 208int 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);
212int perf_event__synthesize_threads(struct perf_tool *tool, 212int 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);
215int perf_event__synthesize_kernel_mmap(struct perf_tool *tool, 215int 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,