From 3badc5ac30fcc0836a2604146788158b16b64f2d Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 23 Jul 2022 18:20:06 +0200 Subject: init: compile as an elf --- Makefile | 13 ++++++++++++- initrd/init.elf | 1 + src/kernel/vfs/request.c | 1 + src/user/app/main.c | 20 +++++++++----------- src/user/lib/elfload.c | 1 + src/user/lib/elfload.h | 2 ++ src/user/lib/elfreloc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/user/linker.ld | 10 +--------- src/user_bootstrap/main.c | 2 +- 9 files changed, 70 insertions(+), 22 deletions(-) create mode 120000 initrd/init.elf create mode 100644 src/user/lib/elfreloc.c diff --git a/Makefile b/Makefile index 72e7883..f1b6ce3 100644 --- a/Makefile +++ b/Makefile @@ -67,12 +67,19 @@ out/bootstrap: src/user_bootstrap/linker.ld $(call from_sources, src/user_bootst initrd/test.elf: out/test.elf @# dummy +initrd/init.elf: out/init.elf + @# dummy + out/test.elf: src/usertestelf.ld out/obj/usertestelf.c.o out/obj/user/lib/syscall.s.o $(call from_sources, src/shared/) @mkdir -p $(@D) @$(CC) $(LFLAGS) -Wl,-pie -Wl,-no-dynamic-linker -T $^ -o $@ +out/init.elf: src/user/linker.ld $(call from_sources, src/user/) $(call from_sources, src/shared/) + @mkdir -p $(@D) + @$(CC) $(LFLAGS) -Wl,-pie -Wl,-no-dynamic-linker -T $^ -o $@ + # TODO automatically resolve symlinks -out/initrd.tar: $(shell find initrd/) out/test.elf +out/initrd.tar: $(shell find initrd/) out/test.elf out/init.elf cd initrd; tar chf ../$@ * out/fs/boot/init: out/bootstrap out/initrd.tar @@ -95,6 +102,10 @@ out/obj/%.c.o: src/%.c @mkdir -p $(@D) @$(CC) $(CFLAGS) -c $^ -o $@ +out/obj/user/%.c.o: src/user/%.c + @mkdir -p $(@D) + @$(CC) $(CFLAGS) -fPIE -c $^ -o $@ + out/obj/usertestelf.c.o: src/usertestelf.c @mkdir -p $(@D) @$(CC) $(CFLAGS) -fPIE -c $^ -o $@ diff --git a/initrd/init.elf b/initrd/init.elf new file mode 120000 index 0000000..21a467a --- /dev/null +++ b/initrd/init.elf @@ -0,0 +1 @@ +../out/init.elf \ No newline at end of file diff --git a/src/kernel/vfs/request.c b/src/kernel/vfs/request.c index b056a31..102a7e8 100644 --- a/src/kernel/vfs/request.c +++ b/src/kernel/vfs/request.c @@ -15,6 +15,7 @@ void vfsreq_create(struct vfs_request req_) { req->backend->refcount++; if (req->caller) { + // TODO after running `run_tests` from vga, this is entered with state == PS_WAITS4FS process_transition(req->caller, PS_WAITS4FS); req->caller->waits4fs.req = req; } diff --git a/src/user/app/main.c b/src/user/app/main.c index 6672344..28c4aa0 100644 --- a/src/user/app/main.c +++ b/src/user/app/main.c @@ -1,23 +1,21 @@ +#include +#include +#include +#include #include #include -#include -#include #include +#include +#include #include -#include -#include -#include -extern char _bss_start; // provided by the linker -extern char _bss_end; -extern char _initrd; +// extern char _initrd; void read_file(const char *path, size_t len); __attribute__((section(".text.startup"))) int main(void) { - // allocate bss - _syscall_memflag(&_bss_start, &_bss_end - &_bss_start, MEMFLAG_PRESENT); + elf_selfreloc(); file_reopen(stdout, "/com1", 0); printf("preinit\n"); @@ -30,7 +28,7 @@ int main(void) { } if (!fork2_n_mount("/")) fs_dir_inject("/kdev/"); // TODO should be part of fs_whitelist - MOUNT("/init/", tar_driver(&_initrd)); + // MOUNT("/init/", tar_driver(&_initrd)); MOUNT("/tmp/", tmpfs_drv()); MOUNT("/keyboard", ps2_drv()); MOUNT("/vga_tty", ansiterm_drv()); diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index c32232e..6c75268 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -76,6 +76,7 @@ void elf_exec(void *base) { struct Elf64_Ehdr *ehdr = base; void *exebase; if (!valid_ehdr(ehdr)) return; + _syscall_debug_klog("here", 4); size_t spread = elf_spread(base); switch (ehdr->e_type) { case ET_EXEC: diff --git a/src/user/lib/elfload.h b/src/user/lib/elfload.h index c6afbdd..f79be6e 100644 --- a/src/user/lib/elfload.h +++ b/src/user/lib/elfload.h @@ -3,3 +3,5 @@ void elf_execf(libc_file *f); void elf_exec(void *elf); + +void elf_selfreloc(void); // elfreloc.c diff --git a/src/user/lib/elfreloc.c b/src/user/lib/elfreloc.c new file mode 100644 index 0000000..550fe97 --- /dev/null +++ b/src/user/lib/elfreloc.c @@ -0,0 +1,42 @@ +#include +#include + +__attribute__((visibility("hidden"))) +extern struct Elf64_Dyn _DYNAMIC[]; + +__attribute__((visibility("hidden"))) +extern char _image_base[]; + +static struct Elf64_Dyn *dyn_gettag(Elf64_Xword tag) { + for (size_t i = 0;; i++) { + if (_DYNAMIC[i].d_tag == tag) return &_DYNAMIC[i]; + if (_DYNAMIC[i].d_tag == DT_NULL) return NULL; + } +} + +void elf_selfreloc(void) { + // TODO DT_REL + if (dyn_gettag(DT_PLTGOT) || dyn_gettag(DT_JMPREL)) { + _klogf("elf: unimplemented tag in _DYNAMIC\n"); + } + + struct Elf64_Dyn *rela_tag = dyn_gettag(DT_RELA); + if (rela_tag) { + /* not checking pointer validity, + * crashing on an invalid elf is fine */ + size_t relasz = dyn_gettag(DT_RELASZ)->d_val; + size_t relaent = dyn_gettag(DT_RELAENT)->d_val; + for (size_t o = 0; o < relasz; o += relaent) { + struct Elf64_Rela *r = (void*)_image_base + rela_tag->d_ptr + o; + uintptr_t *target = (void*)_image_base + r->r_offset; + + switch (ELF64_R_TYPE(r->r_info)) { + case R_X86_64_RELATIVE: + *target = (uintptr_t)&_image_base + r->r_addend; + break; + default: + _klogf("elf: unsupported relocation type\n"); + } + } + } +} diff --git a/src/user/linker.ld b/src/user/linker.ld index f2c9d24..fcb5fc8 100644 --- a/src/user/linker.ld +++ b/src/user/linker.ld @@ -1,12 +1,10 @@ ENTRY(main) -OUTPUT_FORMAT("binary") SECTIONS { - . = 2M; + _image_base = .; .text BLOCK(4K) : ALIGN(4K) { - *(.text.startup) *(.text) } .rodata BLOCK(4K) : ALIGN(4K) @@ -17,15 +15,9 @@ SECTIONS { *(.data) } - - _initrd = .; /* is just appended onto the end of the binary */ - . += 2M; - - _bss_start = .; .bss BLOCK(4K) : ALIGN(4K) { *(COMMON) *(.bss) } - _bss_end = .; } diff --git a/src/user_bootstrap/main.c b/src/user_bootstrap/main.c index baa9803..71647c4 100644 --- a/src/user_bootstrap/main.c +++ b/src/user_bootstrap/main.c @@ -51,7 +51,7 @@ __attribute__((section(".text.startup"))) int main(void) { _syscall_memflag(&_bss_start, &_bss_end - &_bss_start, MEMFLAG_PRESENT); - void *init = tar_find(&_initrd, "test.elf"); + void *init = tar_find(&_initrd, "init.elf"); elf_exec(init); _syscall_debug_klog("bootstrap failed", sizeof("bootstrap failed")); -- cgit v1.2.3