refactor: decouple the executable file implementations with execve functionality.
authorMinep <lunaixsky@qq.com>
Sun, 16 Jul 2023 17:20:16 +0000 (18:20 +0100)
committerMinep <lunaixsky@qq.com>
Sun, 16 Jul 2023 17:20:16 +0000 (18:20 +0100)
lunaix-os/config/make-os
lunaix-os/includes/lunaix/exebi/elf32.h [moved from lunaix-os/includes/lunaix/elf.h with 94% similarity]
lunaix-os/includes/lunaix/exec.h
lunaix-os/includes/lunaix/load.h [new file with mode: 0644]
lunaix-os/kernel/exe/elf32/elf32bfmt.c [moved from lunaix-os/kernel/loader/elf.c with 57% similarity]
lunaix-os/kernel/exe/elf32/ldelf32.c [new file with mode: 0644]
lunaix-os/kernel/exe/exec.c [moved from lunaix-os/kernel/loader/exec.c with 70% similarity]
lunaix-os/kernel/proc0.c
lunaix-os/uprog/init.c
lunaix-os/uprog/ls.c

index 5cb285cc963f7946f14c34552c83f3c8c9500b90..fd4908ecd40a4d9f49d131a2dd82005b67f79e1b 100644 (file)
@@ -1,7 +1,7 @@
 OS_ARCH := x86
 OS_NAME := lunaix
 OS_ID := LunaixOS
-OS_VER := dev20230618
+OS_VER := dev$(shell date +%Y%m%d)
 OS_BIN := $(OS_NAME).bin
 OS_ISO := $(OS_NAME).iso
 
similarity index 94%
rename from lunaix-os/includes/lunaix/elf.h
rename to lunaix-os/includes/lunaix/exebi/elf32.h
index cff442c2f806ceee73b793796f57aac26596cb9a..d9f4f58308201141612decf0586bc929d9ad4225 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __LUNAIX_ELF_H
-#define __LUNAIX_ELF_H
+#ifndef __LUNAIX_ELF32_H
+#define __LUNAIX_ELF32_H
 
 #include <lunaix/types.h>
 
@@ -34,6 +34,9 @@ typedef unsigned int elf32_wrd_t;
 #define EI_CLASS 4
 #define EI_DATA 5
 
+#define NO_LOADER 0
+#define DEFAULT_LOADER "usr/ld"
+
 struct elf32_ehdr
 {
     u8_t e_ident[16];
@@ -114,10 +117,7 @@ elf32_read_phdr(struct elf32* elf);
 size_t
 elf32_loadable_memsz(const struct elf32* elf);
 
-int
-elf32_load(struct load_context* ldctx, const struct elf32* elf);
-
 #define SIZE_EHDR sizeof(struct elf32_ehdr)
 #define SIZE_PHDR sizeof(struct elf32_phdr)
 
-#endif /* __LUNAIX_ELF_H */
+#endif /* __LUNAIX_ELF32_H */
index 00f4d398b42fef007760b3257857e9e5a5fc4b6b..2bc0d9439c60ebea89bba40a7c5ac3928ba0c3a5 100644 (file)
@@ -1,14 +1,10 @@
 #ifndef __LUNAIX_EXEC_H
 #define __LUNAIX_EXEC_H
 
-#include <lunaix/elf.h>
 #include <lunaix/fs.h>
 #include <lunaix/process.h>
 #include <lunaix/types.h>
 
-#define NO_LOADER 0
-#define DEFAULT_LOADER "usr/ld"
-
 #define MAX_VAR_PAGES 8
 #define DEFAULT_HEAP_PAGES 16
 
@@ -29,10 +25,14 @@ struct exec_container
     struct proc_info* proc;
     ptr_t vms_mnt;
 
-    struct load_context executable;
+    struct load_context exe;
+
+    // argv prependums
+    char* argv_pp[2];
+    const char** argv;
+    const char** envp;
 
     ptr_t stack_top;
-    ptr_t entry; // mapped to one of {executable|loader}.entry
 
     int status;
 };
@@ -48,19 +48,13 @@ struct uexec_param
 #ifndef __USR_WRAPPER__
 
 int
-exec_load_byname(struct exec_container* container,
-                 const char* filename,
-                 const char** argv,
-                 const char** envp);
+exec_load_byname(struct exec_container* container, const char* filename);
 
 int
-exec_load(struct exec_container* container,
-          struct v_file* executable,
-          const char** argv,
-          const char** envp);
+exec_load(struct exec_container* container, struct v_file* executable);
 
 int
