xref: /DragonOS/kernel/src/process/exec.rs (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1 use core::{fmt::Debug, ptr::null};
2 
3 use alloc::{collections::BTreeMap, ffi::CString, 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 use super::ProcessManager;
20 
21 /// 系统支持的所有二进制文件加载器的列表
22 const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
23 
24 pub trait BinaryLoader: 'static + Debug {
25     /// 检查二进制文件是否为当前加载器支持的格式
26     fn probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
27 
28     fn load(
29         &'static self,
30         param: &mut ExecParam,
31         head_buf: &[u8],
32     ) -> Result<BinaryLoaderResult, ExecError>;
33 }
34 
35 /// 二进制文件加载结果
36 #[derive(Debug)]
37 pub struct BinaryLoaderResult {
38     /// 程序入口地址
39     entry_point: VirtAddr,
40 }
41 
42 impl BinaryLoaderResult {
43     pub fn new(entry_point: VirtAddr) -> Self {
44         Self { entry_point }
45     }
46 
47     pub fn entry_point(&self) -> VirtAddr {
48         self.entry_point
49     }
50 }
51 
52 #[allow(dead_code)]
53 #[derive(Debug)]
54 pub enum ExecError {
55     /// 二进制文件不可执行
56     NotExecutable,
57     /// 二进制文件不是当前架构的
58     WrongArchitecture,
59     /// 访问权限不足
60     PermissionDenied,
61     /// 不支持的操作
62     NotSupported,
63     /// 解析文件本身的时候出现错误(比如一些字段本身不合法)
64     ParseError,
65     /// 内存不足
66     OutOfMemory,
67     /// 参数错误
68     InvalidParemeter,
69     /// 无效的地址
70     BadAddress(Option<VirtAddr>),
71     Other(String),
72 }
73 impl From<ExecError> for SystemError {
74     fn from(val: ExecError) -> Self {
75         match val {
76             ExecError::NotExecutable => SystemError::ENOEXEC,
77             ExecError::WrongArchitecture => SystemError::ENOEXEC,
78             ExecError::PermissionDenied => SystemError::EACCES,
79             ExecError::NotSupported => SystemError::ENOSYS,
80             ExecError::ParseError => SystemError::ENOEXEC,
81             ExecError::OutOfMemory => SystemError::ENOMEM,
82             ExecError::InvalidParemeter => SystemError::EINVAL,
83             ExecError::BadAddress(_addr) => SystemError::EFAULT,
84             ExecError::Other(_msg) => SystemError::ENOEXEC,
85         }
86     }
87 }
88 
89 bitflags! {
90     pub struct ExecParamFlags: u32 {
91         // 是否以可执行文件的形式加载
92         const EXEC = 1 << 0;
93     }
94 }
95 
96 #[derive(Debug)]
97 pub struct ExecParam {
98     file: 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 ExecParam {
116     pub fn new(
117         file_path: &str,
118         vm: Arc<AddressSpace>,
119         flags: ExecParamFlags,
120     ) -> Result<Self, SystemError> {
121         let inode = ROOT_INODE().lookup(file_path)?;
122 
123         // 读取文件头部,用于判断文件类型
124         let file = File::new(inode, FileMode::O_RDONLY)?;
125 
126         Ok(Self {
127             file,
128             vm,
129             flags,
130             init_info: ProcInitInfo::new(ProcessManager::current_pcb().basic().name()),
131         })
132     }
133 
134     pub fn vm(&self) -> &Arc<AddressSpace> {
135         &self.vm
136     }
137 
138     pub fn flags(&self) -> &ExecParamFlags {
139         &self.flags
140     }
141 
142     pub fn init_info(&self) -> &ProcInitInfo {
143         &self.init_info
144     }
145 
146     pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
147         &mut self.init_info
148     }
149 
150     /// 获取加载模式
151     pub fn load_mode(&self) -> ExecLoadMode {
152         if self.flags.contains(ExecParamFlags::EXEC) {
153             ExecLoadMode::Exec
154         } else {
155             ExecLoadMode::DSO
156         }
157     }
158 
159     pub fn file_mut(&mut self) -> &mut File {
160         &mut self.file
161     }
162 }
163 
164 /// ## 加载二进制文件
165 pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
166     // 读取文件头部,用于判断文件类型
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     // debug!("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     // debug!("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     // debug!("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     // debug!("load_binary_file: load success: {result:?}");
194     return Ok(result);
195 }
196 
197 /// 程序初始化信息,这些信息会被压入用户栈中
198 #[derive(Debug)]
199 pub struct ProcInitInfo {
200     pub proc_name: CString,
201     pub args: Vec<CString>,
202     pub envs: Vec<CString>,
203     pub auxv: BTreeMap<u8, usize>,
204 }
205 
206 impl ProcInitInfo {
207     pub fn new(proc_name: &str) -> Self {
208         Self {
209             proc_name: CString::new(proc_name).unwrap_or(CString::new("").unwrap()),
210             args: Vec::new(),
211             envs: Vec::new(),
212             auxv: BTreeMap::new(),
213         }
214     }
215 
216     /// 把程序初始化信息压入用户栈中
217     /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
218     ///
219     /// ## 返回值
220     ///
221     /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
222     pub unsafe fn push_at(
223         &self,
224         ustack: &mut UserStack,
225     ) -> Result<(VirtAddr, VirtAddr), SystemError> {
226         // 先把程序的名称压入栈中
227         self.push_str(ustack, &self.proc_name)?;
228 
229         // 然后把环境变量压入栈中
230         let envps = self
231             .envs
232             .iter()
233             .map(|s| {
234                 self.push_str(ustack, s).expect("push_str failed");
235                 ustack.sp()
236             })
237             .collect::<Vec<_>>();
238         // 然后把参数压入栈中
239         let argps = self
240             .args
241             .iter()
242             .map(|s| {
243                 self.push_str(ustack, s).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 
270     fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
271         let mut sp = ustack.sp();
272         sp -= core::mem::size_of_val(slice);
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 
284     fn push_str(&self, ustack: &mut UserStack, s: &CString) -> Result<(), SystemError> {
285         let bytes = s.as_bytes_with_nul();
286         self.push_slice(ustack, bytes)?;
287         return Ok(());
288     }
289 }
290