| 19 | namespace { |
| 20 | |
| 21 | auto LoadElf(const uint8_t* elf_data, uint64_t* page_table) -> uint64_t { |
| 22 | // Check ELF magic |
| 23 | auto* ehdr = reinterpret_cast<const Elf64_Ehdr*>(elf_data); |
| 24 | if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 || |
| 25 | ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) { |
| 26 | klog::Err("Invalid ELF magic"); |
| 27 | return 0; |
| 28 | } |
| 29 | |
| 30 | auto* phdr = reinterpret_cast<const Elf64_Phdr*>(elf_data + ehdr->e_phoff); |
| 31 | auto& vm = VirtualMemorySingleton::instance(); |
| 32 | |
| 33 | for (int i = 0; i < ehdr->e_phnum; ++i) { |
| 34 | if (phdr[i].p_type != PT_LOAD) continue; |
| 35 | |
| 36 | uintptr_t vaddr = phdr[i].p_vaddr; |
| 37 | uintptr_t memsz = phdr[i].p_memsz; |
| 38 | uintptr_t filesz = phdr[i].p_filesz; |
| 39 | uintptr_t offset = phdr[i].p_offset; |
| 40 | |
| 41 | uint32_t flags = cpu_io::virtual_memory::GetUserPagePermissions( |
| 42 | (phdr[i].p_flags & PF_R) != 0, (phdr[i].p_flags & PF_W) != 0, |
| 43 | (phdr[i].p_flags & PF_X) != 0); |
| 44 | |
| 45 | uintptr_t start_page = cpu_io::virtual_memory::PageAlign(vaddr); |
| 46 | uintptr_t end_page = cpu_io::virtual_memory::PageAlignUp(vaddr + memsz); |
| 47 | |
| 48 | for (uintptr_t page = start_page; page < end_page; |
| 49 | page += cpu_io::virtual_memory::kPageSize) { |
| 50 | void* p_page = aligned_alloc(cpu_io::virtual_memory::kPageSize, |
| 51 | cpu_io::virtual_memory::kPageSize); |
| 52 | if (!p_page) { |
| 53 | klog::Err("Failed to allocate page for ELF"); |
| 54 | return 0; |
| 55 | } |
| 56 | kstd::memset(p_page, 0, cpu_io::virtual_memory::kPageSize); |
| 57 | |
| 58 | // Mapping logic |
| 59 | uintptr_t v_start = page; |
| 60 | uintptr_t v_end = page + cpu_io::virtual_memory::kPageSize; |
| 61 | |
| 62 | // Map intersection with file data |
| 63 | uintptr_t file_start = vaddr; |
| 64 | uintptr_t file_end = vaddr + filesz; |
| 65 | |
| 66 | uintptr_t copy_start = std::max(v_start, file_start); |
| 67 | uintptr_t copy_end = std::min(v_end, file_end); |
| 68 | |
| 69 | if (copy_end > copy_start) { |
| 70 | uintptr_t dst_off = copy_start - v_start; |
| 71 | uintptr_t src_off = (copy_start - vaddr) + offset; |
| 72 | kstd::memcpy(static_cast<uint8_t*>(p_page) + dst_off, |
| 73 | elf_data + src_off, copy_end - copy_start); |
| 74 | } |
| 75 | |
| 76 | if (!vm.MapPage(page_table, reinterpret_cast<void*>(page), p_page, |
| 77 | flags)) { |
| 78 | klog::Err("MapPage failed"); |
no test coverage detected