mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 15:11:31 +00:00
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>
This commit is contained in:
parent
ef503831d8
commit
62605dc50c
@ -1550,10 +1550,10 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
|
||||
perf_event__synthesize_thread_map(&kvm->tool,
|
||||
kvm->evlist->threads,
|
||||
perf_event__process,
|
||||
&kvm->session->machines.host);
|
||||
&kvm->session->machines.host, false);
|
||||
else
|
||||
perf_event__synthesize_threads(&kvm->tool, perf_event__process,
|
||||
&kvm->session->machines.host);
|
||||
&kvm->session->machines.host, false);
|
||||
|
||||
|
||||
err = kvm_live_open_events(kvm);
|
||||
|
@ -482,11 +482,11 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
|
||||
if (perf_target__has_task(&opts->target))
|
||||
err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
|
||||
process_synthesized_event,
|
||||
machine);
|
||||
process_synthesized_event,
|
||||
machine, opts->sample_address);
|
||||
else if (perf_target__has_cpu(&opts->target))
|
||||
err = perf_event__synthesize_threads(tool, process_synthesized_event,
|
||||
machine);
|
||||
machine, opts->sample_address);
|
||||
else /* command specified */
|
||||
err = 0;
|
||||
|
||||
|
@ -953,10 +953,10 @@ static int __cmd_top(struct perf_top *top)
|
||||
if (perf_target__has_task(&opts->target))
|
||||
perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
|
||||
perf_event__process,
|
||||
&top->session->machines.host);
|
||||
&top->session->machines.host, false);
|
||||
else
|
||||
perf_event__synthesize_threads(&top->tool, perf_event__process,
|
||||
&top->session->machines.host);
|
||||
&top->session->machines.host, false);
|
||||
|
||||
ret = perf_top__start_counters(top);
|
||||
if (ret)
|
||||
|
@ -1343,10 +1343,10 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
|
||||
if (perf_target__has_task(&trace->opts.target)) {
|
||||
err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
|
||||
trace__tool_process,
|
||||
trace->host);
|
||||
trace->host, false);
|
||||
} else {
|
||||
err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
|
||||
trace->host);
|
||||
trace->host, false);
|
||||
}
|
||||
|
||||
if (err)
|
||||
|
@ -441,7 +441,7 @@ static int do_test_code_reading(bool try_kcore)
|
||||
}
|
||||
|
||||
ret = perf_event__synthesize_thread_map(NULL, threads,
|
||||
perf_event__process, machine);
|
||||
perf_event__process, machine, false);
|
||||
if (ret < 0) {
|
||||
pr_debug("perf_event__synthesize_thread_map failed\n");
|
||||
goto out_err;
|
||||
|
@ -170,7 +170,8 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
pid_t pid, pid_t tgid,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine,
|
||||
bool mmap_data)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
FILE *fp;
|
||||
@ -188,10 +189,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
}
|
||||
|
||||
event->header.type = PERF_RECORD_MMAP;
|
||||
/*
|
||||
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
|
||||
*/
|
||||
event->header.misc = PERF_RECORD_MISC_USER;
|
||||
|
||||
while (1) {
|
||||
char bf[BUFSIZ];
|
||||
@ -215,9 +212,17 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
|
||||
if (n != 5)
|
||||
continue;
|
||||
/*
|
||||
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
|
||||
*/
|
||||
event->header.misc = PERF_RECORD_MISC_USER;
|
||||
|
||||
if (prot[2] != 'x')
|
||||
continue;
|
||||
if (prot[2] != 'x') {
|
||||
if (!mmap_data || prot[0] != 'r')
|
||||
continue;
|
||||
|
||||
event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
|
||||
}
|
||||
|
||||
if (!strcmp(execname, ""))
|
||||
strcpy(execname, anonstr);
|
||||
@ -304,20 +309,21 @@ static int __event__synthesize_thread(union perf_event *comm_event,
|
||||
pid_t pid, int full,
|
||||
perf_event__handler_t process,
|
||||
struct perf_tool *tool,
|
||||
struct machine *machine)
|
||||
struct machine *machine, bool mmap_data)
|
||||
{
|
||||
pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
|
||||
process, machine);
|
||||
if (tgid == -1)
|
||||
return -1;
|
||||
return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
|
||||
process, machine);
|
||||
process, machine, mmap_data);
|
||||
}
|
||||
|
||||
int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
struct thread_map *threads,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine,
|
||||
bool mmap_data)
|
||||
{
|
||||
union perf_event *comm_event, *mmap_event;
|
||||
int err = -1, thread, j;
|
||||
@ -334,7 +340,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
for (thread = 0; thread < threads->nr; ++thread) {
|
||||
if (__event__synthesize_thread(comm_event, mmap_event,
|
||||
threads->map[thread], 0,
|
||||
process, tool, machine)) {
|
||||
process, tool, machine,
|
||||
mmap_data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
@ -356,10 +363,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
|
||||
/* if not, generate events for it */
|
||||
if (need_leader &&
|
||||
__event__synthesize_thread(comm_event,
|
||||
mmap_event,
|
||||
comm_event->comm.pid, 0,
|
||||
process, tool, machine)) {
|
||||
__event__synthesize_thread(comm_event, mmap_event,
|
||||
comm_event->comm.pid, 0,
|
||||
process, tool, machine,
|
||||
mmap_data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
@ -374,7 +381,7 @@ out:
|
||||
|
||||
int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine, bool mmap_data)
|
||||
{
|
||||
DIR *proc;
|
||||
struct dirent dirent, *next;
|
||||
@ -404,7 +411,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
* one thread couldn't be synthesized.
|
||||
*/
|
||||
__event__synthesize_thread(comm_event, mmap_event, pid, 1,
|
||||
process, tool, machine);
|
||||
process, tool, machine, mmap_data);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
@ -528,19 +535,22 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
|
||||
|
||||
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
|
||||
event->mmap.pid, event->mmap.tid, event->mmap.start,
|
||||
event->mmap.len, event->mmap.pgoff, event->mmap.filename);
|
||||
event->mmap.len, event->mmap.pgoff,
|
||||
(event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
|
||||
event->mmap.filename);
|
||||
}
|
||||
|
||||
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
|
||||
" %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
|
||||
" %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n",
|
||||
event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
|
||||
event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
|
||||
event->mmap2.min, event->mmap2.ino,
|
||||
event->mmap2.ino_generation,
|
||||
(event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
|
||||
event->mmap2.filename);
|
||||
}
|
||||
|
||||
|
@ -208,10 +208,10 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
|
||||
int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
struct thread_map *threads,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine);
|
||||
struct machine *machine, bool mmap_data);
|
||||
int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine);
|
||||
struct machine *machine, bool mmap_data);
|
||||
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine,
|
||||
|
Loading…
Reference in New Issue
Block a user