mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-06-02 12:44:24 +02:00
925b2bc8d2
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
107 lines
2.9 KiB
Rust
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;
|
|
}
|