elf.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #include <assert.h>
  2. #include <kernel/errno.h>
  3. #include <kernel/mem.h>
  4. #include <kernel/process.hpp>
  5. #include <kernel/vfs.hpp>
  6. #include <stdint.h>
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <types/elf.hpp>
  10. #include <types/string.hpp>
  11. #include <types/vector.hpp>
  12. #define align16_down(sp) (sp = ((char*)((uint32_t)(sp)&0xfffffff0)))
  13. template <typename T>
  14. inline void _user_push(char** sp, T d)
  15. {
  16. *sp -= sizeof(T);
  17. *(T*)*sp = d;
  18. }
  19. template <>
  20. inline void _user_push(char** sp, const char* str)
  21. {
  22. size_t len = strlen(str);
  23. *sp -= (len + 1);
  24. align16_down(*sp);
  25. memcpy(*sp, str, len + 1);
  26. }
  27. int types::elf::elf32_load(types::elf::elf32_load_data* d)
  28. {
  29. auto* ent_exec = fs::vfs_open(d->exec);
  30. if (!ent_exec) {
  31. d->errcode = ENOENT;
  32. return GB_FAILED;
  33. }
  34. // TODO: detect file format
  35. types::elf::elf32_header hdr {};
  36. auto n_read = fs::vfs_read(
  37. ent_exec->ind,
  38. (char*)&hdr,
  39. sizeof(types::elf::elf32_header),
  40. 0, sizeof(types::elf::elf32_header));
  41. if (n_read != sizeof(types::elf::elf32_header)) {
  42. d->errcode = EINVAL;
  43. return GB_FAILED;
  44. }
  45. size_t phents_size = hdr.phentsize * hdr.phnum;
  46. size_t shents_size = hdr.shentsize * hdr.shnum;
  47. auto* phents = new types::elf::elf32_program_header_entry[hdr.phnum];
  48. n_read = fs::vfs_read(
  49. ent_exec->ind,
  50. (char*)phents,
  51. phents_size,
  52. hdr.phoff, phents_size);
  53. // broken file or I/O error
  54. if (n_read != phents_size) {
  55. delete[] phents;
  56. d->errcode = EINVAL;
  57. return GB_FAILED;
  58. }
  59. auto* shents = new types::elf::elf32_section_header_entry[hdr.shnum];
  60. n_read = fs::vfs_read(
  61. ent_exec->ind,
  62. (char*)shents,
  63. shents_size,
  64. hdr.shoff, shents_size);
  65. // broken file or I/O error
  66. if (n_read != shents_size) {
  67. delete[] phents;
  68. delete[] shents;
  69. d->errcode = EINVAL;
  70. return GB_FAILED;
  71. }
  72. // copy argv and envp
  73. vector<string<>> argv, envp;
  74. for (const char* const* p = d->argv; *p; ++p)
  75. argv.emplace_back(*p);
  76. for (const char* const* p = d->envp; *p; ++p)
  77. envp.emplace_back(*p);
  78. // from now on, caller process is recycled.
  79. // so we can't just simply return to it on error.
  80. current_process->mms.clear_user();
  81. fs::inode* null_ind = nullptr;
  82. {
  83. auto* dent = fs::vfs_open("/dev/null");
  84. if (!dent) {
  85. delete[] phents;
  86. delete[] shents;
  87. kill_current(-1);
  88. }
  89. null_ind = dent->ind;
  90. }
  91. for (int i = 0; i < hdr.phnum; ++i) {
  92. if (phents[i].type != types::elf::elf32_program_header_entry::PT_LOAD)
  93. continue;
  94. auto vaddr = align_down<12>(phents[i].vaddr);
  95. auto vlen = align_up<12>(phents[i].vaddr + phents[i].memsz) - vaddr;
  96. auto flen = align_up<12>(phents[i].vaddr + phents[i].filesz) - vaddr;
  97. auto fileoff = align_down<12>(phents[i].offset);
  98. auto ret = mmap(
  99. (char*)vaddr,
  100. phents[i].filesz + (phents[i].vaddr & 0xfff),
  101. ent_exec->ind,
  102. fileoff,
  103. 1,
  104. d->system);
  105. if (ret != GB_OK)
  106. goto error;
  107. if (vlen > flen) {
  108. ret = mmap(
  109. (char*)vaddr + flen,
  110. vlen - flen,
  111. null_ind,
  112. 0,
  113. 1,
  114. d->system);
  115. if (ret != GB_OK)
  116. goto error;
  117. }
  118. continue;
  119. error:
  120. delete[] phents;
  121. delete[] shents;
  122. kill_current(-1);
  123. }
  124. for (int i = 0; i < hdr.shnum; ++i) {
  125. if (shents[i].sh_type == elf32_section_header_entry::SHT_NOBITS)
  126. memset((char*)shents[i].sh_addr, 0x00, shents[i].sh_size);
  127. }
  128. // map stack area
  129. auto ret = mmap((void*)types::elf::ELF_STACK_TOP,
  130. types::elf::ELF_STACK_SIZE,
  131. null_ind, 0, 1, 0);
  132. assert(ret == GB_OK);
  133. d->eip = (void*)hdr.entry;
  134. d->sp = reinterpret_cast<uint32_t*>(types::elf::ELF_STACK_BOTTOM);
  135. auto* sp = (char**)&d->sp;
  136. // fill information block area
  137. vector<char*> args, envs;
  138. for (const auto& env : envp) {
  139. _user_push(sp, env.c_str());
  140. envs.push_back(*sp);
  141. }
  142. for (const auto& arg : argv) {
  143. _user_push(sp, arg.c_str());
  144. args.push_back(*sp);
  145. }
  146. // push null auxiliary vector entry
  147. _user_push(sp, 0);
  148. _user_push(sp, 0);
  149. // push 0 for envp
  150. _user_push(sp, 0);
  151. // push envp
  152. *sp -= sizeof(void*) * envs.size();
  153. memcpy(*sp, envs.data(), sizeof(void*) * envs.size());
  154. // push 0 for argv
  155. _user_push(sp, 0);
  156. // push argv
  157. *sp -= sizeof(void*) * args.size();
  158. memcpy(*sp, args.data(), sizeof(void*) * args.size());
  159. // push argc
  160. _user_push(sp, args.size());
  161. delete[] phents;
  162. delete[] shents;
  163. return GB_OK;
  164. }