-exec_kexecve(const char* filename, const char* argv[], const char* envp);
+exec_kexecve(const char* filename, const char* argv[], const char* envp[]);
 
 #endif
 
diff --git a/lunaix-os/includes/lunaix/load.h b/lunaix-os/includes/lunaix/load.h
new file mode 100644 (file)
index 0000000..a816491
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_LOAD_H
+#define __LUNAIX_LOAD_H
+
+#include <lunaix/exec.h>
+#include <lunaix/fs.h>
+
+int
+load_executable(struct load_context* context, const struct v_file* exefile);
+
+#endif /* __LUNAIX_LOAD_H */
similarity index 57%
rename from lunaix-os/kernel/loader/elf.c
rename to lunaix-os/kernel/exe/elf32/elf32bfmt.c
index fa6b57676dcd8466d14b02e1be87efde441a8cfc..1079b06f85d12e0437a02b9a13a447bc4ae401b6 100644 (file)
@@ -1,13 +1,11 @@
-#include <klibc/string.h>
 #include <lunaix/common.h>
-#include <lunaix/elf.h>
-#include <lunaix/exec.h>
+#include <lunaix/exebi/elf32.h>
 #include <lunaix/fs.h>
-#include <lunaix/mm/mmap.h>
 #include <lunaix/mm/valloc.h>
-#include <lunaix/mm/vmm.h>
 #include <lunaix/spike.h>
 
+#include <klibc/string.h>
+
 static inline int
 elf32_read(struct v_file* elf, void* data, size_t off, size_t len)
 {
@@ -15,56 +13,10 @@ elf32_read(struct v_file* elf, void* data, size_t off, size_t len)
     return pcache_read(elf->inode, data, len, off);
 }
 
-int
-elf32_map_segment(struct load_context* ldctx,
-                  const struct elf32* elf,
-                  struct elf32_phdr* phdre)
-{
-    struct v_file* elfile = (struct v_file*)elf->elf_file;
-
-    assert(PG_ALIGNED(phdre->p_offset));
-
-    int proct = 0;
-    if ((phdre->p_flags & PF_R)) {
-        proct |= PROT_READ;
-    }
-    if ((phdre->p_flags & PF_W)) {
-        proct |= PROT_WRITE;
-    }
-    if ((phdre->p_flags & PF_X)) {
-        proct |= PROT_EXEC;
-    }
-
-    struct exec_container* container = ldctx->container;
-    struct mmap_param param = { .vms_mnt = container->vms_mnt,
-                                .pvms = &container->proc->mm,
-                                .proct = proct,
-                                .offset = PG_ALIGN(phdre->p_offset),
-                                .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE),
-                                .flen = phdre->p_filesz + PG_MOD(phdre->p_va),
-                                .flags = MAP_FIXED | MAP_PRIVATE,
-                                .type = REGION_TYPE_CODE };
-
-    struct mm_region* seg_reg;
-    int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, &param);
-
-    if (!status) {
-        size_t next_addr = phdre->p_memsz + phdre->p_va;
-        ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE));
-        ldctx->mem_sz += phdre->p_memsz;
-    } else {
-        // we probably fucked up our process
-        terminate_proc(-1);
-    }
-
-    return status;
-}
-
 int
 elf32_open(struct elf32* elf, const char* path)
 {
     struct v_dnode* elfdn;
-    struct v_inode* elfin;
     struct v_file* elffile;
     int error = 0;
 
@@ -96,7 +48,7 @@ elf32_openat(struct elf32* elf, void* elf_vfile)
         return status;
     }
 
-    return status;
+    return 0;
 }
 
 int
@@ -111,6 +63,8 @@ elf32_close(struct elf32* elf)
     }
 
     memset(elf, 0, sizeof(*elf));
+
+    return 0;
 }
 
 int
