From 35717f62a070cce9df520e810706592849827b85 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Sat, 5 Aug 2023 21:33:19 +1100 Subject: [PATCH] make dynamic linker perform relocs and jump into the main code --- build.py | 8 +- src/include/bin/elf.h | 1 + src/include/cia-mem.h | 16 ++ src/include/linux/fcntl.h | 1 + src/include/linux/sys/mman.h | 1 - src/linux/crt-entry.asm | 36 ----- src/linux/entry.c | 20 +-- src/loader/loader-self-reloc.c | 156 ++++--------------- src/loader/loader.c | 266 ++++++++++++++++++++++++++++++++- src/loader/loader.h | 127 ++++++++++++++++ 10 files changed, 443 insertions(+), 189 deletions(-) delete mode 100644 src/linux/crt-entry.asm create mode 100644 src/loader/loader.h diff --git a/build.py b/build.py index 2c20c26..031ae15 100755 --- a/build.py +++ b/build.py @@ -72,7 +72,7 @@ dependencies.append(args.compiler) includes = ['src/include'] cc = args.compiler cc_defines = [] -cc_flags = ['-nostdlib'] +cc_flags = ['-nostdlib', '-fno-stack-protector', '-mno-sse'] crt_file = 'crt.lib' lib_file = 'cia.lib' dl_file = 'ld-cia.so' @@ -292,9 +292,9 @@ if target == 'linux': print_step(f'Compiling {crt_file}\n') if target == 'linux': - assemble('src/linux/crt-entry.asm', 'bin/crt-entry.o') + # assemble('src/linux/crt-entry.asm', 'bin/crt-entry.o') compile(['src/linux/crt-ctors.c'], 'bin/crt-ctors.o', '-c') - archive(['bin/crt-ctors.o', 'bin/crt-entry.o'], crt_lib) + archive(['bin/crt-ctors.o'], crt_lib) elif target == 'windows': assemble('src/windows/chkstk.asm', 'bin/chkstk.o') compile(['src/windows/crt-entry.c'], 'bin/crt-entry.o', '-c') @@ -306,6 +306,6 @@ archive(['bin/ciabatta.o'], cia_lib) if args.test: if target == 'linux': - compile([args.test, crt_lib, cia_lib], 'a', f'-pie -Wl,-dynamic-linker,{dl_lib}') + compile([args.test, crt_lib, cia_lib], 'a', f'-pie -Wl,-dynamic-linker,{dl_lib} -fno-stack-protector') elif target == 'windows': compile([args.test, crt_lib, cia_lib], 'a.exe', '-lkernel32.lib') diff --git a/src/include/bin/elf.h b/src/include/bin/elf.h index 57261b6..041f7a6 100644 --- a/src/include/bin/elf.h +++ b/src/include/bin/elf.h @@ -286,6 +286,7 @@ typedef i64 Elf64_Sxword; #define SHT_GROUP 17 #define SHT_SYMTAB_SHNDX 18 #define SHT_LOOS 0x60000000 +#define SHT_GNU_HASH 0x6ffffff6 #define SHT_HIOS 0x6fffffff #define SHT_LOPROC 0x70000000 #define SHT_X86_64_UNWIND 0x70000001 diff --git a/src/include/cia-mem.h b/src/include/cia-mem.h index e728a8e..220468c 100644 --- a/src/include/cia-mem.h +++ b/src/include/cia-mem.h @@ -1,6 +1,22 @@ #pragma once +#if !defined(KB) + #define KB ((i64)1024) +#endif + +#if !defined(MB) + #define MB ((i64)1024*KB) +#endif + +#if !defined(GB) + #define GB ((i64)1024*MB) +#endif + +#if !defined(TB) + #define TB ((i64)1024*GB) +#endif + void *cia_ptr_alignf(void *ptr, u64 alignment); void *cia_ptr_alignb(void *ptr, u64 alignment); u64 cia_size_alignf(u64 size, u64 alignment); diff --git a/src/include/linux/fcntl.h b/src/include/linux/fcntl.h index 5360a61..ce21075 100644 --- a/src/include/linux/fcntl.h +++ b/src/include/linux/fcntl.h @@ -15,3 +15,4 @@ #define O_SYNC 04010000 #define O_FSYNC O_SYNC #define O_ASYNC 020000 +#define O_CLOEXEC 02000000 diff --git a/src/include/linux/sys/mman.h b/src/include/linux/sys/mman.h index ebd47a9..52d8cee 100644 --- a/src/include/linux/sys/mman.h +++ b/src/include/linux/sys/mman.h @@ -17,7 +17,6 @@ #define MAP_FIXED 0x10 #define MAP_FILE 0 -#define MAP_ANONYMOUS #define MAP_ANONYMOUS 0x20 #define MAP_ANON MAP_ANONYMOUS #define MAP_HUGE_SHIFT 26 diff --git a/src/linux/crt-entry.asm b/src/linux/crt-entry.asm deleted file mode 100644 index 10641e3..0000000 --- a/src/linux/crt-entry.asm +++ /dev/null @@ -1,36 +0,0 @@ - -bits 64 - -section .text - default rel - global _start - extern __libc_global_fini - extern __libc_global_init - extern __libc_start_main - extern main -_start: - xor ebp, ebp - ;; Save rtld_fini address to r9 - mov r9, rdx - ;; Get argc and argv from the stack - pop rsi - mov rdx, rsp - ;; Align stack to 16, push junk and stack ptr - and rsp, ~0xf - push rax - push rsp - ;; Load fini and init initializers as function parameters - push rbx - lea rbx, [__libc_global_init wrt ..plt] - mov rcx, rbx - lea rbx, [__libc_global_fini wrt ..plt] - mov r8, rbx - lea rbx, [main wrt ..plt] - mov rdi, rbx - pop rbx - ;; Call start main - call __libc_start_main wrt ..plt - ;; No idea why halt it, I guess that's a funny - ;; way to crash your application if the function we called - ;; returns instead of calling the exit syscall - hlt diff --git a/src/linux/entry.c b/src/linux/entry.c index 1adbdcf..fe63f79 100644 --- a/src/linux/entry.c +++ b/src/linux/entry.c @@ -11,23 +11,17 @@ void __stack_chk_fail(void) { sys_exit(1); } +extern int main(int argc, char **argv, char **envp); static void _fileapi_init(); -void __libc_start_main( - int (*main)(int, char**, char**), - int argc, char **argv, - int (*init)(int, char**, char**), - void (*fini)(void), - void (*dl_fini)(void), - void *stack_end -) { +void _start() { // Get the envp - char **envp = argv + (argc + 1); - init(argc, argv, envp); + // char **envp = argv + (argc + 1); + // init(argc, argv, envp); _fileapi_init(); - main(argc, argv, envp); - fini(); + int code = main(0, NULL, NULL); + // fini(); // glibc bug // dl_fini(); - sys_exit(0); + sys_exit(code); } diff --git a/src/loader/loader-self-reloc.c b/src/loader/loader-self-reloc.c index f44547e..1a08821 100644 --- a/src/loader/loader-self-reloc.c +++ b/src/loader/loader-self-reloc.c @@ -17,126 +17,9 @@ #include #include #include +#include "loader.h" -#define AUX_CNT 32 -#define DYN_CNT 37 - -#define _mfence() asm volatile("" ::: "memory") - -static void print_string_n(char *str, u64 len) { - sys_write(STDOUT_FILENO, str, len); -} -static void print_char(char c) { - print_string_n(&c, 1); -} -static void print_string(char *str) { - int str_len = 0; - while(str[str_len] != 0) { - str_len += 1; - } - print_string_n(str, str_len); -} -static void print_int(i64 number) { - if(number < 0) { - print_char('-'); - number = -number; - } - char buf[20]; - buf[19] = 0; - char *p = buf + sizeof buf - 1; - do { - *--p = (number%10) + '0'; - number /= 10; - } while(number > 0); - print_string(p); -} -static void print_uint(u64 number) { - char buf[20]; - buf[19] = 0; - char *p = buf + sizeof buf - 1; - do { - *--p = (number%10) + '0'; - number /= 10; - } while(number > 0); - print_string(p); -} -static void print_hex(u64 number) { - // print_string("0x"); - char digits[] = "0123456789abcdef"; - char buf[20]; - buf[19] = 0; - char *p = buf + sizeof buf - 1; - for(int i = 0; i < 64; i += 4) { - if(i != 0 && i % 16 == 0) { - *--p = '_'; - } - u8 bits = (number >> i) & 0x0f; - char digit = digits[bits]; - *--p = digit; - } - print_string(p); -} -static void printf(char *fmt, ...) { - va_list args; - va_start(args, fmt); - char str_buf[256]; - i64 buf_i = 0; - while(*fmt != 0) { - while(*fmt != '%' && *fmt != 0 && buf_i != sizeof str_buf-1) { - str_buf[buf_i] = *fmt; - buf_i += 1; - fmt++; - } - str_buf[buf_i] = 0; - print_string_n(str_buf, buf_i); - buf_i = 0; - if(*fmt == '%') { - ++fmt; - if(*fmt == 'd') { - i64 number = va_arg(args, i64); - print_int(number); - } - else if(*fmt == 'u') { - u64 number = va_arg(args, u64); - print_uint(number); - } - else if(*fmt == 'x') { - u64 number = va_arg(args, u64); - print_hex(number); - } - else if(*fmt == 's') { - char *str = va_arg(args, char *); - print_string(str); - } - else if(*fmt == 'c') { - int c = va_arg(args, int); - print_char(c); - } - ++fmt; - } - } - va_end(args); -} - -#if defined(_DEBUG) - #define _dbg_print_char(c) print_char(c) - #define _dbg_print_string(s) print_string(s) - #define _dbg_print_string_n(s,n) print_string_n(s,n) - #define _dbg_print_int(d) print_int(d) - #define _dbg_print_uint(u) print_uint(u) - #define _dbg_print_hex(x) print_hex(x) - #define _dbg_printf(fmt, ...) printf(fmt, ##__VA_ARGS__) -#else - #define _dbg_print_char(c) do {} while(0) - #define _dbg_print_string(s) do {} while(0) - #define _dbg_print_string_n(s,n) do {} while(0) - #define _dbg_print_int(d) do {} while(0) - #define _dbg_print_uint(u) do {} while(0) - #define _dbg_print_hex(x) do {} while(0) - #define _dbg_printf(fmt, ...) do {} while(0) -#endif - -extern void loader_entry(u64 *sp, u64 *dyn, u64 *aux); +extern void loader_entry(Loader_Info *ld_info); void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { _dbg_print_string("Entered dynamic loader\n"); @@ -221,13 +104,13 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { u64 offs = rel->r_offset; u32 sym = ELF64_R_SYM(rel->r_info); u32 type = ELF64_R_TYPE(rel->r_info); - _dbg_printf(" rel sym: %d type %d\n", sym, type); + _dbg_printf(" %d @ %d (%d)\n", sym, offs, type); // TODO: if needed rel_offs += rel_ent; } } if(dyn[DT_RELA] != 0) { - _dbg_printf("RELA Relocations found\n"); + _dbg_printf("RELA:\n"); u8 *rela_ents = (void *)(base + dyn[DT_RELA]); u64 rela_ent = dyn[DT_RELAENT]; u64 rela_size = dyn[DT_RELASZ]; @@ -238,16 +121,24 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { u64 addend = rela->r_addend; u32 sym_idx = ELF64_R_SYM(rela->r_info); u32 type = ELF64_R_TYPE(rela->r_info); - _dbg_printf(" rela sym: %x, rela offs: %x, type: %d, addend: %d\n", - sym_idx, reloc_offs, type, addend - ); + _dbg_printf(" %x+%d, @%x (%d)\n", sym_idx, addend, reloc_offs, type); if(type == R_X86_64_GLOB_DAT) { Elf64_Sym *sym = &symtab[sym_idx]; void *sym_addr = (void *)(base + sym->st_value); void **reloc_addr = (void *)(base + reloc_offs); - _dbg_printf(" -> resolving with %x\n", sym_addr); + _dbg_printf(" -> %x\n", sym_addr); *reloc_addr = sym_addr; } + else if(type == R_X86_64_RELATIVE) { + void *addr = (void *)(base + addend); + void **reloc_addr = (void *)(base + reloc_offs); + *reloc_addr = addr; + _dbg_printf(" -> %x\n", addr); + } + else { + printf("ERROR: unhandled relocation type: %d\n", type); + sys_exit(1); + } rela_offs += rela_ent; } } @@ -255,11 +146,12 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { _dbg_printf("PLT relocations found\n"); if(dyn[DT_PLTREL] == DT_REL) { _dbg_printf(" PLT relocations use relocations of type REL\n"); + printf("ERROR: .plt relocations of type REL not implemented\n"); + sys_exit(1); } else if(dyn[DT_PLTREL] == DT_RELA) { _dbg_printf(" PLT relocations use relocations of type RELA\n"); } - _dbg_printf("plt: %x, rela.plt: %x, rela.pltsz: %x\n", dyn[DT_PLTGOT], dyn[DT_JMPREL], dyn[DT_PLTRELSZ]); void *plt = (void *)(base + dyn[DT_PLTGOT]); void *rela_plt = (void *)(base + dyn[DT_JMPREL]); u64 rela_ent = sizeof(Elf64_Rela); @@ -271,9 +163,7 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { u64 addend = rela->r_addend; u32 sym_idx = ELF64_R_SYM(rela->r_info); u32 type = ELF64_R_TYPE(rela->r_info); - _dbg_printf(" rela sym: %x, rela offs: %x, type: %d, addend: %d\n", - sym_idx, reloc_offs, type, addend - ); + _dbg_printf(" %x+%d, @%x (%d)\n", sym_idx, addend, reloc_offs, type); if(type == R_X86_64_JUMP_SLOT) { Elf64_Sym *sym = &symtab[sym_idx]; void *sym_addr = (void *)(base + sym->st_value); @@ -282,13 +172,17 @@ void _dlstart_reloc_c(u64 *sp, Elf64_Dyn *dynv) { *reloc_addr = sym_addr; } rela_offs += rela_ent; - _dbg_printf("%x\n", rela_offs); } } _mfence(); + Loader_Info ld_info; + ld_info.sp = sp; + ld_info.ldso_base = base; + ld_info.dyn = dyn; + ld_info.aux = aux; _dbg_printf("Self-relocation finished. Entering the loader\n"); - loader_entry(sp, dyn, aux); + loader_entry(&ld_info); sys_exit(0); } diff --git a/src/loader/loader.c b/src/loader/loader.c index 2b94eb9..b335753 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -2,18 +2,276 @@ #include #include #include +#include +#include "loader.h" + +#include +#include +#include +#include "../linux/tinyrt-iface.h" +#include +#include "../linux/tinyrt.c" + +#include +#include "../impl/cia-mem/util.c" +#include "../impl/cia-mem/allocator.c" +#include "../impl/cia-mem/arena.c" +#include "../impl/cia-mem/pool.c" struct Elf_Image typedef Elf_Image; struct Elf_Image { + Cia_Arena arena; + char *name; u8 *base; u8 *phdr; u64 ph_num; u64 ph_ent; - char *name; + u8 *shdr; + u64 sh_num; + u64 sh_ent; + u64 *dyn; }; -void loader_entry(u64 *sp, u64 *dynv, u64 *aux) { - char str[] = "Hello world??\n"; - sys_write(STDOUT_FILENO, str, sizeof str); +#define elf_addr(elf, off) (void *)((elf)->base + (u64)off) + +static Cia_Pool image_pool; + +static u32 elf_sym_gnu_hash(char *name) { + unsigned char *s = (void *)name; + u32 h = 5381; + for(int i = 0; s[i] != 0; ++i) { + char c = s[i]; + h = ((h << 5) + h) + c; + } + return h; +} + +static u64 elf_sym_hash(char *name) { + unsigned char *s = (void *)name; + u64 h = 0; + u64 g; + for(int i = 0; s[i] != 0; ++i) { + h = (h<<4) + s[i]; + g = (h & 0xf0000000); + if(g) { + h ^= g >> 24; + } + h &= 0x0fffffff; + } + return h; +} + +static void elf_load(Elf_Image *image, int fd) { + printf("ERROR: image loading from file not implemented\n"); + sys_exit(1); +} + +static Elf64_Sym *elf_symbol_by_name(Elf_Image *image, char *name) { + Elf64_Ehdr *eh = (void *)image->base; + u8 *shdr = elf_addr(image, eh->e_shoff); + u64 sh_num = eh->e_shnum; + u64 sh_ent = eh->e_shentsize; + // Get the GNU symbol hash table + Elf64_Shdr *sh_gnu_hash = NULL; + for(int i = 0; i < sh_num; ++i) { + u64 sh_off = i * sh_ent; + Elf64_Shdr *sh = (void *)(shdr + sh_off); + if(sh->sh_type == SHT_GNU_HASH) { + sh_gnu_hash = sh; + } + } + // Check if we got gnu hash table + _dbg_printf("gnu hash section: %x\n", sh_gnu_hash->sh_addr); + if(sh_gnu_hash != NULL) { + } + return NULL; +} + +void loader_entry(Loader_Info *ld_info) { + _dbg_printf("Loader entry point reached!\n"); + // Get our loader data back + u64 *sp = ld_info->sp; + u8 *ldso_base = ld_info->ldso_base; + u64 *dyn = ld_info->dyn; + u64 *aux = ld_info->aux; + cia_pool_create(&image_pool, cia_allocator_pages(), 1*KB, sizeof(Elf_Image), 0x10); + Elf_Image *ldso = cia_pool_alloc(&image_pool); + Elf_Image *app = cia_pool_alloc(&image_pool); + cia_arena_create(&app->arena, cia_allocator_pages(), 1*MB); + ldso->base = ldso_base; + ldso->dyn = dyn; + // Read ldso elf header + { + Elf64_Ehdr *eh = (void *)ldso->base; + ldso->phdr = elf_addr(ldso, eh->e_phoff); + ldso->ph_num = eh->e_phnum; + ldso->ph_ent = eh->e_phentsize; + ldso->name = "ld-cia.so"; + } + int fd = 0; + app->name = (void *)aux[AT_EXECFN]; + if(aux[AT_PHDR] != (u64)ldso->base) { + _dbg_printf("Linux loaded the image with phdrs at: %x\n", aux[AT_PHDR]); + // Figure out executable base from its phdrs + u8 *phdr = (void *)aux[AT_PHDR]; + u64 ph_ent = aux[AT_PHENT]; + u64 ph_num = aux[AT_PHNUM]; + for(u64 i = 0; i < ph_num; ++i) { + u64 ph_off = i * ph_ent; + Elf64_Phdr *ph = (void *)(phdr + ph_off); + if(ph->p_type == PT_PHDR) { + app->base = (void *)(aux[AT_PHDR] - ph->p_vaddr); + } + } + _dbg_printf("app base: %x\n", app->base); + app->phdr = phdr; + app->ph_ent = ph_ent; + app->ph_num = ph_num; + } + else { + _dbg_printf("Exec filename: %x\n", aux[AT_EXECFN]); + char *filename = (void *)aux[AT_EXECFN]; + app->name = filename; + if(filename == NULL) { + printf("ERROR: no data about the executable to load dynamically\n"); + sys_exit(1); + } + int fd = sys_open(filename, O_CLOEXEC, O_RDWR); + if(fd < 0) { + printf("ERROR: cannot open file %s\n", filename); + sys_exit(1); + } + elf_load(app, fd); + } + if(fd != 0) { + sys_close(fd); + } + // Find .dynamic section + { + u8 *phdr = (void *)aux[AT_PHDR]; + u64 ph_ent = aux[AT_PHENT]; + u64 ph_num = aux[AT_PHNUM]; + Elf64_Phdr *ph_dynamic = NULL; + for(u64 i = 0; i < ph_num; ++i) { + u64 ph_off = i * ph_ent; + Elf64_Phdr *ph = (void *)(phdr + ph_off); + if(ph->p_type == PT_DYNAMIC) { + ph_dynamic = ph; + } + } + // Read and decode dynamic vector + Elf64_Dyn *dynv = elf_addr(app, ph_dynamic->p_vaddr); + u64 dyn[DYN_CNT]; + for(int i = 0; i < DYN_CNT; ++i) { + dyn[i] = 0; + } + for(int i = 0; dynv[i].d_tag != DT_NULL; ++i) { + i64 d_tag = dynv[i].d_tag; + if(d_tag < DYN_CNT) { + dyn[0] |= 1ul << d_tag; + dyn[d_tag] = dynv[i].d_un.d_val; + } + } + app->dyn = &dyn[0]; + } + // Load section headers for app + _dbg_printf("Loading section headers\n"); + { + } + // Relocate app + { + _dbg_printf("Relocating app\n"); + Elf64_Ehdr *eh = (void *)app->base; + // Resolve relocations + Elf64_Sym *symtab = (void *)app->dyn[DT_SYMTAB]; + if(app->dyn[DT_REL] != 0) { + _dbg_printf("REL Relocations found. This part isn't implemented\n"); + u8 *rel_ents = elf_addr(app, app->dyn[DT_REL]); + u64 rel_ent = app->dyn[DT_RELENT]; + u64 rel_size = app->dyn[DT_RELSZ]; + u64 rel_offs = 0; + while(rel_offs < rel_size) { + Elf64_Rel *rel = (void *)(rel_ents + rel_offs); + u64 offs = rel->r_offset; + u32 sym = ELF64_R_SYM(rel->r_info); + u32 type = ELF64_R_TYPE(rel->r_info); + _dbg_printf(" %d @ %d (%d)\n", sym, offs, type); + // TODO: if needed + rel_offs += rel_ent; + } + } + if(app->dyn[DT_RELA] != 0) { + _dbg_printf("RELA:\n"); + u8 *rela_ents = elf_addr(app, app->dyn[DT_RELA]); + u64 rela_ent = app->dyn[DT_RELAENT]; + u64 rela_size = app->dyn[DT_RELASZ]; + u64 rela_offs = 0; + while(rela_offs < rela_size) { + Elf64_Rela *rela = (void *)(rela_ents + rela_offs); + u64 reloc_offs = rela->r_offset; + u64 addend = rela->r_addend; + u32 sym_idx = ELF64_R_SYM(rela->r_info); + u32 type = ELF64_R_TYPE(rela->r_info); + _dbg_printf(" %x+%d, @%x (%d)\n", sym_idx, addend, reloc_offs, type); + if(type == R_X86_64_GLOB_DAT) { + Elf64_Sym *sym = &symtab[sym_idx]; + void *sym_addr = elf_addr(app, sym->st_value); + void **reloc_addr = elf_addr(app, reloc_offs); + *reloc_addr = sym_addr; + _dbg_printf(" -> %x\n", sym_addr); + } + else if(type == R_X86_64_RELATIVE) { + void *addr = elf_addr(app, addend); + void **reloc_addr = elf_addr(app, reloc_offs); + *reloc_addr = addr; + _dbg_printf(" -> %x\n", addr); + } + else { + printf("ERROR: unhandled relocation type: %d\n", type); + sys_exit(1); + } + rela_offs += rela_ent; + } + } + if(app->dyn[DT_PLTGOT] != 0) { + _dbg_printf("PLT relocations found\n"); + if(app->dyn[DT_PLTREL] == DT_REL) { + _dbg_printf(" PLT relocations use relocations of type REL\n"); + printf("ERROR: .plt relocations of type REL not implemented\n"); + sys_exit(1); + } + else if(app->dyn[DT_PLTREL] == DT_RELA) { + _dbg_printf(" PLT relocations use relocations of type RELA\n"); + } + void *plt = elf_addr(app, app->dyn[DT_PLTGOT]); + void *rela_plt = elf_addr(app, app->dyn[DT_JMPREL]); + u64 rela_ent = sizeof(Elf64_Rela); + u64 rela_size = app->dyn[DT_PLTRELSZ]; + u64 rela_offs = 0; + while(rela_offs < rela_size) { + Elf64_Rela *rela = (void *)(rela_plt + rela_offs); + u64 reloc_offs = rela->r_offset; + u64 addend = rela->r_addend; + u32 sym_idx = ELF64_R_SYM(rela->r_info); + u32 type = ELF64_R_TYPE(rela->r_info); + _dbg_printf(" %x+%d, @%x (%d)\n", sym_idx, addend, reloc_offs, type); + if(type == R_X86_64_JUMP_SLOT) { + Elf64_Sym *sym = &symtab[sym_idx]; + void *sym_addr = elf_addr(app, sym->st_value); + void **reloc_addr = elf_addr(app, reloc_offs); + _dbg_printf(" -> resolving with %x\n", sym_addr); + *reloc_addr = sym_addr; + } + rela_offs += rela_ent; + } + } + _dbg_printf("%x\n", 0); + // Get the app main + // Elf64_Sym *app_main = elf_symbol_by_name(app, "main"); + // _dbg_printf("app main: %x\n", app_main); + void (*crt_entry)() = elf_addr(app, eh->e_entry); + _dbg_printf("Exiting the dynamic loader, trying to enter the main app\n"); + crt_entry(); + } sys_exit(0); } diff --git a/src/loader/loader.h b/src/loader/loader.h new file mode 100644 index 0000000..3c4d29b --- /dev/null +++ b/src/loader/loader.h @@ -0,0 +1,127 @@ + +#define AUX_CNT 32 +#define DYN_CNT 37 + +#define _mfence() asm volatile("" ::: "memory") + +struct Loader_Info typedef Loader_Info; +struct Loader_Info { + u64 *sp; + u8 *ldso_base; + u64 *dyn; + u64 *aux; +}; + +static void print_string_n(char *str, u64 len) { + sys_write(STDOUT_FILENO, str, len); +} +static void print_char(char c) { + print_string_n(&c, 1); +} +static void print_string(char *str) { + int str_len = 0; + while(str[str_len] != 0) { + str_len += 1; + } + print_string_n(str, str_len); +} +static void print_int(i64 number) { + if(number < 0) { + print_char('-'); + number = -number; + } + char buf[20]; + buf[19] = 0; + char *p = buf + sizeof buf - 1; + do { + *--p = (number%10) + '0'; + number /= 10; + } while(number > 0); + print_string(p); +} +static void print_uint(u64 number) { + char buf[20]; + buf[19] = 0; + char *p = buf + sizeof buf - 1; + do { + *--p = (number%10) + '0'; + number /= 10; + } while(number > 0); + print_string(p); +} +static void print_hex(u64 number) { + print_string("0x"); + char digits[] = "0123456789abcdef"; + char buf[20]; + buf[19] = 0; + char *p = buf + sizeof buf - 1; + for(int i = 0; i < 64; i += 4) { + // if(i != 0 && i % 16 == 0) { + // *--p = '_'; + // } + u8 bits = (number >> i) & 0x0f; + char digit = digits[bits]; + *--p = digit; + } + print_string(p); +} +static void printf(char *fmt, ...) { + va_list args; + va_start(args, fmt); + char str_buf[256]; + i64 buf_i = 0; + while(*fmt != 0) { + while(*fmt != '%' && *fmt != 0 && buf_i != sizeof str_buf-1) { + str_buf[buf_i] = *fmt; + buf_i += 1; + fmt++; + } + str_buf[buf_i] = 0; + print_string_n(str_buf, buf_i); + buf_i = 0; + if(*fmt == '%') { + ++fmt; + if(*fmt == 'd') { + i64 number = va_arg(args, i64); + print_int(number); + } + else if(*fmt == 'u') { + u64 number = va_arg(args, u64); + print_uint(number); + } + else if(*fmt == 'x') { + u64 number = va_arg(args, u64); + print_hex(number); + } + else if(*fmt == 's') { + char *str = va_arg(args, char *); + print_string(str); + } + else if(*fmt == 'c') { + int c = va_arg(args, int); + print_char(c); + } + ++fmt; + } + } + va_end(args); +} + +#if defined(_DEBUG) + #define _dbg_print_char(c) print_char(c) + #define _dbg_print_string(s) print_string(s) + #define _dbg_print_string_n(s,n) print_string_n(s,n) + #define _dbg_print_int(d) print_int(d) + #define _dbg_print_uint(u) print_uint(u) + #define _dbg_print_hex(x) print_hex(x) + #define _dbg_printf(fmt, ...) printf(fmt, ##__VA_ARGS__) +#else + #define _dbg_print_char(c) do {} while(0) + #define _dbg_print_string(s) do {} while(0) + #define _dbg_print_string_n(s,n) do {} while(0) + #define _dbg_print_int(d) do {} while(0) + #define _dbg_print_uint(u) do {} while(0) + #define _dbg_print_hex(x) do {} while(0) + #define _dbg_printf(fmt, ...) do {} while(0) +#endif +