libexec: mmap support, prealloc variants
Change-Id: I26694fd3c21deb8b97e01ed675dfc14719b0672b
This commit is contained in:
parent
6a2aada8e6
commit
06c61a2de2
|
|
@ -138,7 +138,8 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
|
|||
/* callbacks for use in the kernel */
|
||||
execi.copymem = libexec_copy_memcpy;
|
||||
execi.clearmem = libexec_clear_memset;
|
||||
execi.allocmem_prealloc = libexec_pg_alloc;
|
||||
execi.allocmem_prealloc_cleared = libexec_pg_alloc;
|
||||
execi.allocmem_prealloc_junk = libexec_pg_alloc;
|
||||
execi.allocmem_ondemand = libexec_pg_alloc;
|
||||
execi.clearproc = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -414,7 +414,8 @@ void arch_boot_proc(struct boot_image *ip, struct proc *rp)
|
|||
/* callbacks for use in the kernel */
|
||||
execi.copymem = libexec_copy_memcpy;
|
||||
execi.clearmem = libexec_clear_memset;
|
||||
execi.allocmem_prealloc = libexec_pg_alloc;
|
||||
execi.allocmem_prealloc_junk = libexec_pg_alloc;
|
||||
execi.allocmem_prealloc_cleared = libexec_pg_alloc;
|
||||
execi.allocmem_ondemand = libexec_pg_alloc;
|
||||
execi.clearproc = NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -150,7 +150,8 @@ int libexec_load_elf(struct exec_info *execi)
|
|||
|
||||
assert(execi->copymem);
|
||||
assert(execi->clearmem);
|
||||
assert(execi->allocmem_prealloc);
|
||||
assert(execi->allocmem_prealloc_cleared);
|
||||
assert(execi->allocmem_prealloc_junk);
|
||||
assert(execi->allocmem_ondemand);
|
||||
|
||||
for (i = 0; i < hdr->e_phnum; i++) {
|
||||
|
|
@ -167,51 +168,124 @@ int libexec_load_elf(struct exec_info *execi)
|
|||
for (i = 0; i < hdr->e_phnum; i++) {
|
||||
vir_bytes seg_membytes, page_offset, p_vaddr, vaddr;
|
||||
vir_bytes chunk, vfileend, vmemend;
|
||||
off_t foffset, fbytes;
|
||||
Elf_Phdr *ph = &phdr[i];
|
||||
int try_mmap = 1;
|
||||
u16_t clearend = 0;
|
||||
int pagechunk;
|
||||
int mmap_prot = PROT_READ;
|
||||
|
||||
if(!(ph->p_flags & PF_R)) {
|
||||
printf("libexec: warning: unreadable segment\n");
|
||||
}
|
||||
|
||||
if(ph->p_flags & PF_W) {
|
||||
mmap_prot |= PROT_WRITE;
|
||||
#if ELF_DEBUG
|
||||
printf("libexec: adding PROT_WRITE\n");
|
||||
#endif
|
||||
} else {
|
||||
#if ELF_DEBUG
|
||||
printf("libexec: not adding PROT_WRITE\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ph->p_type != PT_LOAD || ph->p_memsz == 0) continue;
|
||||
|
||||
if((ph->p_vaddr % PAGE_SIZE) != (ph->p_offset % PAGE_SIZE)) {
|
||||
printf("libexec: unaligned ELF program?\n");
|
||||
try_mmap = 0;
|
||||
}
|
||||
|
||||
if(!execi->memmap) {
|
||||
try_mmap = 0;
|
||||
}
|
||||
|
||||
foffset = ph->p_offset;
|
||||
fbytes = ph->p_filesz;
|
||||
vaddr = p_vaddr = ph->p_vaddr + execi->load_offset;
|
||||
seg_membytes = ph->p_memsz;
|
||||
|
||||
page_offset = vaddr % PAGE_SIZE;
|
||||
vaddr -= page_offset;
|
||||
foffset -= page_offset;
|
||||
seg_membytes += page_offset;
|
||||
fbytes += page_offset;
|
||||
vfileend = p_vaddr + ph->p_filesz;
|
||||
|
||||
/* if there's usable memory after the file end, we have
|
||||
* to tell VM to clear the memory part of the page when it's
|
||||
* mapped in
|
||||
*/
|
||||
if((pagechunk = (vfileend % PAGE_SIZE))
|
||||
&& ph->p_filesz < ph->p_memsz) {
|
||||
clearend = PAGE_SIZE - pagechunk;
|
||||
}
|
||||
|
||||
seg_membytes = roundup(seg_membytes, PAGE_SIZE);
|
||||
fbytes = roundup(fbytes, PAGE_SIZE);
|
||||
|
||||
if(first || startv > vaddr) startv = vaddr;
|
||||
first = 0;
|
||||
|
||||
/* make us some memory */
|
||||
if(execi->allocmem_prealloc(execi, vaddr, seg_membytes) != OK) {
|
||||
if(execi->clearproc) execi->clearproc(execi);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if(try_mmap && execi->memmap(execi, vaddr, fbytes, foffset, clearend, mmap_prot) == OK) {
|
||||
#if ELF_DEBUG
|
||||
printf("mmapped 0x%lx-0x%lx\n", vaddr, vaddr+seg_membytes);
|
||||
printf("libexec: mmap 0x%lx-0x%lx done, clearend 0x%x\n",
|
||||
vaddr, vaddr+fbytes, clearend);
|
||||
#endif
|
||||
|
||||
/* Copy executable section into it */
|
||||
if(execi->copymem(execi, ph->p_offset, p_vaddr, ph->p_filesz) != OK) {
|
||||
if(execi->clearproc) execi->clearproc(execi);
|
||||
return ENOMEM;
|
||||
}
|
||||
if(seg_membytes > fbytes) {
|
||||
int rem_mem = seg_membytes - fbytes;;
|
||||
vir_bytes remstart = vaddr + fbytes;
|
||||
if(execi->allocmem_ondemand(execi,
|
||||
remstart, rem_mem) != OK) {
|
||||
printf("libexec: mmap extra mem failed\n");
|
||||
return ENOMEM;
|
||||
}
|
||||
#if ELF_DEBUG
|
||||
else printf("libexec: allocated 0x%lx-0x%lx\n",
|
||||
|
||||
remstart, remstart+rem_mem);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if(try_mmap) printf("libexec: mmap failed\n");
|
||||
|
||||
/* make us some memory */
|
||||
if(execi->allocmem_prealloc_junk(execi, vaddr, seg_membytes) != OK) {
|
||||
if(execi->clearproc) execi->clearproc(execi);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
#if ELF_DEBUG
|
||||
printf("copied 0x%lx-0x%lx\n", p_vaddr, p_vaddr+ph->p_filesz);
|
||||
printf("mmapped 0x%lx-0x%lx\n", vaddr, vaddr+seg_membytes);
|
||||
#endif
|
||||
|
||||
/* Clear remaining bits */
|
||||
vfileend = p_vaddr + ph->p_filesz;
|
||||
vmemend = vaddr + seg_membytes;
|
||||
if((chunk = p_vaddr - vaddr) > 0) {
|
||||
/* Copy executable section into it */
|
||||
if(execi->copymem(execi, ph->p_offset, p_vaddr, ph->p_filesz) != OK) {
|
||||
if(execi->clearproc) execi->clearproc(execi);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
#if ELF_DEBUG
|
||||
printf("start clearing 0x%lx-0x%lx\n", vaddr, vaddr+chunk);
|
||||
printf("copied 0x%lx-0x%lx\n", p_vaddr, p_vaddr+ph->p_filesz);
|
||||
#endif
|
||||
execi->clearmem(execi, vaddr, chunk);
|
||||
}
|
||||
if((chunk = vmemend - vfileend) > 0) {
|
||||
|
||||
/* Clear remaining bits */
|
||||
vmemend = vaddr + seg_membytes;
|
||||
if((chunk = p_vaddr - vaddr) > 0) {
|
||||
#if ELF_DEBUG
|
||||
printf("end clearing 0x%lx-0x%lx\n", vfileend, vaddr+chunk);
|
||||
printf("start clearing 0x%lx-0x%lx\n", vaddr, vaddr+chunk);
|
||||
#endif
|
||||
execi->clearmem(execi, vfileend, chunk);
|
||||
execi->clearmem(execi, vaddr, chunk);
|
||||
}
|
||||
|
||||
if((chunk = vmemend - vfileend) > 0) {
|
||||
#if ELF_DEBUG
|
||||
printf("end clearing 0x%lx-0x%lx\n", vfileend, vaddr+chunk);
|
||||
#endif
|
||||
execi->clearmem(execi, vfileend, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
#include <sys/mman.h>
|
||||
#include <machine/elf.h>
|
||||
|
||||
int libexec_alloc_mmap_prealloc(struct exec_info *execi, off_t vaddr, size_t len)
|
||||
int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, off_t vaddr, size_t len)
|
||||
{
|
||||
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
|
|
@ -29,6 +29,17 @@ int libexec_alloc_mmap_prealloc(struct exec_info *execi, off_t vaddr, size_t len
|
|||
return OK;
|
||||
}
|
||||
|
||||
int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, off_t vaddr, size_t len)
|
||||
{
|
||||
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
|
||||
PROT_READ|PROT_WRITE|PROT_EXEC,
|
||||
MAP_ANON|MAP_PREALLOC|MAP_FIXED, -1, 0) == MAP_FAILED) {
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int libexec_alloc_mmap_ondemand(struct exec_info *execi, off_t vaddr, size_t len)
|
||||
{
|
||||
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ typedef int (*libexec_allocfunc_t)(struct exec_info *execi,
|
|||
|
||||
typedef int (*libexec_procclearfunc_t)(struct exec_info *execi);
|
||||
|
||||
typedef int (*libexec_mmap_t)(struct exec_info *execi,
|
||||
vir_bytes vaddr, vir_bytes len, vir_bytes foffset, u16_t clearend,
|
||||
int protflags);
|
||||
|
||||
struct exec_info {
|
||||
/* Filled in by libexec caller */
|
||||
endpoint_t proc_e; /* Process endpoint */
|
||||
|
|
@ -33,9 +37,11 @@ struct exec_info {
|
|||
/* Callback pointers for use by libexec */
|
||||
libexec_loadfunc_t copymem; /* Copy callback */
|
||||
libexec_clearfunc_t clearmem; /* Clear callback */
|
||||
libexec_allocfunc_t allocmem_prealloc; /* Alloc callback */
|
||||
libexec_allocfunc_t allocmem_prealloc_cleared; /* Alloc callback */
|
||||
libexec_allocfunc_t allocmem_prealloc_junk; /* Alloc callback */
|
||||
libexec_allocfunc_t allocmem_ondemand; /* Alloc callback */
|
||||
libexec_procclearfunc_t clearproc; /* Clear process callback */
|
||||
libexec_mmap_t memmap; /* mmap callback */
|
||||
void *opaque; /* Callback data */
|
||||
|
||||
/* Filled in by libexec load function */
|
||||
|
|
@ -55,7 +61,8 @@ int libexec_load_elf(struct exec_info *execi);
|
|||
|
||||
int libexec_copy_memcpy(struct exec_info *execi, off_t offset, off_t vaddr, size_t len);
|
||||
int libexec_clear_memset(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
int libexec_alloc_mmap_prealloc(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
int libexec_alloc_mmap_ondemand(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
int libexec_clearproc_vm_procctl(struct exec_info *execi);
|
||||
int libexec_clear_sys_memset(struct exec_info *execi, off_t vaddr, size_t len);
|
||||
|
|
|
|||
|
|
@ -133,7 +133,8 @@ static int do_exec(int proc_e, char *exec, size_t exec_len, char *progname,
|
|||
execi.copymem = read_seg;
|
||||
execi.clearproc = libexec_clearproc_vm_procctl;
|
||||
execi.clearmem = libexec_clear_sys_memset;
|
||||
execi.allocmem_prealloc = libexec_alloc_mmap_prealloc;
|
||||
execi.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared;
|
||||
execi.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk;
|
||||
execi.allocmem_ondemand = libexec_alloc_mmap_ondemand;
|
||||
|
||||
for(i = 0; exec_loaders[i].load_object != NULL; i++) {
|
||||
|
|
|
|||
|
|
@ -306,7 +306,8 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
execi.args.copymem = read_seg;
|
||||
execi.args.clearproc = libexec_clearproc_vm_procctl;
|
||||
execi.args.clearmem = libexec_clear_sys_memset;
|
||||
execi.args.allocmem_prealloc = libexec_alloc_mmap_prealloc;
|
||||
execi.args.allocmem_prealloc_cleared = libexec_alloc_mmap_prealloc_cleared;
|
||||
execi.args.allocmem_prealloc_junk = libexec_alloc_mmap_prealloc_junk;
|
||||
execi.args.allocmem_ondemand = libexec_alloc_mmap_ondemand;
|
||||
execi.args.opaque = &execi;
|
||||
|
||||
|
|
|
|||
|
|
@ -287,7 +287,8 @@ void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
|
|||
execi->copymem = libexec_copy_physcopy;
|
||||
execi->clearproc = NULL;
|
||||
execi->clearmem = libexec_clear_sys_memset;
|
||||
execi->allocmem_prealloc = libexec_alloc_vm_prealloc;
|
||||
execi->allocmem_prealloc_junk = libexec_alloc_vm_prealloc;
|
||||
execi->allocmem_prealloc_cleared = libexec_alloc_vm_prealloc;
|
||||
execi->allocmem_ondemand = libexec_alloc_vm_ondemand;
|
||||
|
||||
if(libexec_load_elf(execi) != OK)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user