@@ -156,9 +110,12 @@ elf32_find_loader(const struct elf32* elf, char* path_out, size_t len)
     for (size_t i = 0; i < elf->eheader.e_phnum; i++) {
         struct elf32_phdr* phdre = &elf->pheaders[i];
         if (phdre->p_type == PT_INTERP) {
-            assert_msg(len >= phdre->p_filesz, "path_out: too small");
+            if (len >= phdre->p_filesz) {
+                return EINVAL;
+            }
+
             retval =
-              elf_read(elfile, path_out, phdre->p_offset, phdre->p_filesz);
+              elf32_read(elfile, path_out, phdre->p_offset, phdre->p_filesz);
 
             if (retval < 0) {
                 return retval;
@@ -175,11 +132,8 @@ int
 elf32_read_ehdr(struct elf32* elf)
 {
     struct v_file* elfile = (struct v_file*)elf->elf_file;
-    int status = elf_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR);
 
-    if (status < 0) {
-        return status;
-    }
+    return elf32_read(elfile, (void*)&elf->eheader, 0, SIZE_EHDR);
 }
 
 int
@@ -198,7 +152,7 @@ elf32_read_phdr(struct elf32* elf)
         return ENOMEM;
     }
 
-    status = elf_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz);
+    status = elf32_read(elfile, phdrs, elf->eheader.e_phoff, tbl_sz);
 
     if (status < 0) {
         vfree(phdrs);
@@ -212,36 +166,10 @@ elf32_read_phdr(struct elf32* elf)
 int
 elf32_check_exec(const struct elf32* elf)
 {
-    struct elf32_ehdr* ehdr = elf->pheaders;
+    struct elf32_ehdr* ehdr = &elf->eheader;
 
     return *(u32_t*)(ehdr->e_ident) == ELFMAGIC &&
            ehdr->e_ident[EI_CLASS] == ELFCLASS32 &&
            ehdr->e_ident[EI_DATA] == ELFDATA2LSB && ehdr->e_type == ET_EXEC &&
            ehdr->e_machine == EM_386;
 }
-
-int
-elf32_load(struct load_context* ldctx, const struct elf32* elf)
-{
-    int err = 0;
-
-    struct v_file* elfile = (struct v_file*)elf->elf_file;
-
-    for (size_t i = 0; i < elf->eheader.e_phnum && !err; i++) {
-        struct elf32_phdr* phdr = &elf->pheaders[i];
-
-        if (phdr->p_type == PT_LOAD) {
-            if (phdr->p_align != PG_SIZE) {
-                // surprising alignment!
-                err = ENOEXEC;
-                continue;
-            }
-
-            err = elf_map_segment(ldctx, elf, phdr);
-        }
-        // TODO Handle relocation
-    }
-
-done:
-    return err;
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/exe/elf32/ldelf32.c b/lunaix-os/kernel/exe/elf32/ldelf32.c
new file mode 100644 (file)
index 0000000..1204be4
--- /dev/null
@@ -0,0 +1,123 @@
+#include <lunaix/exebi/elf32.h>
+#include <lunaix/load.h>
+#include <lunaix/mm/mmap.h>
+#include <lunaix/mm/page.h>
+#include <lunaix/spike.h>
+
+int
+elf32_smap(struct load_context* ldctx,
+           const struct elf32* elf,
+           struct elf32_phdr* phdre)
+{
+    struct v_file* elfile = (struct v_file*)elf->elf_file;
+
+    assert(PG_ALIGNED(phdre->p_offset));
+
+    int proct = 0;
+    if ((phdre->p_flags & PF_R)) {
+        proct |= PROT_READ;
+    }
+    if ((phdre->p_flags & PF_W)) {
+        proct |= PROT_WRITE;
+    }
+    if ((phdre->p_flags & PF_X)) {
+        proct |= PROT_EXEC;
+    }
+
+    struct exec_container* container = ldctx->container;
+    struct mmap_param param = { .vms_mnt = container->vms_mnt,
+                                .pvms = &container->proc->mm,
+                                .proct = proct,
+                                .offset = PG_ALIGN(phdre->p_offset),
+                                .mlen = ROUNDUP(phdre->p_memsz, PG_SIZE),
+                                .flen = phdre->p_filesz + PG_MOD(phdre->p_va),
+                                .flags = MAP_FIXED | MAP_PRIVATE,
+                                .type = REGION_TYPE_CODE };
+
+    struct mm_region* seg_reg;
+    int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdre->p_va), elfile, &param);
+
+    if (!status) {
+        size_t next_addr = phdre->p_memsz + phdre->p_va;
+        ldctx->end = MAX(ldctx->end, ROUNDUP(next_addr, PG_SIZE));
+        ldctx->mem_sz += phdre->p_memsz;
+    } else {
+        // we probably fucked up our process
+        terminate_proc(-1);
+    }
+
+    return status;
+}
+
+int
+load_executable(struct load_context* context, const struct v_file* exefile)
+{
+    int errno = 0;
+
+    char* ldpath = NULL;
+    struct elf32 elf;
+    struct exec_container* container = context->container;
+
+    if ((errno = elf32_openat(&elf, exefile))) {
+        goto done;
+    }
+
+    if (!elf32_check_exec(&elf)) {
+        errno = ENOEXEC;
+        goto done;
+    }
+
+    ldpath = valloc(512);
+    errno = elf32_find_loader(&elf, ldpath, 512);
+
+    if (errno < 0) {
+        goto done;
+    }
+
+    if (errno != NO_LOADER) {
+        container->argv_pp[1] = ldpath;
+
+        // close old elf
+        if ((errno = elf32_close(&elf))) {
+            goto done;
+        }
+
+        // open the loader instead
+        if ((errno = elf32_open(&elf, ldpath))) {
+            goto done;
+        }
+
+        // Is this the valid loader?
+        if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf)) {
+            errno = ELIBBAD;
+            goto done_close_elf32;
+        }
+
+        // TODO: relocate loader
+    } else {
+        context->entry = elf.eheader.e_entry;
+    }
+
+    struct v_file* elfile = (struct v_file*)elf.elf_file;
+
+    for (size_t i = 0; i < elf.eheader.e_phnum && !errno; i++) {
+        struct elf32_phdr* phdr = &elf.pheaders[i];
+
+        if (phdr->p_type == PT_LOAD) {
+            if (phdr->p_align != PG_SIZE) {
+                // surprising alignment!
+                errno = ENOEXEC;
+                continue;
+            }
+
+            errno = elf32_smap(context, &elf, phdr);
+        }
+        // TODO Handle relocation
+    }
+
+done_close_elf32:
+    elf32_close(&elf);
+done:
+    vfree_safe(ldpath);
+    return errno;
+}
similarity index 70%
rename from lunaix-os/kernel/loader/exec.c
rename to lunaix-os/kernel/exe/exec.c
index 5024a1d8a1d8bb4368fed28aeecf94c6a54fa675..535f65978af69ade767718c7abc8b3a2f4de9a51 100644 (file)
@@ -1,7 +1,7 @@
 #include <arch/abi.h>
