Added LIBGTOP_PROC_MAPS: process memory maps.

This commit is contained in:
Martin Baulig
1999-04-03 22:54:00 +00:00
parent 5b946cb261
commit 3ccae8efee
2 changed files with 180 additions and 3 deletions

View File

@@ -43,8 +43,14 @@ static int proc_ctl_handler (ctl_table *table, int *name, int nlen,
size_t newlen, void **context);
static int proc_args_ctl_handler (ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp, void *newval,
size_t newlen, void **context);
void *oldval, size_t *oldlenp,
void *newval, size_t newlen,
void **context);
static int proc_maps_ctl_handler (ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp,
void *newval, size_t newlen,
void **context);
static int libgtop_sysctl_version = 1;
static int libgtop_update_expensive = 5000;
@@ -98,6 +104,8 @@ ctl_table libgtop_table[] = {
sizeof (libgtop_proc_signal), 0444, NULL, NULL, &proc_ctl_handler},
{LIBGTOP_PROC_ARGS, NULL, NULL, 0, 0444, NULL, NULL,
&proc_args_ctl_handler},
{LIBGTOP_PROC_MAPS, NULL, NULL, 0, 0444, NULL, NULL,
&proc_maps_ctl_handler},
{0}
};
@@ -1009,3 +1017,133 @@ proc_args_ctl_handler (ctl_table *table, int *name, int nlen,
free_page (page);
return -EFAULT;
}
static int
proc_maps_ctl_handler (ctl_table *table, int *name, int nlen,
void *oldval, size_t *oldlenp, void *newval,
size_t newlen, void **context)
{
struct task_struct *p = NULL;
struct vm_area_struct * map, * next;
int i, len, len_name, retval = -EINVAL;
libgtop_proc_maps_t *proc_maps;
size_t count, wrote = 0;
loff_t lineno = 0;
int volatile_task;
if (!oldlenp || get_user (len, oldlenp))
return -EFAULT;
if (!name || !nlen || get_user (len_name, name))
return -EFAULT;
if (nlen != 2)
return -EFAULT;
read_lock (&tasklist_lock);
p = find_task_by_pid (name [1]);
/* FIXME!! This should be done after the last use */
read_unlock (&tasklist_lock);
if (!p || !p->mm)
return -ESRCH;
if (len % sizeof (libgtop_proc_maps_t))
return -EINVAL;
count = len / sizeof (libgtop_proc_maps_t);
if (!(proc_maps = kmalloc (sizeof (libgtop_proc_maps_t), GFP_KERNEL)))
return -ENOMEM;
if (!p->mm || p->mm == &init_mm)
goto write_len_out;
/* Check whether the mmaps could change if we sleep */
volatile_task = (p != current || atomic_read (&p->mm->count) > 1);
if (count == 0) {
/* Only get total count. */
for (map = p->mm->mmap, i = 0; map; map = map->vm_next, i++)
continue;
wrote = i;
goto write_len_success;
}
/* quickly go to line lineno */
for (map = p->mm->mmap, i = 0; map && (i < lineno);
map = map->vm_next, i++)
continue;
for ( ; map; map = next) {
memset (proc_maps, 0, sizeof (libgtop_proc_maps_t));
/*
* Get the next vma now (but it won't be used if we sleep).
*/
next = map->vm_next;
proc_maps->header.start = map->vm_start;
proc_maps->header.end = map->vm_end;
proc_maps->header.offset = map->vm_offset;
proc_maps->header.perm = map->vm_flags;
if (map->vm_file != NULL) {
char *line = d_path (map->vm_file->f_dentry, proc_maps->filename,
LIBGTOP_MAP_PATH_LEN);
proc_maps->filename [LIBGTOP_MAP_PATH_LEN-1] = '\0';
proc_maps->header.filename_offset = line - proc_maps->filename;
proc_maps->header.device =
map->vm_file->f_dentry->d_inode->i_dev;
proc_maps->header.inode =
map->vm_file->f_dentry->d_inode->i_ino;
}
/* Copy current entry to user space. */
if (copy_to_user (oldval, proc_maps, sizeof (*proc_maps))) {
retval = -EFAULT;
goto free_page_out;
}
wrote += sizeof (*proc_maps);
oldval += sizeof (*proc_maps);
len -= sizeof (*proc_maps);
count--;
/* If there are no more entries, we don't have to worry about space. */
if (next == NULL)
goto write_len_success;
if (len < sizeof (*proc_maps)) {
retval = -EFAULT;
goto write_len_out;
}
if (count == 0) {
retval = -E2BIG;
goto write_len_out;
}
}
retval = -ENOSYS;
goto free_page_out;
return retval;
write_len_success:
retval = 1;
write_len_out:
if (put_user (wrote, oldlenp)) {
retval = -EFAULT;
goto free_page_out;
}
free_page_out:
kfree (proc_maps);
return retval;
}

View File

@@ -16,7 +16,8 @@ enum {
LIBGTOP_PROC_SEGMENT,
LIBGTOP_PROC_MEM,
LIBGTOP_PROC_SIGNAL,
LIBGTOP_PROC_ARGS
LIBGTOP_PROC_ARGS,
LIBGTOP_PROC_MAPS
};
enum {
@@ -45,6 +46,27 @@ enum {
#define LIBGTOP_TASK_STOPPED 16
#define LIBGTOP_TASK_SWAPPING 32
#define LIBGTOP_VM_READ 0x0001 /* currently active flags */
#define LIBGTOP_VM_WRITE 0x0002
#define LIBGTOP_VM_EXEC 0x0004
#define LIBGTOP_VM_SHARED 0x0008
#define LIBGTOP_VM_MAYREAD 0x0010 /* limits for mprotect() etc */
#define LIBGTOP_VM_MAYWRITE 0x0020
#define LIBGTOP_VM_MAYEXEC 0x0040
#define LIBGTOP_VM_MAYSHARE 0x0080
#define LIBGTOP_VM_GROWSDOWN 0x0100 /* general info on the segment */
#define LIBGTOP_VM_GROWSUP 0x0200
#define LIBGTOP_VM_SHM 0x0400 /* shared memory area, don't swap out */
#define LIBGTOP_VM_DENYWRITE 0x0800 /* ETXTBSY on write attempts.. */
#define LIBGTOP_VM_EXECUTABLE 0x1000
#define LIBGTOP_VM_LOCKED 0x2000
#define LIBGTOP_VM_IO 0x4000 /* Memory mapped I/O or similar */
#define LIBGTOP_MAP_PATH_LEN (PAGE_SIZE - sizeof (libgtop_proc_maps_header_t))
#ifndef min
#define min(a,b) ((a < b) ? a : b)
#endif
@@ -62,6 +84,9 @@ typedef struct libgtop_proc_segment libgtop_proc_segment_t;
typedef struct libgtop_proc_mem libgtop_proc_mem_t;
typedef struct libgtop_proc_signal libgtop_proc_signal_t;
typedef struct libgtop_proc_maps_header libgtop_proc_maps_header_t;
typedef struct libgtop_proc_maps libgtop_proc_maps_t;
struct libgtop_cpu
{
unsigned long total; /* Total CPU Time */
@@ -165,4 +190,18 @@ struct libgtop_proc_signal
unsigned long catch [LIBGTOP_NSIG];
};
struct libgtop_proc_maps_header
{
unsigned long start, end, offset, perm;
off_t filename_offset;
ino_t inode;
dev_t device;
} __attribute__ ((aligned (64)));
struct libgtop_proc_maps
{
libgtop_proc_maps_header_t header;
char filename [LIBGTOP_MAP_PATH_LEN];
};
#endif