elf.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #pragma once
  2. #include <errno.h>
  3. #include <stdint.h>
  4. #include <kernel/interrupt.hpp>
  5. #include <kernel/process.hpp>
  6. #include <kernel/vfs.hpp>
  7. namespace types::elf {
  8. using elf32_addr_t = uint32_t;
  9. using elf32_off_t = uint32_t;
  10. using elf64_addr_t = uint64_t;
  11. using elf64_off_t = uint64_t;
  12. constexpr elf32_addr_t ELF32_STACK_BOTTOM = 0xbffff000;
  13. constexpr elf32_off_t ELF32_STACK_SIZE = 8 * 1024 * 1024;
  14. constexpr elf32_addr_t ELF32_STACK_TOP = ELF32_STACK_BOTTOM - ELF32_STACK_SIZE;
  15. constexpr int ELF_LOAD_FAIL_NORETURN = 0x114514;
  16. struct PACKED elf32_header {
  17. // 0x7f, "ELF"
  18. char magic[4];
  19. enum : uint8_t {
  20. FORMAT_32 = 1,
  21. FORMAT_64 = 2,
  22. } format;
  23. enum : uint8_t {
  24. ENDIAN_LITTLE = 1,
  25. ENDIAN_BIG = 2,
  26. } endian;
  27. // should be 1
  28. uint8_t _version1;
  29. enum : uint8_t {
  30. ABI_SYSTEM_V = 0x00,
  31. // TODO:
  32. ABI_LINUX = 0x03,
  33. } abi;
  34. uint8_t abi_version;
  35. uint8_t _reserved[7];
  36. enum : uint16_t {
  37. ET_NONE = 0x00,
  38. ET_REL = 0x01,
  39. ET_EXEC = 0x02,
  40. ET_DYN = 0x03,
  41. ET_CORE = 0x04,
  42. ET_LOOS = 0xfe00,
  43. ET_HIOS = 0xfeff,
  44. ET_LOPROC = 0xff00,
  45. ET_HIPROC = 0xffff,
  46. } type;
  47. enum : uint16_t {
  48. ARCH_NONE = 0x00,
  49. ARCH_X86 = 0x03,
  50. ARCH_ARM = 0x28,
  51. ARCH_IA64 = 0x32,
  52. ARCH_X86_64 = 0x3e,
  53. ARCH_ARM64 = 0xb7,
  54. ARCH_RISCV = 0xf3,
  55. } arch;
  56. // should be 1
  57. uint32_t _version2;
  58. // entry address
  59. elf32_addr_t entry;
  60. // program header table offset
  61. elf32_off_t phoff;
  62. // section header table offset
  63. elf32_off_t shoff;
  64. // architecture dependent flags
  65. uint32_t flags;
  66. // elf header size
  67. uint16_t ehsize;
  68. // program header table entry size
  69. uint16_t phentsize;
  70. // program header table entries number
  71. uint16_t phnum;
  72. // section header table entry size
  73. uint16_t shentsize;
  74. // section header table entries number
  75. uint16_t shnum;
  76. // section header table entry index that contains section names
  77. uint16_t shstrndx;
  78. };
  79. struct PACKED elf32_program_header_entry {
  80. enum : uint32_t {
  81. PT_NULL = 0x00,
  82. PT_LOAD = 0x01,
  83. PT_DYNAMIC = 0x02,
  84. PT_INTERP = 0x03,
  85. PT_NOTE = 0x04,
  86. PT_SHLIB = 0x05,
  87. PT_PHDR = 0x06,
  88. PT_TLS = 0x07,
  89. PT_LOOS = 0x60000000,
  90. PT_HIOS = 0x6fffffff,
  91. PT_LIPROC = 0x70000000,
  92. PT_HIPROC = 0x7fffffff,
  93. } type;
  94. elf32_off_t offset;
  95. elf32_addr_t vaddr;
  96. elf32_addr_t paddr;
  97. elf32_off_t filesz;
  98. elf32_off_t memsz;
  99. // segment dependent
  100. enum : uint32_t {
  101. PF_X = 0x1,
  102. PF_W = 0x2,
  103. PF_R = 0x4,
  104. } flags;
  105. // 0 and 1 for no alignment, otherwise power of 2
  106. uint32_t align;
  107. };
  108. struct PACKED elf32_section_header_entry {
  109. elf32_off_t sh_name;
  110. enum : uint32_t {
  111. SHT_NULL = 0x00,
  112. SHT_PROGBITS = 0x01,
  113. SHT_RELA = 0x04,
  114. SHT_DYNAMIC = 0x06,
  115. SHT_NOTE = 0x07,
  116. SHT_NOBITS = 0x08,
  117. SHT_REL = 0x09,
  118. SHT_DYNSYM = 0x0b,
  119. SHT_INIT_ARRAY = 0x0e,
  120. SHT_FINI_ARRAY = 0x0f,
  121. SHT_PREINIT_ARRAY = 0x0f,
  122. } sh_type;
  123. enum : uint32_t {
  124. SHF_WRITE = 0x01,
  125. SHF_ALLOC = 0x02,
  126. SHF_EXECINSTR = 0x04,
  127. } sh_flags;
  128. elf32_addr_t sh_addr;
  129. elf32_off_t sh_offset;
  130. elf32_off_t sh_size;
  131. uint32_t sh_link;
  132. uint32_t sh_info;
  133. elf32_off_t sh_addralign;
  134. elf32_off_t sh_entsize;
  135. };
  136. struct elf32_load_data {
  137. const fs::dentry* exec_dent;
  138. const std::vector<std::string>& argv;
  139. const std::vector<std::string>& envp;
  140. uintptr_t ip;
  141. uintptr_t sp;
  142. };
  143. // TODO: environment variables
  144. int elf32_load(elf32_load_data& data);
  145. struct PACKED elf64_header {
  146. // 0x7f, "ELF"
  147. char magic[4];
  148. enum : uint8_t {
  149. FORMAT_32 = 1,
  150. FORMAT_64 = 2,
  151. } format;
  152. enum : uint8_t {
  153. ENDIAN_LITTLE = 1,
  154. ENDIAN_BIG = 2,
  155. } endian;
  156. // should be 1
  157. uint8_t _version1;
  158. enum : uint8_t {
  159. ABI_SYSTEM_V = 0x00,
  160. // TODO:
  161. ABI_LINUX = 0x03,
  162. } abi;
  163. uint8_t abi_version;
  164. uint8_t _reserved[7];
  165. enum : uint16_t {
  166. ET_NONE = 0x00,
  167. ET_REL = 0x01,
  168. ET_EXEC = 0x02,
  169. ET_DYN = 0x03,
  170. ET_CORE = 0x04,
  171. ET_LOOS = 0xfe00,
  172. ET_HIOS = 0xfeff,
  173. ET_LOPROC = 0xff00,
  174. ET_HIPROC = 0xffff,
  175. } type;
  176. enum : uint16_t {
  177. ARCH_NONE = 0x00,
  178. ARCH_X86 = 0x03,
  179. ARCH_ARM = 0x28,
  180. ARCH_IA64 = 0x32,
  181. ARCH_X86_64 = 0x3e,
  182. ARCH_ARM64 = 0xb7,
  183. ARCH_RISCV = 0xf3,
  184. } arch;
  185. // should be 1
  186. uint32_t _version2;
  187. // entry address
  188. elf64_addr_t entry;
  189. // program header table offset
  190. elf64_off_t phoff;
  191. // section header table offset
  192. elf64_off_t shoff;
  193. // architecture dependent flags
  194. uint32_t flags;
  195. // elf header size
  196. uint16_t ehsize;
  197. // program header table entry size
  198. uint16_t phentsize;
  199. // program header table entries number
  200. uint16_t phnum;
  201. // section header table entry size
  202. uint16_t shentsize;
  203. // section header table entries number
  204. uint16_t shnum;
  205. // section header table entry index that contains section names
  206. uint16_t shstrndx;
  207. };
  208. struct PACKED elf64_program_header_entry {
  209. enum : uint32_t {
  210. PT_NULL = 0x00,
  211. PT_LOAD = 0x01,
  212. PT_DYNAMIC = 0x02,
  213. PT_INTERP = 0x03,
  214. PT_NOTE = 0x04,
  215. PT_SHLIB = 0x05,
  216. PT_PHDR = 0x06,
  217. PT_TLS = 0x07,
  218. PT_LOOS = 0x60000000,
  219. PT_HIOS = 0x6fffffff,
  220. PT_LIPROC = 0x70000000,
  221. PT_HIPROC = 0x7fffffff,
  222. } type;
  223. // segment dependent
  224. enum : uint32_t {
  225. PF_X = 0x1,
  226. PF_W = 0x2,
  227. PF_R = 0x4,
  228. } flags;
  229. elf64_off_t offset;
  230. elf64_addr_t vaddr;
  231. elf64_addr_t paddr;
  232. elf64_off_t filesz;
  233. elf64_off_t memsz;
  234. // 0 and 1 for no alignment, otherwise power of 2
  235. uint64_t align;
  236. };
  237. struct PACKED elf64_section_header_entry {
  238. uint32_t sh_name;
  239. enum : uint32_t {
  240. SHT_NULL = 0x00,
  241. SHT_PROGBITS = 0x01,
  242. SHT_RELA = 0x04,
  243. SHT_DYNAMIC = 0x06,
  244. SHT_NOTE = 0x07,
  245. SHT_NOBITS = 0x08,
  246. SHT_REL = 0x09,
  247. SHT_DYNSYM = 0x0b,
  248. SHT_INIT_ARRAY = 0x0e,
  249. SHT_FINI_ARRAY = 0x0f,
  250. SHT_PREINIT_ARRAY = 0x0f,
  251. } sh_type;
  252. enum : uint64_t {
  253. SHF_WRITE = 0x01,
  254. SHF_ALLOC = 0x02,
  255. SHF_EXECINSTR = 0x04,
  256. } sh_flags;
  257. elf64_addr_t sh_addr;
  258. elf64_off_t sh_offset;
  259. elf64_off_t sh_size;
  260. uint32_t sh_link;
  261. uint32_t sh_info;
  262. elf64_off_t sh_addralign;
  263. elf64_off_t sh_entsize;
  264. };
  265. struct elf64_load_data {
  266. const fs::dentry* exec_dent;
  267. std::vector<std::string> argv;
  268. std::vector<std::string> envp;
  269. unsigned long ip;
  270. unsigned long sp;
  271. };
  272. } // namespace types::elf