elf.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <string>
  2. #include <vector>
  3. #include <errno.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <types/elf.hpp>
  8. #include <kernel/mem/mm_list.hpp>
  9. #include <kernel/mem/vm_area.hpp>
  10. #include <kernel/process.hpp>
  11. #include <kernel/vfs.hpp>
  12. #include <kernel/vfs/dentry.hpp>
  13. static inline void __user_push32(uintptr_t* sp, uint32_t d) {
  14. // TODO: use copy_to_user
  15. *(--*(uint32_t**)sp) = d;
  16. }
  17. static inline void __user_push_string32(uintptr_t* sp, const char* str) {
  18. size_t len = strlen(str);
  19. *sp -= (len + 1);
  20. *sp &= ~0xf; // align to 16 bytes
  21. memcpy((void*)*sp, str, len + 1);
  22. }
  23. int types::elf::elf32_load(types::elf::elf32_load_data& d) {
  24. auto exec = fs::dentry_pointer{d.exec_dent};
  25. if (!exec)
  26. return -ENOENT;
  27. types::elf::elf32_header hdr{};
  28. auto n_read = fs::fs_read(exec.get(), (char*)&hdr, sizeof(types::elf::elf32_header), 0,
  29. sizeof(types::elf::elf32_header));
  30. if (n_read != sizeof(types::elf::elf32_header))
  31. return -EINVAL;
  32. if (hdr.magic[0] != 0x7f || hdr.magic[1] != 'E' || hdr.magic[2] != 'L' || hdr.magic[3] != 'F')
  33. return -EINVAL;
  34. size_t phents_size = hdr.phentsize * hdr.phnum;
  35. size_t shents_size = hdr.shentsize * hdr.shnum;
  36. std::vector<types::elf::elf32_program_header_entry> phents(hdr.phnum);
  37. n_read = fs::fs_read(exec.get(), (char*)phents.data(), phents_size, hdr.phoff, phents_size);
  38. // broken file or I/O error
  39. if (n_read != phents_size)
  40. return -EINVAL;
  41. std::vector<types::elf::elf32_section_header_entry> shents(hdr.shnum);
  42. n_read = fs::fs_read(exec.get(), (char*)shents.data(), shents_size, hdr.shoff, shents_size);
  43. // broken file or I/O error
  44. if (n_read != shents_size)
  45. return -EINVAL;
  46. // from now on, caller process is gone.
  47. // so we can't just simply return to it on error.
  48. auto& mms = current_process->mms;
  49. mms.clear();
  50. uintptr_t data_segment_end = 0;
  51. for (const auto& phent : phents) {
  52. if (phent.type != types::elf::elf32_program_header_entry::PT_LOAD)
  53. continue;
  54. auto vaddr = phent.vaddr & ~0xfff;
  55. auto vlen = ((phent.vaddr + phent.memsz + 0xfff) & ~0xfff) - vaddr;
  56. auto flen = ((phent.vaddr + phent.filesz + 0xfff) & ~0xfff) - vaddr;
  57. auto fileoff = phent.offset & ~0xfff;
  58. using namespace kernel::mem;
  59. if (flen) {
  60. mm_list::map_args args{};
  61. args.vaddr = vaddr;
  62. args.length = flen;
  63. args.file = fs::d_get(exec);
  64. args.file_offset = fileoff;
  65. args.flags = MM_MAPPED;
  66. if (phent.flags & elf32_program_header_entry::PF_W)
  67. args.flags |= MM_WRITE;
  68. if (phent.flags & elf32_program_header_entry::PF_X)
  69. args.flags |= MM_EXECUTE;
  70. if (auto ret = mms.mmap(args); ret != 0)
  71. return ELF_LOAD_FAIL_NORETURN;
  72. }
  73. if (vlen > flen) {
  74. mm_list::map_args args{};
  75. args.vaddr = vaddr + flen;
  76. args.length = vlen - flen;
  77. args.flags = MM_ANONYMOUS;
  78. if (phent.flags & elf32_program_header_entry::PF_W)
  79. args.flags |= MM_WRITE;
  80. if (phent.flags & elf32_program_header_entry::PF_X)
  81. args.flags |= MM_EXECUTE;
  82. if (auto ret = mms.mmap(args); ret != 0)
  83. return ELF_LOAD_FAIL_NORETURN;
  84. }
  85. if (vaddr + vlen > data_segment_end)
  86. data_segment_end = vaddr + vlen;
  87. }
  88. current_process->mms.register_brk(data_segment_end + 0x10000);
  89. for (const auto& shent : shents) {
  90. if (shent.sh_type == elf32_section_header_entry::SHT_NOBITS)
  91. memset((char*)(uintptr_t)shent.sh_addr, 0x00, shent.sh_size);
  92. }
  93. // map stack area
  94. if (1) {
  95. using namespace kernel::mem;
  96. mm_list::map_args args{};
  97. args.vaddr = ELF32_STACK_TOP;
  98. args.length = ELF32_STACK_SIZE;
  99. args.flags = MM_ANONYMOUS | MM_WRITE;
  100. if (auto ret = mms.mmap(args); ret != 0)
  101. return ELF_LOAD_FAIL_NORETURN;
  102. }
  103. d.ip = hdr.entry;
  104. d.sp = ELF32_STACK_BOTTOM;
  105. auto* sp = &d.sp;
  106. // fill information block area
  107. std::vector<elf32_addr_t> args, envs;
  108. for (size_t i = 0; i < d.envp_count; ++i) {
  109. __user_push_string32(sp, d.envp[i]);
  110. envs.push_back((uintptr_t)*sp);
  111. }
  112. for (size_t i = 0; i < d.argv_count; ++i) {
  113. __user_push_string32(sp, d.argv[i]);
  114. args.push_back((uintptr_t)*sp);
  115. }
  116. // push null auxiliary vector entry
  117. __user_push32(sp, 0);
  118. __user_push32(sp, 0);
  119. // push 0 for envp
  120. __user_push32(sp, 0);
  121. // push envp
  122. for (auto ent : envs)
  123. __user_push32(sp, ent);
  124. // push 0 for argv
  125. __user_push32(sp, 0);
  126. // push argv
  127. for (int i = args.size() - 1; i >= 0; --i)
  128. __user_push32(sp, args[i]);
  129. // push argc
  130. __user_push32(sp, args.size());
  131. // TODO!!!: rename current thread
  132. current_thread->name = "[thread]";
  133. return 0;
  134. }