elf.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #include <assert.h>
  2. #include <kernel/errno.h>
  3. #include <kernel/mem.h>
  4. #include <stdint.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <types/elf.hpp>
  8. #include <types/string.hpp>
  9. #include <types/vector.hpp>
  10. #define align16_down(sp) (sp = ((char*)((uint32_t)(sp)&0xfffffff0)))
  11. template <typename T>
  12. inline void _user_push(char** sp, T d)
  13. {
  14. *sp -= sizeof(T);
  15. *(T*)*sp = d;
  16. }
  17. template <>
  18. inline void _user_push(char** sp, const char* str)
  19. {
  20. size_t len = strlen(str);
  21. *sp -= (len + 1);
  22. align16_down(*sp);
  23. memcpy(*sp, str, len + 1);
  24. }
  25. int types::elf::elf32_load(types::elf::elf32_load_data* d)
  26. {
  27. auto* ent_exec = fs::vfs_open(d->exec);
  28. if (!ent_exec) {
  29. d->errcode = ENOENT;
  30. return GB_FAILED;
  31. }
  32. // TODO: detect file format
  33. types::elf::elf32_header hdr {};
  34. auto n_read = fs::vfs_read(
  35. ent_exec->ind,
  36. (char*)&hdr,
  37. sizeof(types::elf::elf32_header),
  38. 0, sizeof(types::elf::elf32_header));
  39. if (n_read != sizeof(types::elf::elf32_header)) {
  40. d->errcode = EINVAL;
  41. return GB_FAILED;
  42. }
  43. size_t phents_size = hdr.phentsize * hdr.phnum;
  44. auto* phents = (types::elf::elf32_program_header_entry*)k_malloc(phents_size);
  45. n_read = fs::vfs_read(
  46. ent_exec->ind,
  47. (char*)phents,
  48. phents_size,
  49. hdr.phoff, phents_size);
  50. // broken file or I/O error
  51. if (n_read != phents_size) {
  52. k_free(phents);
  53. d->errcode = EINVAL;
  54. return GB_FAILED;
  55. }
  56. // copy argv and envp
  57. vector<string<>> argv, envp;
  58. for (const char* const* p = d->argv; *p; ++p)
  59. argv.emplace_back(*p);
  60. for (const char* const* p = d->envp; *p; ++p)
  61. envp.emplace_back(*p);
  62. // from now on, caller process is recycled.
  63. // so we can't just simply return to it on error.
  64. current_process->mms.clear_user();
  65. for (int i = 0; i < hdr.phnum; ++i) {
  66. if (phents->type != types::elf::elf32_program_header_entry::PT_LOAD)
  67. continue;
  68. auto ret = mmap((void*)phents->vaddr, phents->memsz, ent_exec->ind, phents->offset, 1, d->system);
  69. if (ret != GB_OK) {
  70. k_free(phents);
  71. // TODO: kill process
  72. assert(false);
  73. d->errcode = ret;
  74. return GB_FAILED;
  75. }
  76. ++phents;
  77. }
  78. // map stack area
  79. auto ret = mmap((void*)types::elf::ELF_STACK_TOP, types::elf::ELF_STACK_SIZE,
  80. fs::vfs_open("/dev/null")->ind, 0, 1, 0);
  81. assert(ret == GB_OK);
  82. d->eip = (void*)hdr.entry;
  83. d->sp = reinterpret_cast<uint32_t*>(types::elf::ELF_STACK_BOTTOM);
  84. auto* sp = (char**)&d->sp;
  85. // fill information block area
  86. vector<char*> args, envs;
  87. for (const auto& env : envp) {
  88. _user_push(sp, env.c_str());
  89. envs.push_back(*sp);
  90. }
  91. for (const auto& arg : argv) {
  92. _user_push(sp, arg.c_str());
  93. args.push_back(*sp);
  94. }
  95. // push null auxiliary vector entry
  96. _user_push(sp, 0);
  97. _user_push(sp, 0);
  98. // push 0 for envp
  99. _user_push(sp, 0);
  100. // push envp
  101. *sp -= sizeof(void*) * envs.size();
  102. memcpy(*sp, envs.data(), sizeof(void*) * envs.size());
  103. // push 0 for argv
  104. _user_push(sp, 0);
  105. // push argv
  106. *sp -= sizeof(void*) * args.size();
  107. memcpy(*sp, args.data(), sizeof(void*) * args.size());
  108. // push argc
  109. _user_push(sp, args.size());
  110. return GB_OK;
  111. }