return sz + 1;
}
+void
+__heap_copied(struct mm_region* region)
+{
+ mm_index((void**)®ion->proc_vms->heap, region);
+}
+
+int
+__exec_remap_heap(struct ld_param* param, struct proc_mm* pvms)
+{
+ if (pvms->heap) {
+ mem_unmap_region(param->vms_mnt, pvms->heap);
+ }
+
+ struct mmap_param map_param = { .pvms = pvms,
+ .vms_mnt = param->vms_mnt,
+ .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
+ .type = REGION_TYPE_HEAP,
+ .proct = PROT_READ | PROT_WRITE,
+ .mlen = DEFAULT_HEAP_PAGES * PG_SIZE };
+ int status = 0;
+ struct mm_region* heap;
+ if ((status = mem_map(NULL, &heap, param->info.end, NULL, &map_param))) {
+ param->status |= LD_STAT_FKUP;
+ return status;
+ }
+
+ heap->region_copied = __heap_copied;
+ mm_index((void**)&pvms->heap, heap);
+}
+
int
exec_loadto(struct ld_param* param,
struct v_file* executable,
goto done;
}
- struct mmap_param map_param = { .regions = ¶m->proc->mm.regions,
- .vms_mnt = param->vms_mnt,
- .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
- .type = REGION_TYPE_VARS,
- .proct = PROT_READ,
- .length = MAX_VAR_PAGES * PG_SIZE };
+ struct proc_mm* pvms = ¶m->proc->mm;
+ struct mmap_param map_vars = { .pvms = pvms,
+ .vms_mnt = param->vms_mnt,
+ .flags = MAP_ANON | MAP_PRIVATE | MAP_FIXED,
+ .type = REGION_TYPE_VARS,
+ .proct = PROT_READ,
+ .mlen = MAX_VAR_PAGES * PG_SIZE };
void* mapped;
isr_param* intr_ctx = ¶m->proc->intr_ctx;
- // TODO reinitialize heap
+ if ((errno = __exec_remap_heap(param, pvms))) {
+ goto done;
+ }
+
+ if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) {
+ goto done;
+ }
if (param->vms_mnt == VMS_SELF) {
// we are loading executable into current addr space
- if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_param))) {
- goto done;
- }
-
- memcpy(mapped, (void*)argv, sz_argv);
- memcpy(mapped + sz_argv, (void*)envp, sz_envp);
-
- ptr_t* ustack = (void*)USTACK_TOP;
- size_t* argc = &((size_t*)&ustack[-1])[-1];
+ // make some handy infos available to user space
+ ptr_t arg_start = mapped + sizeof(struct usr_exec_param);
+ memcpy(arg_start, (void*)argv, sz_argv);
+ memcpy(arg_start + sz_argv, (void*)envp, sz_envp);
+
+ struct usr_exec_param* param = mapped;
+ *param = (struct usr_exec_param){ .argc = argv_len,
+ .argv = arg_start,
+ .envc = envp_len,
+ .envp = arg_start + sz_argv,
+ .info = param->info };
+ ptr_t* ustack = (ptr_t*)USTACK_TOP;
ustack[-1] = (ptr_t)mapped;
- *argc = argv_len;
-
- // TODO handle envp.
-
- intr_ctx->esp = argc;
+ intr_ctx->esp = &ustack[-1];
} else {
// TODO need to find a way to inject argv and envp remotely
fail("not implemented");
}
- intr_ctx->eip = param->ehdr_out.e_entry;
- // we will jump to new entry point upon syscall's return
- // so execve will not return from the perspective of it's invoker
+ intr_ctx->eip = param->info.ehdr_out.e_entry;
+ // we will jump to new entry point (_u_start) upon syscall's
+ // return so execve 'will not return' from the perspective of it's invoker
done:
return errno;