diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/elf.c | 8 | ||||
| -rw-r--r-- | common/proc.c | 2 | ||||
| -rw-r--r-- | common/timer.c | 2 | ||||
| -rw-r--r-- | common/uapi/proc.c | 31 | ||||
| -rw-r--r-- | common/vmem.c | 17 |
5 files changed, 50 insertions, 10 deletions
diff --git a/common/elf.c b/common/elf.c index 97d8fd7..b88be89 100644 --- a/common/elf.c +++ b/common/elf.c @@ -76,7 +76,7 @@ static vm_t __map_dyn(struct tcb *t, vm_t bin, uint8_t ei_c, vm_t phstart, * hacky, I know.*/ } -static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) +static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf, vm_t interp) { short e_type = elf_header_prop(ei_c, elf, e_type); if (e_type != ET_DYN && e_type != ET_EXEC) @@ -97,9 +97,9 @@ static vm_t __prepare_proc(struct tcb *t, uint8_t ei_c, vm_t elf) } /* sets up all memory regions etc, returns the entry address */ -vm_t load_elf(struct tcb *t, vm_t b) +vm_t load_elf(struct tcb *t, vm_t elf, vm_t interp) { - struct elf_ident *i = (struct elf_ident *)b; + struct elf_ident *i = (struct elf_ident *)elf; if (i->ei_magic != cpu_to_be32(EI_MAGIC)) return 0; @@ -107,5 +107,5 @@ vm_t load_elf(struct tcb *t, vm_t b) return 0; /* more sanity checks? */ - return __prepare_proc(t, i->ei_class, b); + return __prepare_proc(t, i->ei_class, elf, interp); } diff --git a/common/proc.c b/common/proc.c index e88d37d..f09e7c1 100644 --- a/common/proc.c +++ b/common/proc.c @@ -45,7 +45,7 @@ stat_t init_proc(void *fdt, struct vmem *b) /* TODO: this stuff should be placed in __sys_exec */ /* the binary gets to choose first what memory regions it requires */ - t->entry = load_elf(t, get_init_base(fdt)); + t->entry = load_elf(t, get_init_base(fdt), 0); if (!t->entry) return ERR_ADDR; diff --git a/common/timer.c b/common/timer.c index f36c90d..dadb88d 100644 --- a/common/timer.c +++ b/common/timer.c @@ -136,7 +136,7 @@ struct timer *find_timer(id_t cid) stat_t remove_timer(struct timer *t) { if (!t) - return; + return ERR_INVAL; struct sp_node *n = &timer_node_container(t)->sp_n; sp_remove(&sp_root(__cpu_timers()), n); diff --git a/common/uapi/proc.c b/common/uapi/proc.c index e36c62e..3f715af 100644 --- a/common/uapi/proc.c +++ b/common/uapi/proc.c @@ -4,6 +4,8 @@ */ #include <apos/uapi.h> +#include <apos/bits.h> +#include <apos/mem_regions.h> SYSCALL_DEFINE0(create)(){ return (struct sys_ret){ OK, 0 }; @@ -23,8 +25,35 @@ SYSCALL_DEFINE0(fork)(){ return (struct sys_ret){ OK, 0 }; } -SYSCALL_DEFINE3(exec)(sys_arg_t bin, sys_arg_t argc, sys_arg_t argv){ +SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){ /* TODO: execute new process, probably with more sensible argc passing */ + struct tcb *r = cur_tcb(); + + /* mark binary to be kept */ + struct mem_region *b = find_used_region(&r->sp_r, bin); + if (!b) + return (struct sys_ret){ERR_INVAL, 0}; + __set_bit(b->flags, MR_KEEP); + + struct mem_region *i = 0; + if (interp) { + /* mark interpreter to be kept */ + i = find_used_region(&r->sp_r, interp); + if (!i) + return (struct sys_ret){ERR_INVAL, 1}; + __set_bit(i->flags, MR_KEEP); + } + + /* free everything except regions to be kept */ + clear_uvmem(r, false); + + /* restore to normal */ + __clear_bit(b->flags, MR_KEEP); + if (interp) + __clear_bit(b->flags, MR_KEEP); + + /* TODO: set entry? */ + load_elf(r, b, i); return (struct sys_ret){ OK, 0 }; } diff --git a/common/vmem.c b/common/vmem.c index ae40748..3ea9ed7 100644 --- a/common/vmem.c +++ b/common/vmem.c @@ -25,15 +25,26 @@ static stat_t __free_mapped_region(struct tcb *t, struct mem_region *m) return status; } -stat_t destroy_uvmem(struct tcb *t) +stat_t clear_uvmem(struct tcb *t, bool force) { struct mem_region *m = find_first_region(&t->sp_r); while (m) { - /* free all memory associated with used regions */ - if (is_region_used(m)) + /* if force is not set, free only regions that are not marked to + * be kept and are owned. + * + * if force is set, free all owned regions. + */ + if (is_region_owned(m) && (force || !is_region_kept(m))) __free_mapped_region(t, m); } + return OK; +} + +stat_t destroy_uvmem(struct tcb *t) +{ + /* force clear all regions */ + clear_uvmem(t, true); /* destroy region tree itself */ return destroy_region(&t->sp_r); } |
