elf.c

Commit: a686c095 Author: jokerz Raw Copy
1
/* elf.c - ELF64 loader for Pactor64 */
2
#include "elf.h"
3
4
int elf64_validate(const void *file_data, uint32_t file_size) {
5
    if (file_size < sizeof(elf64_ehdr_t)) {
6
        kprintf("[elf] File too small for ELF header\n");
7
        return -1;
8
    }
9
10
    const elf64_ehdr_t *ehdr = (const elf64_ehdr_t *)file_data;
11
12
    if (ehdr->e_ident[0] != ELFMAG0 || ehdr->e_ident[1] != ELFMAG1 ||
13
        ehdr->e_ident[2] != ELFMAG2 || ehdr->e_ident[3] != ELFMAG3) {
14
        kprintf("[elf] Bad ELF magic\n");
15
        return -1;
16
    }
17
    if (ehdr->e_ident[4] != ELFCLASS64) {
18
        kprintf("[elf] Not a 64-bit ELF (class=%d)\n", ehdr->e_ident[4]);
19
        return -1;
20
    }
21
    if (ehdr->e_ident[5] != ELFDATA2LSB) {
22
        kprintf("[elf] Not little-endian\n");
23
        return -1;
24
    }
25
    if (ehdr->e_type != ET_EXEC) {
26
        kprintf("[elf] Not an executable (type=%d)\n", ehdr->e_type);
27
        return -1;
28
    }
29
    if (ehdr->e_machine != EM_X86_64) {
30
        kprintf("[elf] Not x86-64 (machine=%d)\n", ehdr->e_machine);
31
        return -1;
32
    }
33
    if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > file_size) {
34
        kprintf("[elf] Program header table extends beyond file\n");
35
        return -1;
36
    }
37
    return 0;
38
}
39
40
elf64_load_result_t elf64_load(const void *file_data, uint32_t file_size) {
41
    elf64_load_result_t result;
42
    result.valid = 0;
43
    result.entry = 0;
44
    result.load_base = 0xFFFFFFFFFFFFFFFFULL;
45
    result.load_end = 0;
46
47
    if (elf64_validate(file_data, file_size) != 0) return result;
48
49
    const elf64_ehdr_t *ehdr = (const elf64_ehdr_t *)file_data;
50
    result.entry = ehdr->e_entry;
51
52
    kprintf("[elf] Entry point: 0x%x\n", result.entry);
53
    kprintf("[elf] Program headers: %d\n", ehdr->e_phnum);
54
55
    const uint8_t *base = (const uint8_t *)file_data;
56
    for (uint16_t i = 0; i < ehdr->e_phnum; i++) {
57
        const elf64_phdr_t *phdr = (const elf64_phdr_t *)
58
            (base + ehdr->e_phoff + i * ehdr->e_phentsize);
59
60
        if (phdr->p_type != PT_LOAD) continue;
61
62
        kprintf("[elf] PT_LOAD[%d]: vaddr=0x%x filesz=0x%x memsz=0x%x flags=%c%c%c\n",
63
                i, phdr->p_vaddr, phdr->p_filesz, phdr->p_memsz,
64
                (phdr->p_flags & PF_R) ? 'R' : '-',
65
                (phdr->p_flags & PF_W) ? 'W' : '-',
66
                (phdr->p_flags & PF_X) ? 'E' : '-');
67
68
        if (phdr->p_offset + phdr->p_filesz > file_size) {
69
            kprintf("[elf] Segment extends beyond file\n");
70
            return result;
71
        }
72
73
        void *dest = (void *)(uintptr_t)phdr->p_vaddr;
74
        kmemset(dest, 0, phdr->p_memsz);
75
        if (phdr->p_filesz > 0) {
76
            kmemcpy(dest, base + phdr->p_offset, phdr->p_filesz);
77
        }
78
79
        if (phdr->p_vaddr < result.load_base)
80
            result.load_base = phdr->p_vaddr;
81
        if (phdr->p_vaddr + phdr->p_memsz > result.load_end)
82
            result.load_end = phdr->p_vaddr + phdr->p_memsz;
83
    }
84
85
    result.valid = 1;
86
    kprintf("[elf] Loaded at 0x%x - 0x%x, entry at 0x%x\n",
87
            result.load_base, result.load_end, result.entry);
88
    return result;
89
}
90
91
uint64_t elf64_get_entry(const void *file_data) {
92
    const elf64_ehdr_t *ehdr = (const elf64_ehdr_t *)file_data;
93
    return ehdr->e_entry;
94
}
95