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