main.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /*
  2. * Copyright (c) 2020, Itamar S. <itamar8910@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibC/sys/internals.h>
  7. #include <LibC/unistd.h>
  8. #include <LibELF/AuxiliaryVector.h>
  9. #include <LibELF/DynamicLinker.h>
  10. char* __static_environ[] = { nullptr }; // We don't get the environment without some libc workarounds..
  11. static void init_libc()
  12. {
  13. environ = __static_environ;
  14. __environ_is_malloced = false;
  15. __stdio_is_initialized = false;
  16. // Initialise the copy of libc included statically in Loader.so,
  17. // initialisation of the dynamic libc.so is done by the DynamicLinker
  18. __libc_init();
  19. }
  20. static void perform_self_relocations(auxv_t* auxvp)
  21. {
  22. // We need to relocate ourselves.
  23. // (these relocations seem to be generated because of our vtables)
  24. FlatPtr base_address = 0;
  25. bool found_base_address = false;
  26. for (; auxvp->a_type != AT_NULL; ++auxvp) {
  27. if (auxvp->a_type == ELF::AuxiliaryValue::BaseAddress) {
  28. base_address = auxvp->a_un.a_val;
  29. found_base_address = true;
  30. }
  31. }
  32. VERIFY(found_base_address);
  33. Elf32_Ehdr* header = (Elf32_Ehdr*)(base_address);
  34. Elf32_Phdr* pheader = (Elf32_Phdr*)(base_address + header->e_phoff);
  35. u32 dynamic_section_addr = 0;
  36. for (size_t i = 0; i < (size_t)header->e_phnum; ++i, ++pheader) {
  37. if (pheader->p_type != PT_DYNAMIC)
  38. continue;
  39. dynamic_section_addr = pheader->p_vaddr + base_address;
  40. }
  41. if (!dynamic_section_addr)
  42. exit(1);
  43. auto dynamic_object = ELF::DynamicObject::create({}, (VirtualAddress(base_address)), (VirtualAddress(dynamic_section_addr)));
  44. dynamic_object->relocation_section().for_each_relocation([base_address](auto& reloc) {
  45. if (reloc.type() != R_386_RELATIVE)
  46. return IterationDecision::Continue;
  47. *(u32*)reloc.address().as_ptr() += base_address;
  48. return IterationDecision::Continue;
  49. });
  50. }
  51. static void display_help()
  52. {
  53. const char message[] =
  54. R"(You have invoked `Loader.so'. This is the helper program for programs that
  55. use shared libraries. Special directives embedded in executables tell the
  56. kernel to load this program.
  57. This helper program loads the shared libraries needed by the program,
  58. prepares the program to run, and runs it. You do not need to invoke
  59. this helper program directly.
  60. )";
  61. fprintf(stderr, "%s", message);
  62. }
  63. extern "C" {
  64. // The compiler expects a previous declaration
  65. void _start(int, char**, char**);
  66. void _start(int argc, char** argv, char** envp)
  67. {
  68. char** env;
  69. for (env = envp; *env; ++env) {
  70. }
  71. auxv_t* auxvp = (auxv_t*)++env;
  72. perform_self_relocations(auxvp);
  73. init_libc();
  74. int main_program_fd = -1;
  75. String main_program_name;
  76. bool is_secure = false;
  77. for (; auxvp->a_type != AT_NULL; ++auxvp) {
  78. if (auxvp->a_type == ELF::AuxiliaryValue::ExecFileDescriptor) {
  79. main_program_fd = auxvp->a_un.a_val;
  80. }
  81. if (auxvp->a_type == ELF::AuxiliaryValue::ExecFilename) {
  82. main_program_name = (const char*)auxvp->a_un.a_ptr;
  83. }
  84. if (auxvp->a_type == ELF::AuxiliaryValue::Secure) {
  85. is_secure = auxvp->a_un.a_val == 1;
  86. }
  87. }
  88. if (main_program_name == "/usr/lib/Loader.so") {
  89. // We've been invoked directly as an executable rather than as the
  90. // ELF interpreter for some other binary. In the future we may want
  91. // to support launching a program directly from the dynamic loader
  92. // like ld.so on Linux.
  93. display_help();
  94. _exit(1);
  95. }
  96. VERIFY(main_program_fd >= 0);
  97. VERIFY(!main_program_name.is_empty());
  98. ELF::DynamicLinker::linker_main(move(main_program_name), main_program_fd, is_secure, argc, argv, envp);
  99. VERIFY_NOT_REACHED();
  100. }
  101. void _fini();
  102. void _fini()
  103. {
  104. }
  105. }