support /proc/self/exe (needed for GDB to attach to an existing process)

This commit is contained in:
Balazs Gerofi
2016-01-19 18:22:45 +09:00
parent 172bf0a389
commit fa7a5ccd11
3 changed files with 104 additions and 28 deletions

View File

@ -49,6 +49,9 @@
//static DECLARE_WAIT_QUEUE_HEAD(wq_prepare);
//extern struct mcctrl_channel *channels;
int mcctrl_ikc_set_recv_cpu(ihk_os_t os, int cpu);
extern int procfs_create_entry(void *os, int ref, int osnum, int pid, char *name,
int mode, void *opaque);
extern void procfs_delete_entry(void *os, int osnum, char *fname);
static long mcexec_prepare_image(ihk_os_t os,
struct program_load_desc * __user udesc)
@ -834,6 +837,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
struct mckernel_exec_file *mcef;
struct mckernel_exec_file *mcef_iter;
int retval;
int os_ind = ihk_host_os_get_index(os);
char proc_name[1024];
if (os_ind < 0) {
return EINVAL;
}
file = open_exec(filename);
retval = PTR_ERR(file);
@ -847,6 +856,8 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
goto out_put_file;
}
snprintf(proc_name, 1024, "mcos%d/%d/exe", os_ind, current->tgid);
spin_lock_irq(&mckernel_exec_file_lock);
/* Find previous file (if exists) and drop it */
list_for_each_entry(mcef_iter, &mckernel_exec_files, list) {
@ -855,6 +866,8 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
fput(mcef_iter->fp);
list_del(&mcef_iter->list);
kfree(mcef_iter);
/* Drop old /proc/self/exe */
procfs_delete_entry(os, os_ind, proc_name);
dprintk("%d open_exec dropped previous executable \n", (int)current->tgid);
break;
}
@ -865,6 +878,12 @@ int mcexec_open_exec(ihk_os_t os, char * __user filename)
mcef->pid = current->tgid;
mcef->fp = file;
list_add_tail(&mcef->list, &mckernel_exec_files);
/* Create /proc/self/exe entry */
if (procfs_create_entry(os, 0, os_ind, current->tgid, proc_name,
S_IFLNK, filename) != 0) {
printk("ERROR: could not create a procfs entry for %s.\n", proc_name);
}
spin_unlock(&mckernel_exec_file_lock);
dprintk("%d open_exec and holding file: %s\n", (int)current->tgid, filename);
@ -882,6 +901,12 @@ int mcexec_close_exec(ihk_os_t os)
{
struct mckernel_exec_file *mcef = NULL;
int found = 0;
int os_ind = ihk_host_os_get_index(os);
char proc_name[1024];
if (os_ind < 0) {
return EINVAL;
}
spin_lock_irq(&mckernel_exec_file_lock);
list_for_each_entry(mcef, &mckernel_exec_files, list) {
@ -895,6 +920,15 @@ int mcexec_close_exec(ihk_os_t os)
break;
}
}
/* Remove /proc/self/exe and /proc/self directory
* TODO: instead of removing directory explicitly, detect in procfs_delete_entry()
* when a directory becomes empty and remove it automatically */
snprintf(proc_name, 1024, "mcos%d/%d/exe", os_ind, current->tgid);
procfs_delete_entry(os, os_ind, proc_name);
snprintf(proc_name, 1024, "mcos%d/%d", os_ind, current->tgid);
procfs_delete_entry(os, os_ind, proc_name);
spin_unlock(&mckernel_exec_file_lock);
return (found ? 0 : EINVAL);

View File

