Em Fri, Jan 27, 2017 at 09:46:55AM -0800, Stephane Eranian escreveu: > On Fri, Jan 27, 2017 at 9:38 AM, Arnaldo Carvalho de Melo > <arnaldo.m...@gmail.com> wrote: > > Em Fri, Jan 27, 2017 at 12:43:05PM -0300, Arnaldo Carvalho de Melo escreveu: > >> Em Fri, Jan 27, 2017 at 02:07:02PM +0100, Peter Zijlstra escreveu: > >> > Something like the (compile tested only) below might be sufficient to > >> > disambiguate things. It would need a corresponding tools/perf patch of > >> > course, but I'm not too familiar with that code anymore. > >> > >> I'm working on patch to do feature test, fallback and handling of the > >> event, etc, will post later. > > > > Just compile tested, need to build a kernel with PeterZ's patch to test, > > feel free to go from there if in a hurry. > > > > > > The place where the map is yanked out of the thread's maps rbtree is at > > > > machine__process_munmap_event() > > > > The rest is making sure the tool works with older kernels, deals with > > endianness in the record in a perf.data file for cross platform > > analysis, hooking it to the various tools where handling this event > > makes sense. > > > At first glance this patch handles the munmap() well. But it will not solve > the case of Andres. Unless you're telling me that the kernel with Peterz's > patch
Nah, I just tried to implement support for the facility PeterZ was proposing for the kernel, not trying to solve Andres, silly me ;-) But then it doesn't even does that well, as it needs to take munmap.len into account, to possibly split the map if they aren't a perfect match (start, len). > will now generate munmap record because of the merging. If not, then the code > handling overlaps needs to change as well as I described in my other Email. Will re-read it, found it confusing at first read :-\ - Arnaldo > > [acme@jouet linux]$ diffstat /tmp/a.patch > > include/uapi/linux/perf_event.h | 14 +++++++++- > > perf/builtin-annotate.c | 1 > > perf/builtin-c2c.c | 1 > > perf/builtin-diff.c | 1 > > perf/builtin-inject.c | 17 +++++++++++- > > perf/builtin-kmem.c | 1 > > perf/builtin-mem.c | 1 > > perf/builtin-record.c | 1 > > perf/builtin-report.c | 1 > > perf/builtin-script.c | 30 ++++++++++++++++++++++ > > perf/builtin-trace.c | 1 > > perf/util/data-convert-bt.c | 1 > > perf/util/event.c | 18 +++++++++++++ > > perf/util/event.h | 10 +++++++ > > perf/util/evsel.c | 12 +++++++- > > perf/util/machine.c | 54 > > ++++++++++++++++++++++++++++++++++++++++ > > perf/util/machine.h | 2 + > > perf/util/python.c | 1 > > perf/util/session.c | 19 ++++++++++++++ > > perf/util/tool.h | 1 > > 20 files changed, 183 insertions(+), 4 deletions(-) > > [acme@jouet linux]$ > > > > diff --git a/tools/include/uapi/linux/perf_event.h > > b/tools/include/uapi/linux/perf_event.h > > index c66a485a24ac..59c5cd5abbbf 100644 > > --- a/tools/include/uapi/linux/perf_event.h > > +++ b/tools/include/uapi/linux/perf_event.h > > @@ -344,7 +344,8 @@ struct perf_event_attr { > > use_clockid : 1, /* use @clockid for > > time fields */ > > context_switch : 1, /* context switch data > > */ > > write_backward : 1, /* Write ring buffer > > from end to beginning */ > > - __reserved_1 : 36; > > + munmap : 1, /* include munmap data > > */ > > + __reserved_1 : 35; > > > > union { > > __u32 wakeup_events; /* wakeup every n events > > */ > > @@ -862,6 +863,17 @@ enum perf_event_type { > > */ > > PERF_RECORD_SWITCH_CPU_WIDE = 15, > > > > + /* > > + * struct { > > + * struct perf_event_header header; > > + * > > + * u64 addr; > > + * u64 len; > > + * struct sample_id sample_id; > > + * }; > > + */ > > + PERF_RECORD_MUNMAP = 16, > > + > > PERF_RECORD_MAX, /* non-ABI */ > > }; > > > > diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c > > index ebb628332a6e..082b5f100ac5 100644 > > --- a/tools/perf/builtin-annotate.c > > +++ b/tools/perf/builtin-annotate.c > > @@ -390,6 +390,7 @@ int cmd_annotate(int argc, const char **argv, const > > char *prefix __maybe_unused) > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c > > index e2b21723bbf8..3e1f1eba77e2 100644 > > --- a/tools/perf/builtin-c2c.c > > +++ b/tools/perf/builtin-c2c.c > > @@ -313,6 +313,7 @@ static struct perf_c2c c2c = { > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c > > index 9ff0db4e2d0c..2c7856848887 100644 > > --- a/tools/perf/builtin-diff.c > > +++ b/tools/perf/builtin-diff.c > > @@ -350,6 +350,7 @@ static struct perf_tool tool = { > > .sample = diff__process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c > > index b9bc7e39833a..4e6103d0c163 100644 > > --- a/tools/perf/builtin-inject.c > > +++ b/tools/perf/builtin-inject.c > > @@ -282,6 +282,19 @@ static int perf_event__repipe_mmap2(struct perf_tool > > *tool, > > return err; > > } > > > > +static int perf_event__repipe_munmap(struct perf_tool *tool, > > + union perf_event *event, > > + struct perf_sample *sample, > > + struct machine *machine) > > +{ > > + int err; > > + > > + err = perf_event__process_munmap(tool, event, sample, machine); > > + perf_event__repipe(tool, event, sample, machine); > > + > > + return err; > > +} > > + > > #ifdef HAVE_JITDUMP > > static int perf_event__jit_repipe_mmap2(struct perf_tool *tool, > > union perf_event *event, > > @@ -569,7 +582,7 @@ static void strip_init(struct perf_inject *inject) > > static bool has_tracking(struct perf_evsel *evsel) > > { > > return evsel->attr.mmap || evsel->attr.mmap2 || evsel->attr.comm || > > - evsel->attr.task; > > + evsel->attr.task || evsel->attr.munmap; > > } > > > > #define COMPAT_MASK (PERF_SAMPLE_ID | PERF_SAMPLE_TID | PERF_SAMPLE_TIME | > > \ > > @@ -632,6 +645,7 @@ static int __cmd_inject(struct perf_inject *inject) > > inject->itrace_synth_opts.set) { > > inject->tool.mmap = perf_event__repipe_mmap; > > inject->tool.mmap2 = perf_event__repipe_mmap2; > > + inject->tool.munmap = perf_event__repipe_munmap; > > inject->tool.fork = perf_event__repipe_fork; > > inject->tool.tracing_data = perf_event__repipe_tracing_data; > > } > > @@ -732,6 +746,7 @@ int cmd_inject(int argc, const char **argv, const char > > *prefix __maybe_unused) > > .sample = perf_event__repipe_sample, > > .mmap = perf_event__repipe, > > .mmap2 = perf_event__repipe, > > + .munmap = perf_event__repipe, > > .comm = perf_event__repipe, > > .fork = perf_event__repipe, > > .exit = perf_event__repipe, > > diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c > > index 29f4751a3574..eb59aa7a0f5b 100644 > > --- a/tools/perf/builtin-kmem.c > > +++ b/tools/perf/builtin-kmem.c > > @@ -964,6 +964,7 @@ static struct perf_tool perf_kmem = { > > .comm = perf_event__process_comm, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .ordered_events = true, > > }; > > > > diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c > > index cd7bc4d104e2..de026e9ef1be 100644 > > --- a/tools/perf/builtin-mem.c > > +++ b/tools/perf/builtin-mem.c > > @@ -338,6 +338,7 @@ int cmd_mem(int argc, const char **argv, const char > > *prefix __maybe_unused) > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .lost = perf_event__process_lost, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c > > index ffac8ca9fb01..f197fc196cd8 100644 > > --- a/tools/perf/builtin-record.c > > +++ b/tools/perf/builtin-record.c > > @@ -1498,6 +1498,7 @@ static struct record record = { > > .comm = perf_event__process_comm, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .ordered_events = true, > > }, > > }; > > diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c > > index dbd7fa028861..96680fbeb664 100644 > > --- a/tools/perf/builtin-report.c > > +++ b/tools/perf/builtin-report.c > > @@ -693,6 +693,7 @@ int cmd_report(int argc, const char **argv, const char > > *prefix __maybe_unused) > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c > > index c0783b4f7b6c..27fcbcb15782 100644 > > --- a/tools/perf/builtin-script.c > > +++ b/tools/perf/builtin-script.c > > @@ -1244,6 +1244,34 @@ static int process_mmap2_event(struct perf_tool > > *tool, > > return 0; > > } > > > > +static int process_munmap_event(struct perf_tool *tool, union perf_event > > *event, > > + struct perf_sample *sample, struct machine > > *machine) > > +{ > > + struct thread *thread; > > + struct perf_script *script = container_of(tool, struct perf_script, > > tool); > > + struct perf_session *session = script->session; > > + struct perf_evsel *evsel = perf_evlist__id2evsel(session->evlist, > > sample->id); > > + > > + if (perf_event__process_munmap(tool, event, sample, machine) < 0) > > + return -1; > > + > > + thread = machine__findnew_thread(machine, sample->pid, sample->tid); > > + if (thread == NULL) { > > + pr_debug("problem processing MUNMAP event, skipping it.\n"); > > + return -1; > > + } > > + > > + if (!evsel->attr.sample_id_all) { > > + pr_debug("MUNMAP event requires attr.sample_id_all, > > skipping it.\n"); > > + return -1; > > + } > > + > > + print_sample_start(sample, thread, evsel); > > + perf_event__fprintf(event, stdout); > > + thread__put(thread); > > + return 0; > > +} > > + > > static int process_switch_event(struct perf_tool *tool, > > union perf_event *event, > > struct perf_sample *sample, > > @@ -1290,6 +1318,7 @@ static int __cmd_script(struct perf_script *script) > > if (script->show_mmap_events) { > > script->tool.mmap = process_mmap_event; > > script->tool.mmap2 = process_mmap2_event; > > + script->tool.munmap = process_munmap_event; > > } > > if (script->show_switch_events) > > script->tool.context_switch = process_switch_event; > > @@ -2096,6 +2125,7 @@ int cmd_script(int argc, const char **argv, const > > char *prefix __maybe_unused) > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c > > index 40ef9b293d1b..cfb7e9e2cd7d 100644 > > --- a/tools/perf/builtin-trace.c > > +++ b/tools/perf/builtin-trace.c > > @@ -2411,6 +2411,7 @@ static int trace__replay(struct trace *trace) > > trace->tool.sample = trace__process_sample; > > trace->tool.mmap = perf_event__process_mmap; > > trace->tool.mmap2 = perf_event__process_mmap2; > > + trace->tool.munmap = perf_event__process_munmap; > > trace->tool.comm = perf_event__process_comm; > > trace->tool.exit = perf_event__process_exit; > > trace->tool.fork = perf_event__process_fork; > > diff --git a/tools/perf/util/data-convert-bt.c > > b/tools/perf/util/data-convert-bt.c > > index 4e6cbc99f08e..8d1feb9fe82d 100644 > > --- a/tools/perf/util/data-convert-bt.c > > +++ b/tools/perf/util/data-convert-bt.c > > @@ -1462,6 +1462,7 @@ int bt_convert__perf2ctf(const char *input, const > > char *path, > > .sample = process_sample_event, > > .mmap = perf_event__process_mmap, > > .mmap2 = perf_event__process_mmap2, > > + .munmap = perf_event__process_munmap, > > .comm = perf_event__process_comm, > > .exit = perf_event__process_exit, > > .fork = perf_event__process_fork, > > diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c > > index 8ab0d7da956b..ffcba9c07c0d 100644 > > --- a/tools/perf/util/event.c > > +++ b/tools/perf/util/event.c > > @@ -18,6 +18,7 @@ static const char *perf_event__names[] = { > > [0] = "TOTAL", > > [PERF_RECORD_MMAP] = "MMAP", > > [PERF_RECORD_MMAP2] = "MMAP2", > > + [PERF_RECORD_MUNMAP] = "MUNMAP", > > [PERF_RECORD_LOST] = "LOST", > > [PERF_RECORD_COMM] = "COMM", > > [PERF_RECORD_EXIT] = "EXIT", > > @@ -1080,6 +1081,12 @@ size_t perf_event__fprintf_mmap2(union perf_event > > *event, FILE *fp) > > event->mmap2.filename); > > } > > > > +size_t perf_event__fprintf_munmap(union perf_event *event, FILE *fp) > > +{ > > + return fprintf(fp, " [%#" PRIx64 ", %" PRIu64 "]\n", > > + event->munmap.start, event->munmap.len); > > +} > > + > > size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp) > > { > > struct thread_map *threads = > > thread_map__new_event(&event->thread_map); > > @@ -1128,6 +1135,14 @@ int perf_event__process_mmap2(struct perf_tool *tool > > __maybe_unused, > > return machine__process_mmap2_event(machine, event, sample); > > } > > > > +int perf_event__process_munmap(struct perf_tool *tool __maybe_unused, > > + union perf_event *event, > > + struct perf_sample *sample, > > + struct machine *machine) > > +{ > > + return machine__process_munmap_event(machine, event, sample); > > +} > > + > > size_t perf_event__fprintf_task(union perf_event *event, FILE *fp) > > { > > return fprintf(fp, "(%d:%d):(%d:%d)\n", > > @@ -1199,6 +1214,9 @@ size_t perf_event__fprintf(union perf_event *event, > > FILE *fp) > > case PERF_RECORD_MMAP2: > > ret += perf_event__fprintf_mmap2(event, fp); > > break; > > + case PERF_RECORD_MUNMAP: > > + ret += perf_event__fprintf_munmap(event, fp); > > + break; > > case PERF_RECORD_AUX: > > ret += perf_event__fprintf_aux(event, fp); > > break; > > diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h > > index c735c53a26f8..00942b6a9d48 100644 > > --- a/tools/perf/util/event.h > > +++ b/tools/perf/util/event.h > > @@ -33,6 +33,12 @@ struct mmap2_event { > > char filename[PATH_MAX]; > > }; > > > > +struct munmap_event { > > + struct perf_event_header header; > > + u64 start; > > + u64 len; > > +}; > > + > > struct comm_event { > > struct perf_event_header header; > > u32 pid, tid; > > @@ -484,6 +490,7 @@ union perf_event { > > struct perf_event_header header; > > struct mmap_event mmap; > > struct mmap2_event mmap2; > > + struct munmap_event munmap; > > struct comm_event comm; > > struct fork_event fork; > > struct lost_event lost; > > @@ -595,6 +602,8 @@ int perf_event__process_mmap2(struct perf_tool *tool, > > union perf_event *event, > > struct perf_sample *sample, > > struct machine *machine); > > +int perf_event__process_munmap(struct perf_tool *tool, union perf_event > > *event, > > + struct perf_sample *sample, struct machine > > *machine); > > int perf_event__process_fork(struct perf_tool *tool, > > union perf_event *event, > > struct perf_sample *sample, > > @@ -647,6 +656,7 @@ int perf_event__synthesize_mmap_events(struct perf_tool > > *tool, > > size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp); > > size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp); > > size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp); > > +size_t perf_event__fprintf_munmap(union perf_event *event, FILE *fp); > > size_t perf_event__fprintf_task(union perf_event *event, FILE *fp); > > size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp); > > size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp); > > diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c > > index 04e536ae4d88..c4b88e4f2422 100644 > > --- a/tools/perf/util/evsel.c > > +++ b/tools/perf/util/evsel.c > > @@ -34,6 +34,7 @@ static struct { > > bool sample_id_all; > > bool exclude_guest; > > bool mmap2; > > + bool munmap; > > bool cloexec; > > bool clockid; > > bool clockid_wrong; > > @@ -930,6 +931,7 @@ void perf_evsel__config(struct perf_evsel *evsel, > > struct record_opts *opts, > > attr->task = track; > > attr->mmap = track; > > attr->mmap2 = track && !perf_missing_features.mmap2; > > + attr->munmap = track && !perf_missing_features.munmap; > > attr->comm = track; > > > > if (opts->record_switch_events) > > @@ -1395,6 +1397,7 @@ int perf_event_attr__fprintf(FILE *fp, struct > > perf_event_attr *attr, > > PRINT_ATTRf(exclude_callchain_kernel, p_unsigned); > > PRINT_ATTRf(exclude_callchain_user, p_unsigned); > > PRINT_ATTRf(mmap2, p_unsigned); > > + PRINT_ATTRf(munmap, p_unsigned); > > PRINT_ATTRf(comm_exec, p_unsigned); > > PRINT_ATTRf(use_clockid, p_unsigned); > > PRINT_ATTRf(context_switch, p_unsigned); > > @@ -1474,6 +1477,8 @@ static int __perf_evsel__open(struct perf_evsel > > *evsel, struct cpu_map *cpus, > > } > > > > fallback_missing_features: > > + if (perf_missing_features.munmap) > > + evsel->attr.munmap = 0; > > if (perf_missing_features.clockid_wrong) > > evsel->attr.clockid = CLOCK_MONOTONIC; /* should always > > work */ > > if (perf_missing_features.clockid) { > > @@ -1603,10 +1608,13 @@ static int __perf_evsel__open(struct perf_evsel > > *evsel, struct cpu_map *cpus, > > goto out_close; > > > > /* > > - * Must probe features in the order they were added to the > > + * Must probe features in the reverse order they were added to the > > * perf_event_attr interface. > > */ > > - if (!perf_missing_features.write_backward && > > evsel->attr.write_backward) { > > + if (!perf_missing_features.munmap && evsel->attr.munmap) { > > + perf_missing_features.munmap = true; > > + goto fallback_missing_features; > > + } else if (!perf_missing_features.write_backward && > > evsel->attr.write_backward) { > > perf_missing_features.write_backward = true; > > goto out_close; > > } else if (!perf_missing_features.clockid_wrong && > > evsel->attr.use_clockid) { > > diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c > > index 747a034d1ff3..24f2f309d70f 100644 > > --- a/tools/perf/util/machine.c > > +++ b/tools/perf/util/machine.c > > @@ -1320,6 +1320,16 @@ static int machine__process_kernel_mmap_event(struct > > machine *machine, > > return -1; > > } > > > > +static int machine__process_kernel_munmap_event(struct machine *machine > > __maybe_unused, > > + union perf_event *event > > __maybe_unused) > > +{ > > + /* > > + * XXX: Fill this in as soon as we get munmap event for kernel > > + * "mmaps", aka module unload > > + */ > > + return 0; > > +} > > + > > int machine__process_mmap2_event(struct machine *machine, > > union perf_event *event, > > struct perf_sample *sample) > > @@ -1379,6 +1389,48 @@ int machine__process_mmap2_event(struct machine > > *machine, > > return 0; > > } > > > > +int machine__process_munmap_event(struct machine *machine, > > + union perf_event *event, > > + struct perf_sample *sample) > > +{ > > + struct thread *thread; > > + struct map *map; > > + enum map_type type = MAP__FUNCTION; > > + int ret = 0; > > + > > + if (dump_trace) > > + perf_event__fprintf_munmap(event, stdout); > > + > > + if (sample->cpumode == PERF_RECORD_MISC_GUEST_KERNEL || > > + sample->cpumode == PERF_RECORD_MISC_KERNEL) { > > + ret = machine__process_kernel_munmap_event(machine, event); > > + if (ret < 0) > > + goto out_problem; > > + return 0; > > + } > > + > > + thread = machine__find_thread(machine, sample->pid, sample->tid); > > + if (thread == NULL) > > + goto out_problem; > > + > > + if (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) > > + type = MAP__VARIABLE; > > + > > + map = map_groups__find(thread->mg, type, event->munmap.start); > > + if (map != NULL) > > + goto out_problem_map; > > + > > + map_groups__remove(thread->mg, map); > > + thread__put(thread); > > + return 0; > > + > > +out_problem_map: > > + thread__put(thread); > > +out_problem: > > + dump_printf("problem processing PERF_RECORD_MUNMAP, skipping > > event.\n"); > > + return 0; > > +} > > + > > int machine__process_mmap_event(struct machine *machine, union perf_event > > *event, > > struct perf_sample *sample) > > { > > @@ -1540,6 +1592,8 @@ int machine__process_event(struct machine *machine, > > union perf_event *event, > > ret = machine__process_mmap_event(machine, event, sample); > > break; > > case PERF_RECORD_MMAP2: > > ret = machine__process_mmap2_event(machine, event, sample); > > break; > > + case PERF_RECORD_MUNMAP: > > + ret = machine__process_munmap_event(machine, event, > > sample); break; > > case PERF_RECORD_FORK: > > ret = machine__process_fork_event(machine, event, sample); > > break; > > case PERF_RECORD_EXIT: > > diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h > > index a28305029711..eabc8b9d8d36 100644 > > --- a/tools/perf/util/machine.h > > +++ b/tools/perf/util/machine.h > > @@ -101,6 +101,8 @@ int machine__process_mmap_event(struct machine > > *machine, union perf_event *event > > struct perf_sample *sample); > > int machine__process_mmap2_event(struct machine *machine, union perf_event > > *event, > > struct perf_sample *sample); > > +int machine__process_munmap_event(struct machine *machine, union > > perf_event *event, > > + struct perf_sample *sample); > > int machine__process_event(struct machine *machine, union perf_event > > *event, > > struct perf_sample *sample); > > > > diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c > > index a5fbc012e3df..047e004dc53f 100644 > > --- a/tools/perf/util/python.c > > +++ b/tools/perf/util/python.c > > @@ -1155,6 +1155,7 @@ static struct { > > PERF_CONST(RECORD_READ), > > PERF_CONST(RECORD_SAMPLE), > > PERF_CONST(RECORD_MMAP2), > > + PERF_CONST(RECORD_MUNMAP), > > PERF_CONST(RECORD_AUX), > > PERF_CONST(RECORD_ITRACE_START), > > PERF_CONST(RECORD_LOST_SAMPLES), > > diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c > > index 349c68144e55..42edd68ce0b8 100644 > > --- a/tools/perf/util/session.c > > +++ b/tools/perf/util/session.c > > @@ -357,6 +357,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) > > tool->mmap = process_event_stub; > > if (tool->mmap2 == NULL) > > tool->mmap2 = process_event_stub; > > + if (tool->munmap == NULL) > > + tool->munmap = process_event_stub; > > if (tool->comm == NULL) > > tool->comm = process_event_stub; > > if (tool->fork == NULL) > > @@ -480,6 +482,20 @@ static void perf_event__mmap2_swap(union perf_event > > *event, > > swap_sample_id_all(event, data); > > } > > } > > + > > +static void perf_event__munmap_swap(union perf_event *event, bool > > sample_id_all) > > +{ > > + event->munmap.start = bswap_64(event->munmap.start); > > + event->munmap.len = bswap_64(event->munmap.len); > > + > > + if (sample_id_all) { > > + void *data = &event->munmap.len; > > + > > + data += sizeof(event->munmap.len); > > + swap_sample_id_all(event, data); > > + } > > +} > > + > > static void perf_event__task_swap(union perf_event *event, bool > > sample_id_all) > > { > > event->fork.pid = bswap_32(event->fork.pid); > > @@ -773,6 +789,7 @@ typedef void (*perf_event__swap_op)(union perf_event > > *event, > > static perf_event__swap_op perf_event__swap_ops[] = { > > [PERF_RECORD_MMAP] = perf_event__mmap_swap, > > [PERF_RECORD_MMAP2] = perf_event__mmap2_swap, > > + [PERF_RECORD_MUNMAP] = perf_event__munmap_swap, > > [PERF_RECORD_COMM] = perf_event__comm_swap, > > [PERF_RECORD_FORK] = perf_event__task_swap, > > [PERF_RECORD_EXIT] = perf_event__task_swap, > > @@ -1237,6 +1254,8 @@ static int machines__deliver_event(struct machines > > *machines, > > if (event->header.misc & > > PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT) > > ++evlist->stats.nr_proc_map_timeout; > > return tool->mmap2(tool, event, sample, machine); > > + case PERF_RECORD_MUNMAP: > > + return tool->munmap(tool, event, sample, machine); > > case PERF_RECORD_COMM: > > return tool->comm(tool, event, sample, machine); > > case PERF_RECORD_FORK: > > diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h > > index ac2590a3de2d..66291063b8b2 100644 > > --- a/tools/perf/util/tool.h > > +++ b/tools/perf/util/tool.h > > @@ -39,6 +39,7 @@ struct perf_tool { > > read; > > event_op mmap, > > mmap2, > > + munmap, > > comm, > > fork, > > exit,