diff --git a/src/arch/amd64/loader.S b/src/arch/amd64/loader.S new file mode 100644 index 0000000..db3aac2 --- /dev/null +++ b/src/arch/amd64/loader.S @@ -0,0 +1,43 @@ +/* $Id$ */ +/* Copyright (c) 2021 Pierre Pronchery */ +/* This file is part of DeforaOS System Loader */ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +.section .text +.global loader_enter +.type loader_enter,@function +.type _loader_enter_do,@function +loader_enter: + /* reset the stack */ + xor %rbp, %rbp + + call _loader_enter_do + call _exit + +_loader_enter_do: + jmp *%r8 diff --git a/src/arch/i386/loader.S b/src/arch/i386/loader.S new file mode 100644 index 0000000..1cdd760 --- /dev/null +++ b/src/arch/i386/loader.S @@ -0,0 +1,40 @@ +/* $Id$ */ +/* Copyright (c) 2021 Pierre Pronchery */ +/* This file is part of DeforaOS System Loader */ +/* All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + + + +.section .text +.global loader_enter +.type loader_enter,@function +loader_enter: + /* reset the stack */ + xor %ebp, %ebp + + mov 0x10(%esp), %eax /* entrypoint */ + + jmp *%eax diff --git a/src/loader.c b/src/loader.c index cba9b4c..973d104 100644 --- a/src/loader.c +++ b/src/loader.c @@ -53,10 +53,15 @@ static int _prot(int flags); /* public */ +/* variables */ +extern char ** environ; + + /* functions */ /* loader */ static int _loader_do(int fd, char const * filename, int argc, char * argv[]); -static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr); +static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr, + void ** entrypoint); static size_t _do_phdr_align_bits(unsigned long align); static int _do_shdr(int fd, char const * filename, Elf_Ehdr * ehdr); static int _do_shdr_rela(int fd, char const * filename, Elf_Shdr * shdr, @@ -78,6 +83,7 @@ static int _loader_do(int fd, char const * filename, int argc, char * argv[]) { int ret; Elf_Ehdr ehdr; + void * entrypoint = NULL; if(read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) return _error(2, "%s: %s", filename, strerror(errno)); @@ -90,16 +96,22 @@ static int _loader_do(int fd, char const * filename, int argc, char * argv[]) if(ehdr.e_ehsize != sizeof(ehdr)) return _error(2, "%s: %s", filename, "Invalid or unsupported ELF file"); - if((ret = _do_phdr(fd, filename, &ehdr)) != 0 + if((ret = _do_phdr(fd, filename, &ehdr, &entrypoint)) != 0 || (ret = _do_shdr(fd, filename, &ehdr)) != 0) return ret; + if(entrypoint == NULL) + return _error(2, "%s: %s", filename, "Entrypoint not set"); #ifdef DEBUG - fprintf(stderr, "DEBUG: e_entry=%#lx\n", (unsigned long)ehdr.e_entry); + fprintf(stderr, "DEBUG: loader_enter(%d, %p, %p, %p, %p)\n", + argc, argv, environ, NULL, entrypoint); #endif + ret = loader_enter(argc, argv, environ, NULL, entrypoint); + _exit(ret); return 0; } -static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr) +static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr, + void ** entrypoint) { Elf_Phdr phdr; size_t i; @@ -203,8 +215,18 @@ static int _do_phdr(int fd, char const * filename, Elf_Ehdr * ehdr) return _error(2, "%s: %s", filename, strerror(errno)); } - /* FIXME keep this value */ - phdr.p_vaddr = (intptr_t)addr; + if(prot & PROT_EXEC) + { + *entrypoint = (char *)(ehdr->e_entry - phdr.p_vaddr + + (intptr_t)addr); +#ifdef DEBUG + fprintf(stderr, "DEBUG: e_entry=%#lx p_vaddr=%#lx" + " addr=%p => %p\n", + (unsigned long)ehdr->e_entry, + (unsigned long)phdr.p_vaddr, + addr, *entrypoint); +#endif + } } return 0; } diff --git a/src/loader.h b/src/loader.h index b13d026..aa7b4b4 100644 --- a/src/loader.h +++ b/src/loader.h @@ -36,5 +36,7 @@ /* public */ /* functions */ int loader(char const * filename, int argc, char * argv[]); +int loader_enter(int argc, char * argv[], char ** envp, void * auxv, + void * entrypoint); #endif /* !LOADER_LOADER_H */ diff --git a/src/project.conf b/src/project.conf index cb46950..c72c2ff 100644 --- a/src/project.conf +++ b/src/project.conf @@ -1,4 +1,6 @@ targets=ld.so,ld.so-i386 +as=$(CC) +asflags=$(CPPFLAGSF) $(CPPFLAGS) $(CFLAGSF) $(CFLAGS) -c cppflags_force= cflags_force=-g cflags=-W -Wall -O2 -D_FORTIFY_SOURCE=2 -fstack-protector @@ -49,7 +51,7 @@ cflags_force= #targets [ld.so] type=binary -sources=loader.c,main.c +sources=arch/amd64/loader.S,loader.c,main.c install=$(PREFIX)/libexec [ld.so-arm] @@ -61,7 +63,8 @@ install=$(PREFIX)/libexec [ld.so-i386] type=binary -sources=loader32.c,main32.c +sources=arch/i386/loader.S,loader32.c,main32.c +asflags=-m32 cflags=-m32 ldflags=-m32 install=$(PREFIX)/libexec