perf: Pass protection and flags bits through mmap2 interface

The mmap2 interface was missing the protection and flags bits needed to
accurately determine if a mmap memory area was shared or private and
if it was readable or not.

Signed-off-by: Peter Zijlstra <peterz@infradead.org>
[tweaked patch to compile and wrote changelog]
Signed-off-by: Don Zickus <dzickus@redhat.com>
Link: http://lkml.kernel.org/r/1400526833-141779-2-git-send-email-dzickus@redhat.com
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
This commit is contained in:
Peter Zijlstra 2014-05-19 15:13:47 -04:00 committed by Jiri Olsa
parent e646fe730a
commit f972eb63b1
2 changed files with 34 additions and 0 deletions

View file

@ -705,6 +705,7 @@ enum perf_event_type {
* u32 min; * u32 min;
* u64 ino; * u64 ino;
* u64 ino_generation; * u64 ino_generation;
* u32 prot, flags;
* char filename[]; * char filename[];
* struct sample_id sample_id; * struct sample_id sample_id;
* }; * };

View file

@ -40,6 +40,7 @@
#include <linux/mm_types.h> #include <linux/mm_types.h>
#include <linux/cgroup.h> #include <linux/cgroup.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mman.h>
#include "internal.h" #include "internal.h"
@ -5127,6 +5128,7 @@ struct perf_mmap_event {
int maj, min; int maj, min;
u64 ino; u64 ino;
u64 ino_generation; u64 ino_generation;
u32 prot, flags;
struct { struct {
struct perf_event_header header; struct perf_event_header header;
@ -5168,6 +5170,8 @@ static void perf_event_mmap_output(struct perf_event *event,
mmap_event->event_id.header.size += sizeof(mmap_event->min); mmap_event->event_id.header.size += sizeof(mmap_event->min);
mmap_event->event_id.header.size += sizeof(mmap_event->ino); mmap_event->event_id.header.size += sizeof(mmap_event->ino);
mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation); mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation);
mmap_event->event_id.header.size += sizeof(mmap_event->prot);
mmap_event->event_id.header.size += sizeof(mmap_event->flags);
} }
perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); perf_event_header__init_id(&mmap_event->event_id.header, &sample, event);
@ -5186,6 +5190,8 @@ static void perf_event_mmap_output(struct perf_event *event,
perf_output_put(&handle, mmap_event->min); perf_output_put(&handle, mmap_event->min);
perf_output_put(&handle, mmap_event->ino); perf_output_put(&handle, mmap_event->ino);
perf_output_put(&handle, mmap_event->ino_generation); perf_output_put(&handle, mmap_event->ino_generation);
perf_output_put(&handle, mmap_event->prot);
perf_output_put(&handle, mmap_event->flags);
} }
__output_copy(&handle, mmap_event->file_name, __output_copy(&handle, mmap_event->file_name,
@ -5204,6 +5210,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
struct file *file = vma->vm_file; struct file *file = vma->vm_file;
int maj = 0, min = 0; int maj = 0, min = 0;
u64 ino = 0, gen = 0; u64 ino = 0, gen = 0;
u32 prot = 0, flags = 0;
unsigned int size; unsigned int size;
char tmp[16]; char tmp[16];
char *buf = NULL; char *buf = NULL;
@ -5234,6 +5241,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event)
gen = inode->i_generation; gen = inode->i_generation;
maj = MAJOR(dev); maj = MAJOR(dev);
min = MINOR(dev); min = MINOR(dev);
if (vma->vm_flags & VM_READ)
prot |= PROT_READ;
if (vma->vm_flags & VM_WRITE)
prot |= PROT_WRITE;
if (vma->vm_flags & VM_EXEC)
prot |= PROT_EXEC;
if (vma->vm_flags & VM_MAYSHARE)
flags = MAP_SHARED;
else
flags = MAP_PRIVATE;
if (vma->vm_flags & VM_DENYWRITE)
flags |= MAP_DENYWRITE;
if (vma->vm_flags & VM_MAYEXEC)
flags |= MAP_EXECUTABLE;
if (vma->vm_flags & VM_LOCKED)
flags |= MAP_LOCKED;
if (vma->vm_flags & VM_HUGETLB)
flags |= MAP_HUGETLB;
goto got_name; goto got_name;
} else { } else {
name = (char *)arch_vma_name(vma); name = (char *)arch_vma_name(vma);
@ -5274,6 +5303,8 @@ got_name:
mmap_event->min = min; mmap_event->min = min;
mmap_event->ino = ino; mmap_event->ino = ino;
mmap_event->ino_generation = gen; mmap_event->ino_generation = gen;
mmap_event->prot = prot;
mmap_event->flags = flags;
if (!(vma->vm_flags & VM_EXEC)) if (!(vma->vm_flags & VM_EXEC))
mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA; mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA;
@ -5314,6 +5345,8 @@ void perf_event_mmap(struct vm_area_struct *vma)
/* .min (attr_mmap2 only) */ /* .min (attr_mmap2 only) */
/* .ino (attr_mmap2 only) */ /* .ino (attr_mmap2 only) */
/* .ino_generation (attr_mmap2 only) */ /* .ino_generation (attr_mmap2 only) */
/* .prot (attr_mmap2 only) */
/* .flags (attr_mmap2 only) */
}; };
perf_event_mmap_event(&mmap_event); perf_event_mmap_event(&mmap_event);