From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932569AbdA0SKS (ORCPT ); Fri, 27 Jan 2017 13:10:18 -0500 Received: from mail-ot0-f193.google.com ([74.125.82.193]:35276 "EHLO mail-ot0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754249AbdA0SKL (ORCPT ); Fri, 27 Jan 2017 13:10:11 -0500 MIME-Version: 1.0 Reply-To: eranian@gmail.com In-Reply-To: <20170127180531.GD9082@kernel.org> References: <20170126221912.GF6515@twins.programming.kicks-ass.net> <20170126223820.t2564ltcu3cjmt3p@alap3.anarazel.de> <20170126230956.srv2wtlwhwihgn32@alap3.anarazel.de> <20170127130702.GI6515@twins.programming.kicks-ass.net> <20170127154304.GB9082@kernel.org> <20170127173802.GC9082@kernel.org> <20170127180531.GD9082@kernel.org> From: Stephane Eranian Date: Fri, 27 Jan 2017 10:10:09 -0800 Message-ID: Subject: Re: [PATCH] handle munmap records in tools/perf was: Re: perf/jit doesn't cope well with mprotect() to jit containing pages To: Arnaldo Carvalho de Melo Cc: Peter Zijlstra , Stephane Eranian , Andres Freund , LKML , Jiri Olsa , Ingo Molnar , Anton Blanchard , Namhyung Kim Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Jan 27, 2017 at 10:05 AM, Arnaldo Carvalho de Melo wrote: > 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 >> 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). > Ah, yes, that's correct. You need to consider len and possibly split the maps you have. >> 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 :-\ > Took me some time to understand his test case as well. But the key point is the fact that anon cannot overlap a non-anon map without a prior munmap() anymore. > - 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,