xref: /DragonOS/kernel/src/process/exec.rs (revision 865f4ba4cdce23b154844d6d297f75033f3dcf70)
140fe15e0SLoGin use core::{fmt::Debug, ptr::null};
240fe15e0SLoGin 
340fe15e0SLoGin use alloc::{collections::BTreeMap, string::String, sync::Arc, vec::Vec};
440fe15e0SLoGin 
540fe15e0SLoGin use crate::{
6b087521eSChiichen     driver::base::block::SeekFrom,
740fe15e0SLoGin     filesystem::vfs::{
840fe15e0SLoGin         file::{File, FileMode},
940fe15e0SLoGin         ROOT_INODE,
1040fe15e0SLoGin     },
1140fe15e0SLoGin     libs::elf::ELF_LOADER,
1240fe15e0SLoGin     mm::{
1340fe15e0SLoGin         ucontext::{AddressSpace, UserStack},
1440fe15e0SLoGin         VirtAddr,
1540fe15e0SLoGin     },
1640fe15e0SLoGin     syscall::SystemError,
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)]
9640fe15e0SLoGin pub struct ExecParam<'a> {
9740fe15e0SLoGin     file_path: &'a str,
9840fe15e0SLoGin     file: Option<File>,
9940fe15e0SLoGin     vm: Arc<AddressSpace>,
10040fe15e0SLoGin     /// 一些标志位
10140fe15e0SLoGin     flags: ExecParamFlags,
10240fe15e0SLoGin     /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
10340fe15e0SLoGin     init_info: ProcInitInfo,
10440fe15e0SLoGin }
10540fe15e0SLoGin 
10640fe15e0SLoGin #[derive(Debug, Eq, PartialEq)]
10740fe15e0SLoGin pub enum ExecLoadMode {
10840fe15e0SLoGin     /// 以可执行文件的形式加载
10940fe15e0SLoGin     Exec,
11040fe15e0SLoGin     /// 以动态链接库的形式加载
11140fe15e0SLoGin     DSO,
11240fe15e0SLoGin }
11340fe15e0SLoGin 
11440fe15e0SLoGin #[allow(dead_code)]
11540fe15e0SLoGin impl<'a> ExecParam<'a> {
11640fe15e0SLoGin     pub fn new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self {
11740fe15e0SLoGin         Self {
11840fe15e0SLoGin             file_path,
11940fe15e0SLoGin             file: None,
12040fe15e0SLoGin             vm,
12140fe15e0SLoGin             flags,
12240fe15e0SLoGin             init_info: ProcInitInfo::new(),
12340fe15e0SLoGin         }
12440fe15e0SLoGin     }
12540fe15e0SLoGin 
12640fe15e0SLoGin     pub fn file_path(&self) -> &'a str {
12740fe15e0SLoGin         self.file_path
12840fe15e0SLoGin     }
12940fe15e0SLoGin 
13040fe15e0SLoGin     pub fn vm(&self) -> &Arc<AddressSpace> {
13140fe15e0SLoGin         &self.vm
13240fe15e0SLoGin     }
13340fe15e0SLoGin 
13440fe15e0SLoGin     pub fn flags(&self) -> &ExecParamFlags {
13540fe15e0SLoGin         &self.flags
13640fe15e0SLoGin     }
13740fe15e0SLoGin 
13840fe15e0SLoGin     pub fn init_info(&self) -> &ProcInitInfo {
13940fe15e0SLoGin         &self.init_info
14040fe15e0SLoGin     }
14140fe15e0SLoGin 
14240fe15e0SLoGin     pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
14340fe15e0SLoGin         &mut self.init_info
14440fe15e0SLoGin     }
14540fe15e0SLoGin 
14640fe15e0SLoGin     /// 获取加载模式
14740fe15e0SLoGin     pub fn load_mode(&self) -> ExecLoadMode {
14840fe15e0SLoGin         if self.flags.contains(ExecParamFlags::EXEC) {
14940fe15e0SLoGin             ExecLoadMode::Exec
15040fe15e0SLoGin         } else {
15140fe15e0SLoGin             ExecLoadMode::DSO
15240fe15e0SLoGin         }
15340fe15e0SLoGin     }
15440fe15e0SLoGin 
15540fe15e0SLoGin     pub fn file_mut(&mut self) -> &mut File {
15640fe15e0SLoGin         self.file.as_mut().unwrap()
15740fe15e0SLoGin     }
15840fe15e0SLoGin }
15940fe15e0SLoGin 
16040fe15e0SLoGin /// ## 加载二进制文件
16140fe15e0SLoGin pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
16240fe15e0SLoGin     let inode = ROOT_INODE().lookup(param.file_path)?;
16340fe15e0SLoGin 
16440fe15e0SLoGin     // 读取文件头部,用于判断文件类型
16540fe15e0SLoGin     let file = File::new(inode, FileMode::O_RDONLY)?;
16640fe15e0SLoGin     param.file = Some(file);
16740fe15e0SLoGin     let mut head_buf = [0u8; 512];
16840fe15e0SLoGin     param.file_mut().lseek(SeekFrom::SeekSet(0))?;
16940fe15e0SLoGin     let _bytes = param.file_mut().read(512, &mut head_buf)?;
17040fe15e0SLoGin     // kdebug!("load_binary_file: read {} bytes", _bytes);
17140fe15e0SLoGin 
17240fe15e0SLoGin     let mut loader = None;
17340fe15e0SLoGin     for bl in BINARY_LOADERS.iter() {
17440fe15e0SLoGin         let probe_result = bl.probe(param, &head_buf);
17540fe15e0SLoGin         if probe_result.is_ok() {
17640fe15e0SLoGin             loader = Some(bl);
17740fe15e0SLoGin             break;
17840fe15e0SLoGin         }
17940fe15e0SLoGin     }
18040fe15e0SLoGin     // kdebug!("load_binary_file: loader: {:?}", loader);
18140fe15e0SLoGin     if loader.is_none() {
18240fe15e0SLoGin         return Err(SystemError::ENOEXEC);
18340fe15e0SLoGin     }
18440fe15e0SLoGin 
18540fe15e0SLoGin     let loader: &&dyn BinaryLoader = loader.unwrap();
18640fe15e0SLoGin     assert!(param.vm().is_current());
18740fe15e0SLoGin     // kdebug!("load_binary_file: to load with param: {:?}", param);
18840fe15e0SLoGin 
18940fe15e0SLoGin     let result: BinaryLoaderResult = loader
19040fe15e0SLoGin         .load(param, &head_buf)
19140fe15e0SLoGin         .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
19240fe15e0SLoGin 
19340fe15e0SLoGin     // kdebug!("load_binary_file: load success");
19440fe15e0SLoGin     return Ok(result);
19540fe15e0SLoGin }
19640fe15e0SLoGin 
19740fe15e0SLoGin /// 程序初始化信息,这些信息会被压入用户栈中
19840fe15e0SLoGin #[derive(Debug)]
19940fe15e0SLoGin pub struct ProcInitInfo {
200*865f4ba4SGnoCiYeH     pub proc_name: String,
20140fe15e0SLoGin     pub args: Vec<String>,
20240fe15e0SLoGin     pub envs: Vec<String>,
20340fe15e0SLoGin     pub auxv: BTreeMap<u8, usize>,
20440fe15e0SLoGin }
20540fe15e0SLoGin 
20640fe15e0SLoGin impl ProcInitInfo {
20740fe15e0SLoGin     pub fn new() -> Self {
20840fe15e0SLoGin         Self {
209*865f4ba4SGnoCiYeH             proc_name: String::new(),
21040fe15e0SLoGin             args: Vec::new(),
21140fe15e0SLoGin             envs: Vec::new(),
21240fe15e0SLoGin             auxv: BTreeMap::new(),
21340fe15e0SLoGin         }
21440fe15e0SLoGin     }
21540fe15e0SLoGin 
21640fe15e0SLoGin     /// 把程序初始化信息压入用户栈中
21740fe15e0SLoGin     /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
21840fe15e0SLoGin     ///
21940fe15e0SLoGin     /// ## 返回值
22040fe15e0SLoGin     ///
22140fe15e0SLoGin     /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
22240fe15e0SLoGin     pub unsafe fn push_at(
22340fe15e0SLoGin         &self,
22440fe15e0SLoGin         ustack: &mut UserStack,
22540fe15e0SLoGin     ) -> Result<(VirtAddr, VirtAddr), SystemError> {
22640fe15e0SLoGin         // 先把程序的名称压入栈中
227*865f4ba4SGnoCiYeH         self.push_str(ustack, &self.proc_name)?;
22840fe15e0SLoGin 
22940fe15e0SLoGin         // 然后把环境变量压入栈中
23040fe15e0SLoGin         let envps = self
23140fe15e0SLoGin             .envs
23240fe15e0SLoGin             .iter()
23340fe15e0SLoGin             .map(|s| {
23440fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
23540fe15e0SLoGin                 ustack.sp()
23640fe15e0SLoGin             })
23740fe15e0SLoGin             .collect::<Vec<_>>();
23840fe15e0SLoGin 
23940fe15e0SLoGin         // 然后把参数压入栈中
24040fe15e0SLoGin         let argps = self
24140fe15e0SLoGin             .args
24240fe15e0SLoGin             .iter()
24340fe15e0SLoGin             .map(|s| {
24440fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
24540fe15e0SLoGin                 ustack.sp()
24640fe15e0SLoGin             })
24740fe15e0SLoGin             .collect::<Vec<_>>();
24840fe15e0SLoGin 
24940fe15e0SLoGin         // 压入auxv
25040fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
25140fe15e0SLoGin         for (&k, &v) in self.auxv.iter() {
25240fe15e0SLoGin             self.push_slice(ustack, &[k as usize, v])?;
25340fe15e0SLoGin         }
25440fe15e0SLoGin 
25540fe15e0SLoGin         // 把环境变量指针压入栈中
25640fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
25740fe15e0SLoGin         self.push_slice(ustack, envps.as_slice())?;
25840fe15e0SLoGin 
25940fe15e0SLoGin         // 把参数指针压入栈中
26040fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
26140fe15e0SLoGin         self.push_slice(ustack, argps.as_slice())?;
26240fe15e0SLoGin 
26340fe15e0SLoGin         let argv_ptr = ustack.sp();
26440fe15e0SLoGin 
26540fe15e0SLoGin         // 把argc压入栈中
26640fe15e0SLoGin         self.push_slice(ustack, &[self.args.len()])?;
26740fe15e0SLoGin 
26840fe15e0SLoGin         return Ok((ustack.sp(), argv_ptr));
26940fe15e0SLoGin     }
27040fe15e0SLoGin 
27140fe15e0SLoGin     fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
27240fe15e0SLoGin         let mut sp = ustack.sp();
27340fe15e0SLoGin         sp -= slice.len() * core::mem::size_of::<T>();
27440fe15e0SLoGin         sp -= sp.data() % core::mem::align_of::<T>();
27540fe15e0SLoGin 
27640fe15e0SLoGin         unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
27740fe15e0SLoGin             .copy_from_slice(slice);
27840fe15e0SLoGin         unsafe {
27940fe15e0SLoGin             ustack.set_sp(sp);
28040fe15e0SLoGin         }
28140fe15e0SLoGin 
28240fe15e0SLoGin         return Ok(());
28340fe15e0SLoGin     }
28440fe15e0SLoGin 
28540fe15e0SLoGin     fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
28640fe15e0SLoGin         self.push_slice(ustack, &[b'\0'])?;
28740fe15e0SLoGin         self.push_slice(ustack, s.as_bytes())?;
28840fe15e0SLoGin         return Ok(());
28940fe15e0SLoGin     }
29040fe15e0SLoGin }
291