xref: /DragonOS/kernel/src/process/exec.rs (revision ddb9d91712b6e87aa15b9cc4a8fdec8ae0996a5e)
1 use core::{fmt::Debug, ptr::null};
2 
3 use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
4 
5 use crate::{
6     filesystem::vfs::io::SeekFrom,
7     filesystem::vfs::{
8         file::{File, FileMode},
9         ROOT_INODE,
10     },
11     libs::elf::ELF_LOADER,
12     mm::{
13         ucontext::{AddressSpace, UserStack},
14         VirtAddr,
15     },
16     syscall::SystemError,
17 };
18 
19 /// 系统支持的所有二进制文件加载器的列表
20 const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
21 
22 pub trait BinaryLoader: 'static + Debug {
23     /// 检查二进制文件是否为当前加载器支持的格式
24     fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
25 
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 {
41     pub fn new(entry_point: VirtAddr) -> Self {
42         Self { entry_point }
43     }
44 
45     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 {
73     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<'a> {
97     file_path: &'a str,
98     file: Option<File>,
99     vm: Arc<AddressSpace>,
100     /// 一些标志位
101     flags: ExecParamFlags,
102     /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
103     init_info: ProcInitInfo,
104 }
105 
106 #[derive(Debug, Eq, PartialEq)]
107 pub enum ExecLoadMode {
108     /// 以可执行文件的形式加载
109     Exec,
110     /// 以动态链接库的形式加载
111     DSO,
112 }
113 
114 #[allow(dead_code)]
115 impl<'a> ExecParam<'a> {
116     pub fn new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self {
117         Self {
118             file_path,
119             file: None,
120             vm,
121             flags,
122             init_info: ProcInitInfo::new(),
123         }
124     }
125 
126     pub fn file_path(&self) -> &'a str {
127         self.file_path
128     }
129 
130     pub fn vm(&self) -> &Arc<AddressSpace> {
131         &self.vm
132     }
133 
134     pub fn flags(&self) -> &ExecParamFlags {
135         &self.flags
136     }
137 
138     pub fn init_info(&self) -> &ProcInitInfo {
139         &self.init_info
140     }
141 
142     pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
143         &mut self.init_info
144     }
145 
146     /// 获取加载模式
147     pub fn load_mode(&self) -> ExecLoadMode {
148         if self.flags.contains(ExecParamFlags::EXEC) {
149             ExecLoadMode::Exec
150         } else {
151             ExecLoadMode::DSO
152         }
153     }
154 
155     pub fn file_mut(&mut self) -> &mut File {
156         self.file.as_mut().unwrap()
157     }
158 }
159 
160 /// ## 加载二进制文件
161 pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
162     let inode = ROOT_INODE().lookup(param.file_path)?;
163 
164     // 读取文件头部,用于判断文件类型
165     let file = File::new(inode, FileMode::O_RDONLY)?;
166     param.file = Some(file);
167     let mut head_buf = [0u8; 512];
168     param.file_mut().lseek(SeekFrom::SeekSet(0))?;
169     let _bytes = param.file_mut().read(512, &mut head_buf)?;
170     // kdebug!("load_binary_file: read {} bytes", _bytes);
171 
172     let mut loader = None;
173     for bl in BINARY_LOADERS.iter() {
174         let probe_result = bl.probe(param, &head_buf);
175         if probe_result.is_ok() {
176             loader = Some(bl);
177             break;
178         }
179     }
180     // kdebug!("load_binary_file: loader: {:?}", loader);
181     if loader.is_none() {
182         return Err(SystemError::ENOEXEC);
183     }
184 
185     let loader: &&dyn BinaryLoader = loader.unwrap();
186     assert!(param.vm().is_current());
187     // kdebug!("load_binary_file: to load with param: {:?}", param);
188 
189     let result: BinaryLoaderResult = loader
190         .load(param, &head_buf)
191         .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
192 
193     // kdebug!("load_binary_file: load success");
194     return Ok(result);
195 }
196 
197 /// 程序初始化信息,这些信息会被压入用户栈中
198 #[derive(Debug)]
199 pub struct ProcInitInfo {
200     pub args: Vec<String>,
201     pub envs: Vec<String>,
202     pub auxv: BTreeMap<u8, usize>,
203 }
204 
205 impl ProcInitInfo {
206     pub fn new() -> Self {
207         Self {
208             args: Vec::new(),
209             envs: Vec::new(),
210             auxv: BTreeMap::new(),
211         }
212     }
213 
214     /// 把程序初始化信息压入用户栈中
215     /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
216     ///
217     /// ## 返回值
218     ///
219     /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
220     pub unsafe fn push_at(
221         &self,
222         ustack: &mut UserStack,
223     ) -> Result<(VirtAddr, VirtAddr), SystemError> {
224         // 先把程序的名称压入栈中
225         self.push_str(ustack, self.args[0].as_str())?;
226 
227         // 然后把环境变量压入栈中
228         let envps = self
229             .envs
230             .iter()
231             .map(|s| {
232                 self.push_str(ustack, s.as_str()).expect("push_str failed");
233                 ustack.sp()
234             })
235             .collect::<Vec<_>>();
236 
237         // 然后把参数压入栈中
238         let argps = self
239             .args
240             .iter()
241             .map(|s| {
242                 self.push_str(ustack, s.as_str()).expect("push_str failed");
243                 ustack.sp()
244             })
245             .collect::<Vec<_>>();
246 
247         // 压入auxv
248         self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
249         for (&k, &v) in self.auxv.iter() {
250             self.push_slice(ustack, &[k as usize, v])?;
251         }
252 
253         // 把环境变量指针压入栈中
254         self.push_slice(ustack, &[null::<u8>()])?;
255         self.push_slice(ustack, envps.as_slice())?;
256 
257         // 把参数指针压入栈中
258         self.push_slice(ustack, &[null::<u8>()])?;
259         self.push_slice(ustack, argps.as_slice())?;
260 
261         let argv_ptr = ustack.sp();
262 
263         // 把argc压入栈中
264         self.push_slice(ustack, &[self.args.len()])?;
265 
266         return Ok((ustack.sp(), argv_ptr));
267     }
268 
269     fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
270         let mut sp = ustack.sp();
271         sp -= slice.len() * core::mem::size_of::<T>();
272         sp -= sp.data() % core::mem::align_of::<T>();
273 
274         unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
275             .copy_from_slice(slice);
276         unsafe {
277             ustack.set_sp(sp);
278         }
279 
280         return Ok(());
281     }
282 
283     fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
284         self.push_slice(ustack, &[b'\0'])?;
285         self.push_slice(ustack, s.as_bytes())?;
286         return Ok(());
287     }
288 }
289