feat: heap support and re-worked
[lunaix-os.git] / lunaix-os / kernel / loader / exec.c
index 6c3349537a2a93afbde80689da62dc5a0a2717cc..3c40f6cd227b21e77e52c4c523b7f8de8fd72c8b 100644 (file)
@@ -27,6 +27,36 @@ exec_str_size(const char** str_arr, size_t* length)
     return sz + 1;
 }
 
     return sz + 1;
 }
 
+void
+__heap_copied(struct mm_region* region)
+{
+    mm_index((void**)&region->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,
 int
 exec_loadto(struct ld_param* param,
             struct v_file* executable,
@@ -49,44 +79,50 @@ exec_loadto(struct ld_param* param,
         goto done;
     }
 
         goto done;
     }
 
-    struct mmap_param map_param = { .regions = &param->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 = &param->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 = &param->proc->intr_ctx;
 
 
     void* mapped;
     isr_param* intr_ctx = &param->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 (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;
         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");
     }
 
     } 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;
 
 done:
     return errno;