Serenity Operating System
at master 115 lines 3.3 kB view raw
1/* 2 * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibELF/AuxiliaryVector.h> 8#include <LibELF/DynamicLinker.h> 9#include <LibELF/Relocation.h> 10#include <sys/internals.h> 11#include <unistd.h> 12 13char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds.. 14 15static void init_libc() 16{ 17 environ = __static_environ; 18 __environ_is_malloced = false; 19 __stdio_is_initialized = false; 20 // Initialise the copy of libc included statically in Loader.so, 21 // initialisation of the dynamic libc.so is done by the DynamicLinker 22 __libc_init(); 23} 24 25static void perform_self_relocations(auxv_t* auxvp) 26{ 27 // We need to relocate ourselves. 28 // (these relocations seem to be generated because of our vtables) 29 30 FlatPtr base_address = 0; 31 bool found_base_address = false; 32 for (; auxvp->a_type != AT_NULL; ++auxvp) { 33 if (auxvp->a_type == ELF::AuxiliaryValue::BaseAddress) { 34 base_address = auxvp->a_un.a_val; 35 found_base_address = true; 36 } 37 } 38 VERIFY(found_base_address); 39 if (!ELF::perform_relative_relocations(base_address)) 40 exit(1); 41} 42 43static void display_help() 44{ 45 char const message[] = 46 R"(You have invoked `Loader.so'. This is the helper program for programs that 47use shared libraries. Special directives embedded in executables tell the 48kernel to load this program. 49 50This helper program loads the shared libraries needed by the program, 51prepares the program to run, and runs it. You do not need to invoke 52this helper program directly. 53)"; 54 fprintf(stderr, "%s", message); 55} 56 57extern "C" { 58 59// The compiler expects a previous declaration 60void _start(int, char**, char**) __attribute__((used)); 61void _entry(int, char**, char**) __attribute__((used)); 62 63NAKED void _start(int, char**, char**) 64{ 65#ifdef AK_ARCH_AARCH64 66 asm( 67 "bl _entry\n"); 68#else 69 asm( 70 "push $0\n" 71 "jmp _entry@plt\n"); 72#endif 73} 74 75void _entry(int argc, char** argv, char** envp) 76{ 77 char** env; 78 for (env = envp; *env; ++env) { 79 } 80 81 auxv_t* auxvp = (auxv_t*)++env; 82 perform_self_relocations(auxvp); 83 init_libc(); 84 85 int main_program_fd = -1; 86 DeprecatedString main_program_path; 87 bool is_secure = false; 88 for (; auxvp->a_type != AT_NULL; ++auxvp) { 89 if (auxvp->a_type == ELF::AuxiliaryValue::ExecFileDescriptor) { 90 main_program_fd = auxvp->a_un.a_val; 91 } 92 if (auxvp->a_type == ELF::AuxiliaryValue::ExecFilename) { 93 main_program_path = (char const*)auxvp->a_un.a_ptr; 94 } 95 if (auxvp->a_type == ELF::AuxiliaryValue::Secure) { 96 is_secure = auxvp->a_un.a_val == 1; 97 } 98 } 99 100 if (main_program_path == "/usr/lib/Loader.so"sv) { 101 // We've been invoked directly as an executable rather than as the 102 // ELF interpreter for some other binary. In the future we may want 103 // to support launching a program directly from the dynamic loader 104 // like ld.so on Linux. 105 display_help(); 106 _exit(1); 107 } 108 109 VERIFY(main_program_fd >= 0); 110 VERIFY(!main_program_path.is_empty()); 111 112 ELF::DynamicLinker::linker_main(move(main_program_path), main_program_fd, is_secure, argc, argv, envp); 113 VERIFY_NOT_REACHED(); 114} 115}