1 use core::{fmt::Debug, ptr::null};
2
3 use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
4 use system_error::SystemError;
5
6 use crate::{
7 driver::base::block::SeekFrom,
8 filesystem::vfs::{
9 file::{File, FileMode},
10 ROOT_INODE,
11 },
12 libs::elf::ELF_LOADER,
13 mm::{
14 ucontext::{AddressSpace, UserStack},
15 VirtAddr,
16 },
17 };
18
19 /// 系统支持的所有二进制文件加载器的列表
20 const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
21
22 pub trait BinaryLoader: 'static + Debug {
23 /// 检查二进制文件是否为当前加载器支持的格式
probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>24 fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
25
load( self: &'static Self, param: &mut ExecParam, head_buf: &[u8], ) -> Result<BinaryLoaderResult, ExecError>26 fn load(
27 self: &'static Self,
28 param: &mut ExecParam,
29 head_buf: &[u8],
30 ) -> Result<BinaryLoaderResult, ExecError>;
31 }
32
33 /// 二进制文件加载结果
34 #[derive(Debug)]
35 pub struct BinaryLoaderResult {
36 /// 程序入口地址
37 entry_point: VirtAddr,
38 }
39
40 impl BinaryLoaderResult {
new(entry_point: VirtAddr) -> Self41 pub fn new(entry_point: VirtAddr) -> Self {
42 Self { entry_point }
43 }
44
entry_point(&self) -> VirtAddr45 pub fn entry_point(&self) -> VirtAddr {
46 self.entry_point
47 }
48 }
49
50 #[allow(dead_code)]
51 #[derive(Debug)]
52 pub enum ExecError {
53 /// 二进制文件不可执行
54 NotExecutable,
55 /// 二进制文件不是当前架构的
56 WrongArchitecture,
57 /// 访问权限不足
58 PermissionDenied,
59 /// 不支持的操作
60 NotSupported,
61 /// 解析文件本身的时候出现错误(比如一些字段本身不合法)
62 ParseError,
63 /// 内存不足
64 OutOfMemory,
65 /// 参数错误
66 InvalidParemeter,
67 /// 无效的地址
68 BadAddress(Option<VirtAddr>),
69 Other(String),
70 }
71
72 impl Into<SystemError> for ExecError {
into(self) -> SystemError73 fn into(self) -> SystemError {
74 match self {
75 ExecError::NotExecutable => SystemError::ENOEXEC,
76 ExecError::WrongArchitecture => SystemError::EOPNOTSUPP_OR_ENOTSUP,
77 ExecError::PermissionDenied => SystemError::EACCES,
78 ExecError::NotSupported => SystemError::EOPNOTSUPP_OR_ENOTSUP,
79 ExecError::ParseError => SystemError::ENOEXEC,
80 ExecError::OutOfMemory => SystemError::ENOMEM,
81 ExecError::InvalidParemeter => SystemError::EINVAL,
82 ExecError::BadAddress(_addr) => SystemError::EFAULT,
83 ExecError::Other(_msg) => SystemError::ENOEXEC,
84 }
85 }
86 }
87
88 bitflags! {
89 pub struct ExecParamFlags: u32 {
90 // 是否以可执行文件的形式加载
91 const EXEC = 1 << 0;
92 }
93 }
94
95 #[derive(Debug)]
96 pub struct ExecParam {
97 file: File,
98 vm: Arc<AddressSpace>,
99 /// 一些标志位
100 flags: ExecParamFlags,
101 /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
102 init_info: ProcInitInfo,
103 }
104
105 #[derive(Debug, Eq, PartialEq)]
106 pub enum ExecLoadMode {
107 /// 以可执行文件的形式加载
108 Exec,
109 /// 以动态链接库的形式加载
110 DSO,
111 }
112
113 #[allow(dead_code)]
114 impl ExecParam {
new( file_path: &str, vm: Arc<AddressSpace>, flags: ExecParamFlags, ) -> Result<Self, SystemError>115 pub fn new(
116 file_path: &str,
117 vm: Arc<AddressSpace>,
118 flags: ExecParamFlags,
119 ) -> Result<Self, SystemError> {
120 let inode = ROOT_INODE().lookup(file_path)?;
121
122 // 读取文件头部,用于判断文件类型
123 let file = File::new(inode, FileMode::O_RDONLY)?;
124
125 Ok(Self {
126 file,
127 vm,
128 flags,
129 init_info: ProcInitInfo::new(),
130 })
131 }
132
vm(&self) -> &Arc<AddressSpace>133 pub fn vm(&self) -> &Arc<AddressSpace> {
134 &self.vm
135 }
136
flags(&self) -> &ExecParamFlags137 pub fn flags(&self) -> &ExecParamFlags {
138 &self.flags
139 }
140
init_info(&self) -> &ProcInitInfo141 pub fn init_info(&self) -> &ProcInitInfo {
142 &self.init_info
143 }
144
init_info_mut(&mut self) -> &mut ProcInitInfo145 pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
146 &mut self.init_info
147 }
148
149 /// 获取加载模式
load_mode(&self) -> ExecLoadMode150 pub fn load_mode(&self) -> ExecLoadMode {
151 if self.flags.contains(ExecParamFlags::EXEC) {
152 ExecLoadMode::Exec
153 } else {
154 ExecLoadMode::DSO
155 }
156 }
157
file_mut(&mut self) -> &mut File158 pub fn file_mut(&mut self) -> &mut File {
159 &mut self.file
160 }
161 }
162
163 /// ## 加载二进制文件
load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError>164 pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
165 // 读取文件头部,用于判断文件类型
166 let mut head_buf = [0u8; 512];
167 param.file_mut().lseek(SeekFrom::SeekSet(0))?;
168 let _bytes = param.file_mut().read(512, &mut head_buf)?;
169 // kdebug!("load_binary_file: read {} bytes", _bytes);
170
171 let mut loader = None;
172 for bl in BINARY_LOADERS.iter() {
173 let probe_result = bl.probe(param, &head_buf);
174 if probe_result.is_ok() {
175 loader = Some(bl);
176 break;
177 }
178 }
179 // kdebug!("load_binary_file: loader: {:?}", loader);
180 if loader.is_none() {
181 return Err(SystemError::ENOEXEC);
182 }
183
184 let loader: &&dyn BinaryLoader = loader.unwrap();
185 assert!(param.vm().is_current());
186 // kdebug!("load_binary_file: to load with param: {:?}", param);
187
188 let result: BinaryLoaderResult = loader
189 .load(param, &head_buf)
190 .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
191
192 // kdebug!("load_binary_file: load success");
193 return Ok(result);
194 }
195
196 /// 程序初始化信息,这些信息会被压入用户栈中
197 #[derive(Debug)]
198 pub struct ProcInitInfo {
199 pub proc_name: String,
200 pub args: Vec<String>,
201 pub envs: Vec<String>,
202 pub auxv: BTreeMap<u8, usize>,
203 }
204
205 impl ProcInitInfo {
new() -> Self206 pub fn new() -> Self {
207 Self {
208 proc_name: String::new(),
209 args: Vec::new(),
210 envs: Vec::new(),
211 auxv: BTreeMap::new(),
212 }
213 }
214
215 /// 把程序初始化信息压入用户栈中
216 /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
217 ///
218 /// ## 返回值
219 ///
220 /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
push_at( &self, ustack: &mut UserStack, ) -> Result<(VirtAddr, VirtAddr), SystemError>221 pub unsafe fn push_at(
222 &self,
223 ustack: &mut UserStack,
224 ) -> Result<(VirtAddr, VirtAddr), SystemError> {
225 // 先把程序的名称压入栈中
226 self.push_str(ustack, &self.proc_name)?;
227
228 // 然后把环境变量压入栈中
229 let envps = self
230 .envs
231 .iter()
232 .map(|s| {
233 self.push_str(ustack, s.as_str()).expect("push_str failed");
234 ustack.sp()
235 })
236 .collect::<Vec<_>>();
237
238 // 然后把参数压入栈中
239 let argps = self
240 .args
241 .iter()
242 .map(|s| {
243 self.push_str(ustack, s.as_str()).expect("push_str failed");
244 ustack.sp()
245 })
246 .collect::<Vec<_>>();
247
248 // 压入auxv
249 self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
250 for (&k, &v) in self.auxv.iter() {
251 self.push_slice(ustack, &[k as usize, v])?;
252 }
253
254 // 把环境变量指针压入栈中
255 self.push_slice(ustack, &[null::<u8>()])?;
256 self.push_slice(ustack, envps.as_slice())?;
257
258 // 把参数指针压入栈中
259 self.push_slice(ustack, &[null::<u8>()])?;
260 self.push_slice(ustack, argps.as_slice())?;
261
262 let argv_ptr = ustack.sp();
263
264 // 把argc压入栈中
265 self.push_slice(ustack, &[self.args.len()])?;
266
267 return Ok((ustack.sp(), argv_ptr));
268 }
269
push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError>270 fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
271 let mut sp = ustack.sp();
272 sp -= slice.len() * core::mem::size_of::<T>();
273 sp -= sp.data() % core::mem::align_of::<T>();
274
275 unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
276 .copy_from_slice(slice);
277 unsafe {
278 ustack.set_sp(sp);
279 }
280
281 return Ok(());
282 }
283
push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError>284 fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
285 self.push_slice(ustack, &[b'\0'])?;
286 self.push_slice(ustack, s.as_bytes())?;
287 return Ok(());
288 }
289 }
290