1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::panic;
use crate::mem;
use crate::arch;
use crate::page;
use crate::process;
use crate::symbols::*;
use crate::{info, println};
#[repr(C)]
pub struct ELFHeader {
pub magic: u32,
pub elf: [u8; 12],
pub etype: u16,
pub machine: u16,
pub version: u32,
pub entry: u64,
pub phoff: u64,
pub shoff: u64,
pub flags: u32,
pub ehsize: u16,
pub phentsize: u16,
pub phnum: u16,
pub shentsize: u16,
pub shnum: u16,
pub shstrndx: u16,
}
#[repr(C)]
pub struct ProgramHeader {
pub ptype: u32,
pub flags: u32,
pub off: u64,
pub vaddr: u64,
pub paddr: u64,
pub filesz: u64,
pub memsz: u64,
pub align: u64,
}
const ELF_PROG_LOAD: u32 = 1;
const ELF_PROG_FLAG_EXEC: u32 = 1;
const ELF_PROG_FLAG_WRITE: u32 = 2;
const ELF_PROG_FLAG_READ: u32 = 4;
const ELF_MAGIC: u32 = 0x464C457F;
pub fn parse_elf(a: &[u8], pgtable: &mut page::Table) -> u64 {
let a = a.as_ptr();
let elfhdr = unsafe { &*(a as *const ELFHeader) };
if elfhdr.magic != ELF_MAGIC {
panic!("wrong magic number");
}
let mut proghdr = unsafe {
let offset_u8 = a.offset(elfhdr.phoff as isize);
offset_u8 as *const ProgramHeader
};
for _i in 0..elfhdr.phnum {
let hdr: &ProgramHeader = unsafe {
let hdr = &*proghdr;
proghdr = proghdr.offset(1);
hdr
};
if hdr.ptype != ELF_PROG_LOAD {
continue;
}
if hdr.memsz < hdr.filesz {
panic!("bad elf: memsz");
}
if hdr.vaddr + hdr.memsz < hdr.vaddr {
panic!("bad elf: vaddr");
}
if hdr.vaddr as usize % PAGE_SIZE != 0 {
println!("{:X}", hdr.vaddr);
panic!("bad elf: vaddr align")
}
load_segment(
pgtable,
hdr.vaddr as usize,
a,
hdr.off as usize,
hdr.filesz as usize,
);
}
elfhdr.entry
}
fn load_segment(
pgtable: &mut page::Table,
vaddr: usize,
elf: *const u8,
offset: usize,
sz: usize,
) {
let num_pages = mem::align_val(sz, PAGE_ORDER) / PAGE_SIZE;
for i in 0..num_pages {
let mut seg = page::Page::new();
let src = elf as *const u8;
unsafe {
let src = src.add(offset + i * PAGE_SIZE);
core::ptr::copy(src, seg.data.as_mut_ptr(), PAGE_SIZE);
}
use page::EntryAttributes;
pgtable.map(
vaddr + i * PAGE_SIZE,
seg,
EntryAttributes::URX as usize
);
}
}