|
28 | 28 | /* https://github.com/KevinAlavik/nekonix/blob/main/kernel/src/proc/elf.c */
|
29 | 29 | /* Thanks, Kevin <3 */
|
30 | 30 |
|
31 |
| -uint64_t elf_load(char *data, uintptr_t *pagemap) |
| 31 | +uintptr_t elf32_load(char *data, pagetable *pagemap) |
| 32 | +{ |
| 33 | + (void)data; |
| 34 | + (void)pagemap; |
| 35 | + return 0; |
| 36 | +} |
| 37 | + |
| 38 | +uintptr_t elf64_load(char *data, pagetable *pagemap) |
32 | 39 | {
|
33 | 40 | struct elf_header *header = (struct elf_header *)data;
|
| 41 | + struct elf_program_header *ph = (struct elf_program_header *)((uint8_t *)data + header->e_phoff); |
34 | 42 |
|
35 |
| - if (header->e_magic != ELF_MAGIC) { |
36 |
| - debug("Invalid ELF magic: 0x%x", header->e_magic); |
37 |
| - return 0; |
38 |
| - } |
| 43 | + uint64_t lowest = UINT64_MAX; |
| 44 | + uint64_t max_align = 0; |
39 | 45 |
|
40 |
| - if (header->e_class != 2) { |
41 |
| - debug("Unsupported ELF class: %u", header->e_class); |
42 |
| - return 0; |
| 46 | + for (uint16_t i = 0; i < header->e_phnum; i++) { |
| 47 | + if (ph[i].p_type != PT_LOAD) |
| 48 | + continue; |
| 49 | + |
| 50 | + if (ph[i].p_align > max_align) { |
| 51 | + max_align = ph[i].p_align; |
| 52 | + } |
43 | 53 | }
|
44 | 54 |
|
45 |
| - struct elf_program_header *ph = (struct elf_program_header *)(data + header->e_phoff); |
46 |
| - |
47 | 55 | for (uint16_t i = 0; i < header->e_phnum; i++) {
|
48 | 56 | if (ph[i].p_type != PT_LOAD)
|
49 | 57 | continue;
|
50 |
| - |
51 |
| - uint64_t vaddr_start = ALIGN_DOWN(ph[i].p_vaddr, PAGE_SIZE); |
52 |
| - uint64_t vaddr_end = ALIGN_UP(ph[i].p_vaddr + ph[i].p_memsz, PAGE_SIZE); |
53 |
| - uint64_t offset = ph[i].p_offset; |
| 58 | + |
| 59 | + if ((ph[i].p_vaddr & (~(max_align - 1))) < lowest) { |
| 60 | + lowest = ph[i].p_vaddr & ~(max_align - 1); |
| 61 | + } |
54 | 62 |
|
55 | 63 | uint64_t flags = VMM_PRESENT;
|
56 | 64 | if (ph[i].p_flags & PF_W)
|
57 | 65 | flags |= VMM_WRITABLE;
|
58 | 66 | if (!(ph[i].p_flags & PF_X))
|
59 | 67 | flags |= VMM_NX;
|
| 68 | + |
| 69 | + debug("elf64_load(): phys=0x%llx, virt=0x%llx, size=%lu\n", ph[i].p_paddr, ph[i].p_vaddr, ph[i].p_filesz); |
| 70 | + |
| 71 | + uint64_t phys = (uint64_t)mem_alloc(ph[i].p_memsz); |
| 72 | + if (!phys) { |
| 73 | + debug("elf64_load(): Out of memory\n"); |
| 74 | + return 0; |
| 75 | + } |
60 | 76 |
|
61 |
| - for (uint64_t addr = vaddr_start; addr < vaddr_end; addr += PAGE_SIZE) { |
62 |
| - uint64_t phys = (uint64_t)mem_alloc(PAGE_SIZE); |
63 |
| - if (!phys) { |
64 |
| - debug("Out of physical memory"); |
65 |
| - return 0; |
66 |
| - } |
| 77 | + map_page(pagemap, ph[i].p_vaddr, phys, flags); |
| 78 | + memcpy((void*)ph[i].p_vaddr - lowest, data + ph[i].p_offset, ph[i].p_filesz); |
| 79 | + } |
67 | 80 |
|
68 |
| - map_page(pagemap, addr, phys, flags); |
| 81 | + debug("elf64_load(): ELF loaded successfully, entry: 0x%llx\n", header->e_entry); |
| 82 | + return (uintptr_t)((uint8_t *)data + (header->e_entry - lowest)); |
| 83 | +} |
69 | 84 |
|
70 |
| - uint64_t file_offset = offset + (addr - vaddr_start); |
71 |
| - if (file_offset < offset + ph[i].p_filesz) { |
72 |
| - uint64_t to_copy = PAGE_SIZE; |
73 |
| - if (file_offset + PAGE_SIZE > offset + ph[i].p_filesz) |
74 |
| - to_copy = offset + ph[i].p_filesz - file_offset; |
| 85 | +uintptr_t elf_load(char *data, pagetable *pagemap) |
| 86 | +{ |
| 87 | + struct elf_header *header = (struct elf_header *)data; |
75 | 88 |
|
76 |
| - memcpy((void *)phys, data + file_offset, to_copy); |
77 |
| - } else { |
78 |
| - memset((void *)phys, 0, PAGE_SIZE); |
79 |
| - } |
80 |
| - } |
| 89 | + if (header->e_magic != ELF_MAGIC) { |
| 90 | + debug("Invalid ELF magic: 0x%x", header->e_magic); |
| 91 | + return 0; |
| 92 | + } |
| 93 | + |
| 94 | + if (header->e_class != 2) { |
| 95 | + debug("Unsupported ELF class: %u", header->e_class); |
| 96 | + return 0; |
| 97 | + } |
| 98 | + |
| 99 | + if (header->e_machine == 20 || |
| 100 | + header->e_machine == 3 || |
| 101 | + header->e_machine == 40) { |
| 102 | + return elf32_load(data, pagemap); |
| 103 | + } else if (header->e_machine == 62) { |
| 104 | + return elf64_load(data, pagemap); |
81 | 105 | }
|
82 | 106 |
|
83 |
| - debug("ELF loaded successfully, entry: 0x%lx", header->e_entry); |
84 |
| - return header->e_entry; |
| 107 | + debug("Unsupported ELF machine: %u", header->e_machine); |
| 108 | + return 0; |
85 | 109 | }
|
0 commit comments