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
-#ifndef __LUNAIX_ELF_H
-#define __LUNAIX_ELF_H
+#ifndef __LUNAIX_ELF32_H
+#define __LUNAIX_ELF32_H
#include <lunaix/types.h>
#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];
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 */
#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
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;
};
#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
--- /dev/null
+#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 */
-#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)
{
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, ¶m);
-
- 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;
return status;
}
- return status;
+ return 0;
}
int
}
memset(elf, 0, sizeof(*elf));
+
+ return 0;
}
int
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;
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
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);
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
--- /dev/null
+#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, ¶m);
+
+ 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;
+}
#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
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)
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) {
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;
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,
{
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;
}
// 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
{
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;
}
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);
}
main(int argc, const char* argv[])
{
char* path = ".";
- if (argc > 0) {
- path = argv[0];
+ if (argc > 1) {
+ path = argv[1];
}
DIR* dir = opendir(path);