1use crate::arch::x86_64::paging::get_root;
3use crate::arch::x86_64::paging::map_vma;
4use crate::black_magic;
5use crate::fs;
6use crate::mm::vmm::{VMArea, VMPerms, VMType};
7use crate::proc::task::Task;
8use alloc::string::String;
9use core::ops::Range;
10use core::str::FromStr;
11use xmas_elf::header::HeaderPt2;
12use xmas_elf::program::{ProgramHeader, Type};
13use xmas_elf::ElfFile;
14pub fn cat_elf(f: &fs::File) {
15 let elf = ElfFile::new(f.file).unwrap();
16 println!("{:?}", elf.header);
17}
18
19pub fn load(file: &fs::File) -> Option<u64> {
25 let task = Task::current().unwrap();
26 let mm = &mut task.mm;
27 let elf = ElfFile::new(file.file).ok()?;
28 let pt_root = get_root();
29
30 let mut header_ok = true;
31 for hdr in elf.program_iter() {
32 if let ProgramHeader::Ph32(_) = hdr {
36 println!("not an 64 bit elf header");
37 header_ok = false;
38 break;
39 }
40 let h = match hdr {
44 ProgramHeader::Ph64(h) => h,
45 _ => panic!(),
46 };
47
48 if h.get_type() != Ok(Type::Load) {
50 continue;
51 }
52
53 sprintln!(
54 "{:?} VA:{:#X}+{:#X}, FILE:{:#X}+{:#X}",
55 h.type_,
56 h.virtual_addr,
57 h.mem_size,
58 h.offset,
59 h.file_size,
60 );
61 let fstart = h.offset as usize;
62 let fend = fstart + h.file_size as usize;
63 if fstart >= file.file.len() || fend >= file.file.len() {
64 println!("bad size");
65 }
66
67 if h.mem_size > h.file_size {
68 sprintln!(
69 "including BSS: {:#X} - {:#X}",
70 h.virtual_addr + h.file_size,
71 h.virtual_addr + h.mem_size
72 );
73 }
74 let vma = VMArea {
78 vm_range: Range::<u64> {
79 start: h.virtual_addr,
80 end: h.virtual_addr + h.mem_size,
81 },
82 tag: String::from_str("USER BITS").unwrap(),
83 user_perms: VMPerms::all(),
84 backing: match h.file_size {
85 0 => VMType::ANOM,
86 _ => VMType::FILE(unsafe {
87 black_magic::make_static(&file.file[fstart..fend])
88 }),
89 },
90 };
91
92 let res = unsafe { map_vma(pt_root, &vma, true) };
93 if !res {
94 println!("failed to push vma: {:#X?}", &vma);
95 return None;
96 }
97 mm.vmas.push(vma);
98 }
99
100 if !header_ok {
101 println!("bad header");
102 return None;
103 }
104 match &elf.header.pt2 {
105 HeaderPt2::Header64(pt2) => return Some(pt2.entry_point),
106 _ => {
107 println!("bad header, not entry point");
108 return None;
109 }
110 };
111}