1use kernel_user_link::process::ProcessMetadata;
2use tracing::trace;
3
4use crate::{cpu, fs, memory_management::virtual_memory_mapper};
5
6pub mod elf;
7
8pub unsafe fn load_elf_to_vm(
12 elf: &elf::Elf,
13 file: &mut fs::File,
14 process_meta: &mut ProcessMetadata,
15 vm: &mut virtual_memory_mapper::VirtualMemoryMapper,
16) -> Result<(usize, usize), fs::FileSystemError> {
17 cpu::cpu().push_cli();
19 let old_vm = virtual_memory_mapper::get_current_vm();
20
21 vm.switch_to_this();
25
26 let mut min_address = usize::MAX;
27 let mut max_address = 0;
28 let mut phdr_address = 0;
29
30 for segment in elf.program_headers() {
31 match segment.ty() {
32 elf::ElfProgramType::Load => {
33 let segment_virtual = segment.virtual_address();
34 assert_eq!(segment_virtual, segment.physical_address());
35
36 let mut flags = elf::to_virtual_memory_flags(segment.flags());
37 flags |= virtual_memory_mapper::flags::PTE_USER;
38 let entry = virtual_memory_mapper::VirtualMemoryMapEntry {
39 virtual_address: segment_virtual as usize,
40 physical_address: None,
41 size: segment.mem_size() as usize,
42 flags,
43 };
44 min_address = min_address.min(entry.virtual_address);
45 max_address = max_address.max(entry.virtual_address + entry.size);
46 trace!("Mapping segment: {:x?}", entry);
47 vm.map(&entry);
48
49 file.seek(segment.offset())?;
51
52 let ptr = segment_virtual as *mut u8;
53 let slice =
54 unsafe { core::slice::from_raw_parts_mut(ptr, segment.file_size() as usize) };
55
56 assert_eq!(file.read(slice)?, segment.file_size());
58 }
59 elf::ElfProgramType::ProgramHeader => {
60 phdr_address = segment.virtual_address() as usize;
61 }
62 _ => {}
63 }
64 }
65
66 for section in elf.sections() {
67 if section.name() == ".eh_frame" {
68 process_meta.eh_frame_address = section.address() as usize;
69 process_meta.eh_frame_size = section.size() as usize;
70 } else if section.name() == ".text" {
71 process_meta.text_address = section.address() as usize;
72 process_meta.text_size = section.size() as usize;
73 }
74 }
75
76 process_meta.image_base = min_address;
77 process_meta.image_size = max_address - min_address;
78 assert!(phdr_address >= min_address && phdr_address < max_address);
79 process_meta.program_headers_offset = phdr_address - min_address;
80
81 if process_meta.eh_frame_address < min_address || process_meta.eh_frame_address >= max_address {
83 process_meta.eh_frame_address = 0;
84 process_meta.eh_frame_size = 0;
85 }
86
87 old_vm.switch_to_this();
89 cpu::cpu().pop_cli();
91
92 Ok((min_address, max_address))
93}