xref: /DragonOS/kernel/src/process/exec.rs (revision a02ce654cf0166720f8569827d0c5b2dfd0ca95a)
140fe15e0SLoGin use core::{fmt::Debug, ptr::null};
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
491e9d4abSLoGin use system_error::SystemError;
540fe15e0SLoGin 
640fe15e0SLoGin use crate::{
7b087521eSChiichen     driver::base::block::SeekFrom,
840fe15e0SLoGin     filesystem::vfs::{
940fe15e0SLoGin         file::{File, FileMode},
1040fe15e0SLoGin         ROOT_INODE,
1140fe15e0SLoGin     },
1240fe15e0SLoGin     libs::elf::ELF_LOADER,
1340fe15e0SLoGin     mm::{
1440fe15e0SLoGin         ucontext::{AddressSpace, UserStack},
1540fe15e0SLoGin         VirtAddr,
1640fe15e0SLoGin     },
1740fe15e0SLoGin };
1840fe15e0SLoGin 
1940fe15e0SLoGin /// 系统支持的所有二进制文件加载器的列表
2040fe15e0SLoGin const BINARY_LOADERS: [&'static dyn BinaryLoader; 1] = [&ELF_LOADER];
2140fe15e0SLoGin 
2240fe15e0SLoGin pub trait BinaryLoader: 'static + Debug {
2340fe15e0SLoGin     /// 检查二进制文件是否为当前加载器支持的格式
2440fe15e0SLoGin     fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
2540fe15e0SLoGin 
2640fe15e0SLoGin     fn load(
2740fe15e0SLoGin         self: &'static Self,
2840fe15e0SLoGin         param: &mut ExecParam,
2940fe15e0SLoGin         head_buf: &[u8],
3040fe15e0SLoGin     ) -> Result<BinaryLoaderResult, ExecError>;
3140fe15e0SLoGin }
3240fe15e0SLoGin 
3340fe15e0SLoGin /// 二进制文件加载结果
3440fe15e0SLoGin #[derive(Debug)]
3540fe15e0SLoGin pub struct BinaryLoaderResult {
3640fe15e0SLoGin     /// 程序入口地址
3740fe15e0SLoGin     entry_point: VirtAddr,
3840fe15e0SLoGin }
3940fe15e0SLoGin 
4040fe15e0SLoGin impl BinaryLoaderResult {
4140fe15e0SLoGin     pub fn new(entry_point: VirtAddr) -> Self {
4240fe15e0SLoGin         Self { entry_point }
4340fe15e0SLoGin     }
4440fe15e0SLoGin 
4540fe15e0SLoGin     pub fn entry_point(&self) -> VirtAddr {
4640fe15e0SLoGin         self.entry_point
4740fe15e0SLoGin     }
4840fe15e0SLoGin }
4940fe15e0SLoGin 
5040fe15e0SLoGin #[allow(dead_code)]
5140fe15e0SLoGin #[derive(Debug)]
5240fe15e0SLoGin pub enum ExecError {
5340fe15e0SLoGin     /// 二进制文件不可执行
5440fe15e0SLoGin     NotExecutable,
5540fe15e0SLoGin     /// 二进制文件不是当前架构的
5640fe15e0SLoGin     WrongArchitecture,
5740fe15e0SLoGin     /// 访问权限不足
5840fe15e0SLoGin     PermissionDenied,
5940fe15e0SLoGin     /// 不支持的操作
6040fe15e0SLoGin     NotSupported,
6140fe15e0SLoGin     /// 解析文件本身的时候出现错误(比如一些字段本身不合法)
6240fe15e0SLoGin     ParseError,
6340fe15e0SLoGin     /// 内存不足
6440fe15e0SLoGin     OutOfMemory,
6540fe15e0SLoGin     /// 参数错误
6640fe15e0SLoGin     InvalidParemeter,
6740fe15e0SLoGin     /// 无效的地址
6840fe15e0SLoGin     BadAddress(Option<VirtAddr>),
6940fe15e0SLoGin     Other(String),
7040fe15e0SLoGin }
7140fe15e0SLoGin 
7240fe15e0SLoGin impl Into<SystemError> for ExecError {
7340fe15e0SLoGin     fn into(self) -> SystemError {
7440fe15e0SLoGin         match self {
7540fe15e0SLoGin             ExecError::NotExecutable => SystemError::ENOEXEC,
7640fe15e0SLoGin             ExecError::WrongArchitecture => SystemError::EOPNOTSUPP_OR_ENOTSUP,
7740fe15e0SLoGin             ExecError::PermissionDenied => SystemError::EACCES,
7840fe15e0SLoGin             ExecError::NotSupported => SystemError::EOPNOTSUPP_OR_ENOTSUP,
7940fe15e0SLoGin             ExecError::ParseError => SystemError::ENOEXEC,
8040fe15e0SLoGin             ExecError::OutOfMemory => SystemError::ENOMEM,
8140fe15e0SLoGin             ExecError::InvalidParemeter => SystemError::EINVAL,
8240fe15e0SLoGin             ExecError::BadAddress(_addr) => SystemError::EFAULT,
8340fe15e0SLoGin             ExecError::Other(_msg) => SystemError::ENOEXEC,
8440fe15e0SLoGin         }
8540fe15e0SLoGin     }
8640fe15e0SLoGin }
8740fe15e0SLoGin 
8840fe15e0SLoGin bitflags! {
8940fe15e0SLoGin     pub struct ExecParamFlags: u32 {
9040fe15e0SLoGin         // 是否以可执行文件的形式加载
9140fe15e0SLoGin         const EXEC = 1 << 0;
9240fe15e0SLoGin     }
9340fe15e0SLoGin }
9440fe15e0SLoGin 
9540fe15e0SLoGin #[derive(Debug)]
96*a02ce654SChiichen pub struct ExecParam {
97*a02ce654SChiichen     file: File,
9840fe15e0SLoGin     vm: Arc<AddressSpace>,
9940fe15e0SLoGin     /// 一些标志位
10040fe15e0SLoGin     flags: ExecParamFlags,
10140fe15e0SLoGin     /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
10240fe15e0SLoGin     init_info: ProcInitInfo,
10340fe15e0SLoGin }
10440fe15e0SLoGin 
10540fe15e0SLoGin #[derive(Debug, Eq, PartialEq)]
10640fe15e0SLoGin pub enum ExecLoadMode {
10740fe15e0SLoGin     /// 以可执行文件的形式加载
10840fe15e0SLoGin     Exec,
10940fe15e0SLoGin     /// 以动态链接库的形式加载
11040fe15e0SLoGin     DSO,
11140fe15e0SLoGin }
11240fe15e0SLoGin 
11340fe15e0SLoGin #[allow(dead_code)]
114*a02ce654SChiichen impl ExecParam {
115*a02ce654SChiichen     pub fn new(
116*a02ce654SChiichen         file_path: &str,
117*a02ce654SChiichen         vm: Arc<AddressSpace>,
118*a02ce654SChiichen         flags: ExecParamFlags,
119*a02ce654SChiichen     ) -> Result<Self, SystemError> {
120*a02ce654SChiichen         let inode = ROOT_INODE().lookup(file_path)?;
121*a02ce654SChiichen 
122*a02ce654SChiichen         // 读取文件头部,用于判断文件类型
123*a02ce654SChiichen         let file = File::new(inode, FileMode::O_RDONLY)?;
124*a02ce654SChiichen 
125*a02ce654SChiichen         Ok(Self {
126*a02ce654SChiichen             file,
12740fe15e0SLoGin             vm,
12840fe15e0SLoGin             flags,
12940fe15e0SLoGin             init_info: ProcInitInfo::new(),
130*a02ce654SChiichen         })
13140fe15e0SLoGin     }
13240fe15e0SLoGin 
13340fe15e0SLoGin     pub fn vm(&self) -> &Arc<AddressSpace> {
13440fe15e0SLoGin         &self.vm
13540fe15e0SLoGin     }
13640fe15e0SLoGin 
13740fe15e0SLoGin     pub fn flags(&self) -> &ExecParamFlags {
13840fe15e0SLoGin         &self.flags
13940fe15e0SLoGin     }
14040fe15e0SLoGin 
14140fe15e0SLoGin     pub fn init_info(&self) -> &ProcInitInfo {
14240fe15e0SLoGin         &self.init_info
14340fe15e0SLoGin     }
14440fe15e0SLoGin 
14540fe15e0SLoGin     pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
14640fe15e0SLoGin         &mut self.init_info
14740fe15e0SLoGin     }
14840fe15e0SLoGin 
14940fe15e0SLoGin     /// 获取加载模式
15040fe15e0SLoGin     pub fn load_mode(&self) -> ExecLoadMode {
15140fe15e0SLoGin         if self.flags.contains(ExecParamFlags::EXEC) {
15240fe15e0SLoGin             ExecLoadMode::Exec
15340fe15e0SLoGin         } else {
15440fe15e0SLoGin             ExecLoadMode::DSO
15540fe15e0SLoGin         }
15640fe15e0SLoGin     }
15740fe15e0SLoGin 
15840fe15e0SLoGin     pub fn file_mut(&mut self) -> &mut File {
159*a02ce654SChiichen         &mut self.file
16040fe15e0SLoGin     }
16140fe15e0SLoGin }
16240fe15e0SLoGin 
16340fe15e0SLoGin /// ## 加载二进制文件
16440fe15e0SLoGin pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
16540fe15e0SLoGin     // 读取文件头部,用于判断文件类型
16640fe15e0SLoGin     let mut head_buf = [0u8; 512];
16740fe15e0SLoGin     param.file_mut().lseek(SeekFrom::SeekSet(0))?;
16840fe15e0SLoGin     let _bytes = param.file_mut().read(512, &mut head_buf)?;
16940fe15e0SLoGin     // kdebug!("load_binary_file: read {} bytes", _bytes);
17040fe15e0SLoGin 
17140fe15e0SLoGin     let mut loader = None;
17240fe15e0SLoGin     for bl in BINARY_LOADERS.iter() {
17340fe15e0SLoGin         let probe_result = bl.probe(param, &head_buf);
17440fe15e0SLoGin         if probe_result.is_ok() {
17540fe15e0SLoGin             loader = Some(bl);
17640fe15e0SLoGin             break;
17740fe15e0SLoGin         }
17840fe15e0SLoGin     }
17940fe15e0SLoGin     // kdebug!("load_binary_file: loader: {:?}", loader);
18040fe15e0SLoGin     if loader.is_none() {
18140fe15e0SLoGin         return Err(SystemError::ENOEXEC);
18240fe15e0SLoGin     }
18340fe15e0SLoGin 
18440fe15e0SLoGin     let loader: &&dyn BinaryLoader = loader.unwrap();
18540fe15e0SLoGin     assert!(param.vm().is_current());
18640fe15e0SLoGin     // kdebug!("load_binary_file: to load with param: {:?}", param);
18740fe15e0SLoGin 
18840fe15e0SLoGin     let result: BinaryLoaderResult = loader
18940fe15e0SLoGin         .load(param, &head_buf)
19040fe15e0SLoGin         .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
19140fe15e0SLoGin 
19240fe15e0SLoGin     // kdebug!("load_binary_file: load success");
19340fe15e0SLoGin     return Ok(result);
19440fe15e0SLoGin }
19540fe15e0SLoGin 
19640fe15e0SLoGin /// 程序初始化信息,这些信息会被压入用户栈中
19740fe15e0SLoGin #[derive(Debug)]
19840fe15e0SLoGin pub struct ProcInitInfo {
199865f4ba4SGnoCiYeH     pub proc_name: String,
20040fe15e0SLoGin     pub args: Vec<String>,
20140fe15e0SLoGin     pub envs: Vec<String>,
20240fe15e0SLoGin     pub auxv: BTreeMap<u8, usize>,
20340fe15e0SLoGin }
20440fe15e0SLoGin 
20540fe15e0SLoGin impl ProcInitInfo {
20640fe15e0SLoGin     pub fn new() -> Self {
20740fe15e0SLoGin         Self {
208865f4ba4SGnoCiYeH             proc_name: String::new(),
20940fe15e0SLoGin             args: Vec::new(),
21040fe15e0SLoGin             envs: Vec::new(),
21140fe15e0SLoGin             auxv: BTreeMap::new(),
21240fe15e0SLoGin         }
21340fe15e0SLoGin     }
21440fe15e0SLoGin 
21540fe15e0SLoGin     /// 把程序初始化信息压入用户栈中
21640fe15e0SLoGin     /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
21740fe15e0SLoGin     ///
21840fe15e0SLoGin     /// ## 返回值
21940fe15e0SLoGin     ///
22040fe15e0SLoGin     /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
22140fe15e0SLoGin     pub unsafe fn push_at(
22240fe15e0SLoGin         &self,
22340fe15e0SLoGin         ustack: &mut UserStack,
22440fe15e0SLoGin     ) -> Result<(VirtAddr, VirtAddr), SystemError> {
22540fe15e0SLoGin         // 先把程序的名称压入栈中
226865f4ba4SGnoCiYeH         self.push_str(ustack, &self.proc_name)?;
22740fe15e0SLoGin 
22840fe15e0SLoGin         // 然后把环境变量压入栈中
22940fe15e0SLoGin         let envps = self
23040fe15e0SLoGin             .envs
23140fe15e0SLoGin             .iter()
23240fe15e0SLoGin             .map(|s| {
23340fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
23440fe15e0SLoGin                 ustack.sp()
23540fe15e0SLoGin             })
23640fe15e0SLoGin             .collect::<Vec<_>>();
23740fe15e0SLoGin 
23840fe15e0SLoGin         // 然后把参数压入栈中
23940fe15e0SLoGin         let argps = self
24040fe15e0SLoGin             .args
24140fe15e0SLoGin             .iter()
24240fe15e0SLoGin             .map(|s| {
24340fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
24440fe15e0SLoGin                 ustack.sp()
24540fe15e0SLoGin             })
24640fe15e0SLoGin             .collect::<Vec<_>>();
24740fe15e0SLoGin 
24840fe15e0SLoGin         // 压入auxv
24940fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
25040fe15e0SLoGin         for (&k, &v) in self.auxv.iter() {
25140fe15e0SLoGin             self.push_slice(ustack, &[k as usize, v])?;
25240fe15e0SLoGin         }
25340fe15e0SLoGin 
25440fe15e0SLoGin         // 把环境变量指针压入栈中
25540fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
25640fe15e0SLoGin         self.push_slice(ustack, envps.as_slice())?;
25740fe15e0SLoGin 
25840fe15e0SLoGin         // 把参数指针压入栈中
25940fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
26040fe15e0SLoGin         self.push_slice(ustack, argps.as_slice())?;
26140fe15e0SLoGin 
26240fe15e0SLoGin         let argv_ptr = ustack.sp();
26340fe15e0SLoGin 
26440fe15e0SLoGin         // 把argc压入栈中
26540fe15e0SLoGin         self.push_slice(ustack, &[self.args.len()])?;
26640fe15e0SLoGin 
26740fe15e0SLoGin         return Ok((ustack.sp(), argv_ptr));
26840fe15e0SLoGin     }
26940fe15e0SLoGin 
27040fe15e0SLoGin     fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
27140fe15e0SLoGin         let mut sp = ustack.sp();
27240fe15e0SLoGin         sp -= slice.len() * core::mem::size_of::<T>();
27340fe15e0SLoGin         sp -= sp.data() % core::mem::align_of::<T>();
27440fe15e0SLoGin 
27540fe15e0SLoGin         unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
27640fe15e0SLoGin             .copy_from_slice(slice);
27740fe15e0SLoGin         unsafe {
27840fe15e0SLoGin             ustack.set_sp(sp);
27940fe15e0SLoGin         }
28040fe15e0SLoGin 
28140fe15e0SLoGin         return Ok(());
28240fe15e0SLoGin     }
28340fe15e0SLoGin 
28440fe15e0SLoGin     fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
28540fe15e0SLoGin         self.push_slice(ustack, &[b'\0'])?;
28640fe15e0SLoGin         self.push_slice(ustack, s.as_bytes())?;
28740fe15e0SLoGin         return Ok(());
28840fe15e0SLoGin     }
28940fe15e0SLoGin }
290