Files
XunilOS/kernel/src/driver/elf/loader.rs
T
csd4ni3l 925b2bc8d2 Add a proper vfs driver into the kernel which handles file operations,
fix munmap number, remove the draw calls, make address space an option,
copy only the top 256 bytes of the HHDM and map the ELF code inside
userspace, add safe copying from userspace
2026-05-09 11:36:48 +02:00

107 lines
2.9 KiB
Rust

use core::ptr::null;
use x86_64::structures::paging::OffsetPageTable;
use crate::{
arch::syscall::{malloc, memset},
driver::elf::{
header::{
ET_DYN, ET_EXEC, ET_REL, Elf64Ehdr, Elf64Rel, Elf64Shdr, SHF_ALLOC, SHT_NOBITS, SHT_REL,
},
program::load_program,
reloc::elf_do_reloc,
section::elf_sheader,
validation::validate_elf,
},
};
pub fn load_file(mapper: &mut OffsetPageTable, elf_bytes: &[u8]) -> (*const u8, u64) {
// elf header size
if elf_bytes.len() < 64 {
return (null(), 0);
}
let elf_header: Elf64Ehdr =
unsafe { core::ptr::read_unaligned(elf_bytes.as_ptr() as *const Elf64Ehdr) };
if !validate_elf(&elf_header, elf_bytes.len()) {
return (null(), 0);
}
let elf_header_ptr = elf_bytes.as_ptr() as *const Elf64Ehdr;
return match elf_header.e_type {
ET_EXEC => unsafe { load_program(mapper, elf_header_ptr, elf_bytes, false) },
ET_DYN => unsafe { load_program(mapper, elf_header_ptr, elf_bytes, true) },
ET_REL => return (null(), 0),
_ => return (null(), 0),
};
}
// TODO: make ET_REL work
pub unsafe fn elf_load_stage1(hdr: *const Elf64Ehdr) {
let shdr = unsafe { elf_sheader(hdr) } as *mut Elf64Shdr;
let mut i: u16 = 0;
let shnum = unsafe { (*hdr).e_shnum };
while i < shnum {
let section: &mut Elf64Shdr = unsafe { &mut *(shdr.add(i as usize)) };
if section.sh_type == SHT_NOBITS {
if section.sh_size == 0 {
continue;
}
if (section.sh_flags & SHF_ALLOC) != 1 {
let mem =
unsafe { malloc(section.sh_size as usize, section.sh_addralign as usize) };
if mem.is_null() {
continue; // handle OOM
}
unsafe {
// zero the memory
memset(mem, 0, section.sh_size as usize);
}
section.sh_offset = mem.addr() as u64;
}
}
i += 1;
}
}
pub unsafe fn elf_load_stage2(hdr: *const Elf64Ehdr) -> i8 {
let shdr = unsafe { elf_sheader(hdr) } as *mut Elf64Shdr;
let mut i: u16 = 0;
let mut idx: u64;
let shnum = unsafe { (*hdr).e_shnum };
while i < shnum {
let section: &mut Elf64Shdr = unsafe { &mut *(shdr.add(i as usize)) };
if section.sh_type == SHT_REL {
idx = 0;
while idx < section.sh_size / section.sh_entsize {
let reltab: *const Elf64Rel = unsafe {
((hdr as *const u8).add(section.sh_offset as usize) as *const Elf64Rel)
.add(idx as usize)
};
let result: i8 = unsafe { elf_do_reloc(hdr, reltab, section) };
if result == -1 {
return -1;
}
idx += 1;
}
}
i += 1;
}
return 0;
}