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]
Message-ID: <20170127173802.GC9082@kernel.org>
Date:   Fri, 27 Jan 2017 14:38:02 -0300
From:   Arnaldo Carvalho de Melo <acme@...nel.org>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     Stephane Eranian <eranian@...gle.com>,
        Andres Freund <andres@...razel.de>,
        Stephane Eranian <eranian@...il.com>,
        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: [PATCH] handle munmap records in tools/perf was: Re: perf/jit
 doesn't cope well with mprotect() to jit containing pages

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.

[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