-#include <lunaix/elf.h>
 #include <lunaix/exec.h>
 #include <lunaix/fs.h>
+#include <lunaix/load.h>
 #include <lunaix/mm/mmap.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/mm/vmm.h>
 #include <klibc/string.h>
 
 void
-exec_container(struct exec_container* param, struct proc_info* proc, ptr_t vms)
+exec_container(struct exec_container* param,
+               struct proc_info* proc,
+               ptr_t vms,
+               const char** argv,
+               const char** envp)
 {
     *param = (struct exec_container){ .proc = proc,
                                       .vms_mnt = vms,
-                                      .executable = { .container = param } };
+                                      .exe = { .container = param },
+                                      .argv_pp = { 0, 0 },
+                                      .argv = argv,
+                                      .envp = envp };
 }
 
 size_t
@@ -48,72 +55,28 @@ extern int
 create_heap(struct proc_mm* pvms, ptr_t addr);
 
 int
-exec_load(struct exec_container* container,
-          struct v_file* executable,
-          const char** argv,
-          const char** envp)
+exec_load(struct exec_container* container, struct v_file* executable)
 {
     int errno = 0;
-    char* ldpath = NULL;
 
+    const char **argv = container->argv, **envp = container->envp;
     size_t argv_len, envp_len;
     size_t sz_argv = exec_str_size(argv, &argv_len);
     size_t sz_envp = exec_str_size(envp, &envp_len);
     size_t var_sz = ROUNDUP(sz_envp, PG_SIZE);
+    char** argv_extra = container->argv_pp;
 
-    char* argv_extra[2] = { executable->dnode->name.value, 0 };
+    argv_extra[0] = executable->dnode->name.value;
 
     if (var_sz / PG_SIZE > MAX_VAR_PAGES) {
         errno = E2BIG;
         goto done;
     }
 
-    struct elf32 elf;
-
-    if ((errno = elf32_openat(&elf, executable))) {
-        goto done;
-    }
-
-    if (!elf32_check_exec(&elf)) {
-        errno = ENOEXEC;
-        goto done;
-    }
-
-    ldpath = valloc(512);
-    errno = elf32_find_loader(&elf, ldpath, 512);
-
-    if (errno < 0) {
-        vfree(ldpath);
+    if ((errno = load_executable(&container->exe, executable))) {
         goto done;
     }
 
-    if (errno != NO_LOADER) {
-        // TODO load loader
-        argv_extra[1] = ldpath;
-
-        // close old elf
-        if ((errno = elf32_close(&elf))) {
-            goto done;
-        }
-
-        // open the loader instead
-        if ((errno = elf32_open(&elf, ldpath))) {
-            goto done;
-        }
-
-        // Is this the valid loader?
-        if (!elf32_static_linked(&elf) || !elf32_check_exec(&elf)) {
-            errno = ELIBBAD;
-            goto done_close_elf32;
-        }
-
-        // TODO: relocate loader
-    }
-
-    if ((errno = elf32_load(&container->executable, &elf))) {
-        goto done_close_elf32;
-    }
-
     struct proc_mm* pvms = &container->proc->mm;
 
     // A dedicated place for process variables (e.g. envp)
@@ -134,11 +97,11 @@ exec_load(struct exec_container* container,
     if (!argv_extra[1]) {
         // If loading a statically linked file, then heap remapping we can do,
         // otherwise delayed.
-        create_heap(container->vms_mnt, PG_ALIGN(container->executable.end));
+        create_heap(&container->proc->mm, PG_ALIGN(container->exe.end));
     }
 
     if ((errno = mem_map(&mapped, NULL, UMMAP_END, NULL, &map_vars))) {
-        goto done_close_elf32;
+        goto done;
     }
 
     if (container->vms_mnt == VMS_SELF) {
@@ -190,18 +153,12 @@ exec_load(struct exec_container* container,
         fail("not implemented");
     }
 
-done_close_elf32:
-    elf32_close(&elf);
 done:
-    vfree_safe(ldpath);
     return errno;
 }
 
 int
-exec_load_byname(struct exec_container* container,
-                 const char* filename,
-                 const char** argv,
-                 const char** envp)
+exec_load_byname(struct exec_container* container, const char* filename)
 {
     int errno = 0;
     struct v_dnode* dnode;
@@ -215,26 +172,33 @@ exec_load_byname(struct exec_container* container,
         goto done;
     }
 
-    errno = exec_load(container, file, argv, envp);
+    errno = exec_load(container, file);
 
 done:
     return errno;
 }
 
 int
-exec_kexecve(const char* filename, const char* argv[], const char* envp)
+exec_kexecve(const char* filename, const char* argv[], const char* envp[])
 {
     int errno = 0;
     struct exec_container container;
-    exec_container(&container, __current, VMS_SELF);
+    exec_container(&container, __current, VMS_SELF, argv, envp);
 
-    errno = exec_load_byname(&container, filename, argv, envp);
+    errno = exec_load_byname(&container, filename);
 
     if (errno) {
         return errno;
     }
 
-    j_usr(container.stack_top, container.entry);
+    ptr_t entry = container.exe.entry;
+
+    assert(entry);
+    j_usr(container.stack_top, entry);
+
+    // should not reach
+
+    return errno;
 }
 
 __DEFINE_LXSYSCALL3(int,
@@ -248,9 +212,9 @@ __DEFINE_LXSYSCALL3(int,
 {
     int errno = 0;
     struct exec_container container;
-    exec_container(&container, __current, VMS_SELF);
+    exec_container(&container, __current, VMS_SELF, argv, envp);
 
-    if (!(errno = exec_load_byname(&container, filename, argv, envp))) {
+    if ((errno = exec_load_byname(&container, filename))) {
         goto done;
     }
 
@@ -258,7 +222,7 @@ __DEFINE_LXSYSCALL3(int,
     // return so execve 'will not return' from the perspective of it's invoker
     volatile struct exec_param* execp = __current->intr_ctx.execp;
     execp->esp = container.stack_top;
-    execp->eip = container.entry;
+    execp->eip = container.exe.entry;
 
 done:
     // set return value
index d765691a3d622482076d07c161ca414833639b1c..2029bc593ccf9ccef10f896f4c38beb4464be184 100644 (file)
@@ -68,7 +68,7 @@ exec_initd()
 {
     int errno = 0;
 
-    if (exec_kexecve("/mnt/lunaix-os/usr/init", NULL, NULL)) {
+    if ((errno = exec_kexecve("/mnt/lunaix-os/usr/init", NULL, NULL))) {
         goto fail;
     }
 
index 82e3ea32ec1b694b5e5729baa55e2c210ae94109..b78cd3b360c293a055fbb4db217da3ff2eacfb29 100644 (file)
@@ -28,7 +28,7 @@ main(int argc, const char** argv)
 
     pid_t pid;
     if (!(pid = fork())) {
-        err = execve("/mnt/lunaix-os/usr/sh", NULL, NULL);
+        err = execve("/usr/sh", NULL, NULL);
         printf("fail to execute (%d)\n", errno);
         _exit(err);
     }
index da4cca36de2398879793992438125707f59b6c19..bac3c71eb2541e056fd8561b79e61d8d9ad2c31e 100644 (file)
@@ -6,8 +6,8 @@ int
 main(int argc, const char* argv[])
 {
     char* path = ".";
-    if (argc > 0) {
-        path = argv[0];
+    if (argc > 1) {
+        path = argv[1];
     }
 
     DIR* dir = opendir(path);