lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri, 27 Jan 2017 10:10:09 -0800
From:   Stephane Eranian <eranian@...glemail.com>
To:     Arnaldo Carvalho de Melo <arnaldo.melo@...il.com>
Cc:     Peter Zijlstra <peterz@...radead.org>,
        Stephane Eranian <eranian@...gle.com>,
        Andres Freund <andres@...razel.de>,
        LKML <linux-kernel@...r.kernel.org>,
        Jiri Olsa <jolsa@...hat.com>, Ingo Molnar <mingo@...nel.org>,
        Anton Blanchard <anton@...abs.org>,
        Namhyung Kim <namhyung@...nel.org>
Subject: Re: [PATCH] handle munmap records in tools/perf was: Re: perf/jit
 doesn't cope well with mprotect() to jit containing pages

On Fri, Jan 27, 2017 at 10:05 AM, Arnaldo Carvalho de Melo
<arnaldo.melo@...il.com> 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
>> <arnaldo.melo@...il.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).
>
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@...et 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@...et 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,

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