@ -83,7 +83,8 @@ static const struct file_operations mckernel_procfs_file_operations = {
*
* \param p a name of the procfs file
* \param osnum os number
* \param mode if zero create a directory otherwise a file
* \param mode if zero create a directory otherwise a file or link
* \param opaque additional context dependent information
*
* return value: NULL: Something wrong has occurred.
* otherwise: address of the proc_dir_entry structure of the procfs file
@ -103,7 +104,7 @@ static const struct file_operations mckernel_procfs_file_operations = {
* ancestor directory which was not explicitly created were racing.
*/
static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int mode)
struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int mode, void *opaque)
{
char *r;
struct proc_dir_entry *pde = NULL;
@ -133,7 +134,7 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m
/* We have non-null parent dir. */
strncpy(name, p, r - p);
name[r - p] = '\0';
parent = get_procfs_list_entry(name, osnum, 0);
parent = get_procfs_list_entry(name, osnum, 0, NULL);
if (parent == NULL) {
/* We counld not get a parent procfs entry. Give up.*/
return NULL;
@ -158,6 +159,8 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m
#else
pde = proc_mkdir_data(name, 0555, parent ? parent->entry : NULL, ret);
#endif
} else if (mode & S_IFLNK) {
pde = proc_symlink(name, parent->entry, (char *)opaque);
} else {
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
pde = create_proc_entry(name, mode, parent->entry);
@ -188,6 +191,36 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m
return ret;
}
/**
* \brief Create procfs create (internal, can be called directly from host Linux).
*
* \param os (opaque) os variable
* \param ref cpuid of the requesting mckernel process
* \param osnum osnum of the requesting mckernel process
* \param pid pid of the requesting mckernel process
* \param name path of the file
* \param mode mode of the file (e.g., dir, link, regular, etc.)
* \param opaque context dependent additional argument
*/
int procfs_create_entry(void *os, int ref, int osnum, int pid, char *name,
int mode, void *opaque)
{
struct procfs_list_entry *e;
e = get_procfs_list_entry(name, osnum, mode, opaque);
if (e == NULL) {
printk("ERROR: could not create a procfs entry for %s.\n", name);
return EINVAL;
}
e->os = os;
e->cpu = ref;
e->pid = pid;
return 0;
}
/**
* \brief Create a procfs entry.
*
@ -200,7 +233,6 @@ static struct procfs_list_entry *get_procfs_list_entry(char *p, int osnum, int m
void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg)
{
struct procfs_list_entry *e;
ihk_device_t dev = ihk_os_to_dev(__os);
unsigned long parg;
struct procfs_file *f;
@ -221,16 +253,12 @@ void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg)
printk("ERROR: procfs_creat: file name not properly terminated.\n");
goto quit;
}
e = get_procfs_list_entry(name, osnum, mode);
if (e == NULL) {
if (procfs_create_entry(__os, ref, osnum, pid, name, mode, NULL) != 0) {
printk("ERROR: could not create a procfs entry for %s.\n", name);
goto quit;
}
e->os = __os;
e->cpu = ref;
e->pid = pid;
quit:
f->status = 1; /* Now the peer can free the data. */
ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file));
@ -239,31 +267,24 @@ quit:
}
/**
* \brief Delete a procfs entry.
* \brief Delete a procfs entry (internal).
*
* \param __os (opaque) os variable
* \param osnum os number
* \param arg sent argument
*/
void procfs_delete(void *__os, int osnum, unsigned long arg)
/* TODO: detect when a directory becomes empty remove it automatically */
void procfs_delete_entry(void *os, int osnum, char *fname)
{
ihk_device_t dev = ihk_os_to_dev(__os);
unsigned long parg;
struct procfs_file *f;
struct procfs_list_entry *e;
struct procfs_list_entry *parent = NULL;
char name[PROCFS_NAME_MAX];
char *r;
unsigned long irqflags;
dprintk("procfs_delete: \n");
parg = ihk_device_map_memory(dev, arg, sizeof(struct procfs_file));
f = ihk_device_map_virtual(dev, parg, sizeof(struct procfs_file), NULL, 0);
dprintk("fname: %s.\n", f->fname);
irqflags = ihk_ikc_spinlock_lock(&procfs_file_list_lock);
list_for_each_entry(e, &procfs_file_list, list) {
if ((strncmp(e->fname, f->fname, PROCFS_NAME_MAX) == 0) &&
if ((strncmp(e->fname, fname, PROCFS_NAME_MAX) == 0) &&
(e->osnum == osnum)) {
list_del(&e->list);
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
@ -272,18 +293,41 @@ void procfs_delete(void *__os, int osnum, unsigned long arg)
#endif
parent = e->parent;
kfree(e);
r = strrchr(f->fname, '/');
r = strrchr(fname, '/');
if (r == NULL) {
strncpy(name, f->fname, PROCFS_NAME_MAX);
strncpy(name, fname, PROCFS_NAME_MAX);
} else {
strncpy(name, r + 1, PROCFS_NAME_MAX);
}
dprintk("found and remove %s from the list.\n", name);
printk("found and remove %s from the list.\n", name);
remove_proc_entry(name, parent->entry);
break;
}
}
ihk_ikc_spinlock_unlock(&procfs_file_list_lock, irqflags);
}
/**
* \brief Delete a procfs entry (internal, can be called directly from host Linux).
*
* \param __os (opaque) os variable
* \param osnum os number
* \param arg sent argument
*/
void procfs_delete(void *__os, int osnum, unsigned long arg)
{
struct procfs_file *f;
ihk_device_t dev = ihk_os_to_dev(__os);
unsigned long parg;
dprintk("procfs_delete: \n");
parg = ihk_device_map_memory(dev, arg, sizeof(struct procfs_file));
f = ihk_device_map_virtual(dev, parg, sizeof(struct procfs_file), NULL, 0);
dprintk("fname: %s.\n", f->fname);
procfs_delete_entry(__os, osnum, f->fname);
f->status = 1; /* Now the peer can free the data. */
ihk_device_unmap_virtual(dev, f, sizeof(struct procfs_file));
ihk_device_unmap_memory(dev, parg, sizeof(struct procfs_file));

View File

@ -146,9 +146,7 @@ void delete_proc_procfs_files(int pid)
snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d/auxv", osnum, pid);
delete_proc_procfs_file(pid, fname);
snprintf(fname, PROCFS_NAME_MAX, "mcos%d/%d", osnum, pid);
delete_proc_procfs_file(pid, fname);
/* NOTE: Directory is removed on the host when mcexec drops the executable */
dprintf("delete procfs files for pid %d: done\n", pid);
}