elf.cpp 5.0 KB

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