elf.cpp 5.0 KB

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