xref: /DragonOS/kernel/src/process/exec.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
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     /// 检查二进制文件是否为当前加载器支持的格式
24b5b571e0SLoGin     fn probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
2540fe15e0SLoGin 
2640fe15e0SLoGin     fn load(
27b5b571e0SLoGin         &'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 }
71b5b571e0SLoGin impl From<ExecError> for SystemError {
72b5b571e0SLoGin     fn from(val: ExecError) -> Self {
73b5b571e0SLoGin         match val {
7440fe15e0SLoGin             ExecError::NotExecutable => SystemError::ENOEXEC,
75b5b571e0SLoGin             ExecError::WrongArchitecture => SystemError::ENOEXEC,
7640fe15e0SLoGin             ExecError::PermissionDenied => SystemError::EACCES,
77b5b571e0SLoGin             ExecError::NotSupported => SystemError::ENOSYS,
7840fe15e0SLoGin             ExecError::ParseError => SystemError::ENOEXEC,
7940fe15e0SLoGin             ExecError::OutOfMemory => SystemError::ENOMEM,
8040fe15e0SLoGin             ExecError::InvalidParemeter => SystemError::EINVAL,
8140fe15e0SLoGin             ExecError::BadAddress(_addr) => SystemError::EFAULT,
8240fe15e0SLoGin             ExecError::Other(_msg) => SystemError::ENOEXEC,
8340fe15e0SLoGin         }
8440fe15e0SLoGin     }
8540fe15e0SLoGin }
8640fe15e0SLoGin 
8740fe15e0SLoGin bitflags! {
8840fe15e0SLoGin     pub struct ExecParamFlags: u32 {
8940fe15e0SLoGin         // 是否以可执行文件的形式加载
9040fe15e0SLoGin         const EXEC = 1 << 0;
9140fe15e0SLoGin     }
9240fe15e0SLoGin }
9340fe15e0SLoGin 
9440fe15e0SLoGin #[derive(Debug)]
95a02ce654SChiichen pub struct ExecParam {
96a02ce654SChiichen     file: File,
9740fe15e0SLoGin     vm: Arc<AddressSpace>,
9840fe15e0SLoGin     /// 一些标志位
9940fe15e0SLoGin     flags: ExecParamFlags,
10040fe15e0SLoGin     /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充
10140fe15e0SLoGin     init_info: ProcInitInfo,
10240fe15e0SLoGin }
10340fe15e0SLoGin 
10440fe15e0SLoGin #[derive(Debug, Eq, PartialEq)]
10540fe15e0SLoGin pub enum ExecLoadMode {
10640fe15e0SLoGin     /// 以可执行文件的形式加载
10740fe15e0SLoGin     Exec,
10840fe15e0SLoGin     /// 以动态链接库的形式加载
10940fe15e0SLoGin     DSO,
11040fe15e0SLoGin }
11140fe15e0SLoGin 
11240fe15e0SLoGin #[allow(dead_code)]
113a02ce654SChiichen impl ExecParam {
114a02ce654SChiichen     pub fn new(
115a02ce654SChiichen         file_path: &str,
116a02ce654SChiichen         vm: Arc<AddressSpace>,
117a02ce654SChiichen         flags: ExecParamFlags,
118a02ce654SChiichen     ) -> Result<Self, SystemError> {
119a02ce654SChiichen         let inode = ROOT_INODE().lookup(file_path)?;
120a02ce654SChiichen 
121a02ce654SChiichen         // 读取文件头部,用于判断文件类型
122a02ce654SChiichen         let file = File::new(inode, FileMode::O_RDONLY)?;
123a02ce654SChiichen 
124a02ce654SChiichen         Ok(Self {
125a02ce654SChiichen             file,
12640fe15e0SLoGin             vm,
12740fe15e0SLoGin             flags,
12840fe15e0SLoGin             init_info: ProcInitInfo::new(),
129a02ce654SChiichen         })
13040fe15e0SLoGin     }
13140fe15e0SLoGin 
13240fe15e0SLoGin     pub fn vm(&self) -> &Arc<AddressSpace> {
13340fe15e0SLoGin         &self.vm
13440fe15e0SLoGin     }
13540fe15e0SLoGin 
13640fe15e0SLoGin     pub fn flags(&self) -> &ExecParamFlags {
13740fe15e0SLoGin         &self.flags
13840fe15e0SLoGin     }
13940fe15e0SLoGin 
14040fe15e0SLoGin     pub fn init_info(&self) -> &ProcInitInfo {
14140fe15e0SLoGin         &self.init_info
14240fe15e0SLoGin     }
14340fe15e0SLoGin 
14440fe15e0SLoGin     pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
14540fe15e0SLoGin         &mut self.init_info
14640fe15e0SLoGin     }
14740fe15e0SLoGin 
14840fe15e0SLoGin     /// 获取加载模式
14940fe15e0SLoGin     pub fn load_mode(&self) -> ExecLoadMode {
15040fe15e0SLoGin         if self.flags.contains(ExecParamFlags::EXEC) {
15140fe15e0SLoGin             ExecLoadMode::Exec
15240fe15e0SLoGin         } else {
15340fe15e0SLoGin             ExecLoadMode::DSO
15440fe15e0SLoGin         }
15540fe15e0SLoGin     }
15640fe15e0SLoGin 
15740fe15e0SLoGin     pub fn file_mut(&mut self) -> &mut File {
158a02ce654SChiichen         &mut self.file
15940fe15e0SLoGin     }
16040fe15e0SLoGin }
16140fe15e0SLoGin 
16240fe15e0SLoGin /// ## 加载二进制文件
16340fe15e0SLoGin pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> {
16440fe15e0SLoGin     // 读取文件头部,用于判断文件类型
16540fe15e0SLoGin     let mut head_buf = [0u8; 512];
16640fe15e0SLoGin     param.file_mut().lseek(SeekFrom::SeekSet(0))?;
16740fe15e0SLoGin     let _bytes = param.file_mut().read(512, &mut head_buf)?;
168*2eab6dd7S曾俊     // debug!("load_binary_file: read {} bytes", _bytes);
16940fe15e0SLoGin 
17040fe15e0SLoGin     let mut loader = None;
17140fe15e0SLoGin     for bl in BINARY_LOADERS.iter() {
17240fe15e0SLoGin         let probe_result = bl.probe(param, &head_buf);
17340fe15e0SLoGin         if probe_result.is_ok() {
17440fe15e0SLoGin             loader = Some(bl);
17540fe15e0SLoGin             break;
17640fe15e0SLoGin         }
17740fe15e0SLoGin     }
178*2eab6dd7S曾俊     // debug!("load_binary_file: loader: {:?}", loader);
17940fe15e0SLoGin     if loader.is_none() {
18040fe15e0SLoGin         return Err(SystemError::ENOEXEC);
18140fe15e0SLoGin     }
18240fe15e0SLoGin 
18340fe15e0SLoGin     let loader: &&dyn BinaryLoader = loader.unwrap();
18440fe15e0SLoGin     assert!(param.vm().is_current());
185*2eab6dd7S曾俊     // debug!("load_binary_file: to load with param: {:?}", param);
18640fe15e0SLoGin 
18740fe15e0SLoGin     let result: BinaryLoaderResult = loader
18840fe15e0SLoGin         .load(param, &head_buf)
18940fe15e0SLoGin         .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}"));
19040fe15e0SLoGin 
191*2eab6dd7S曾俊     // debug!("load_binary_file: load success: {result:?}");
19240fe15e0SLoGin     return Ok(result);
19340fe15e0SLoGin }
19440fe15e0SLoGin 
19540fe15e0SLoGin /// 程序初始化信息,这些信息会被压入用户栈中
19640fe15e0SLoGin #[derive(Debug)]
19740fe15e0SLoGin pub struct ProcInitInfo {
198865f4ba4SGnoCiYeH     pub proc_name: String,
19940fe15e0SLoGin     pub args: Vec<String>,
20040fe15e0SLoGin     pub envs: Vec<String>,
20140fe15e0SLoGin     pub auxv: BTreeMap<u8, usize>,
20240fe15e0SLoGin }
20340fe15e0SLoGin 
20440fe15e0SLoGin impl ProcInitInfo {
20540fe15e0SLoGin     pub fn new() -> Self {
20640fe15e0SLoGin         Self {
207865f4ba4SGnoCiYeH             proc_name: String::new(),
20840fe15e0SLoGin             args: Vec::new(),
20940fe15e0SLoGin             envs: Vec::new(),
21040fe15e0SLoGin             auxv: BTreeMap::new(),
21140fe15e0SLoGin         }
21240fe15e0SLoGin     }
21340fe15e0SLoGin 
21440fe15e0SLoGin     /// 把程序初始化信息压入用户栈中
21540fe15e0SLoGin     /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中
21640fe15e0SLoGin     ///
21740fe15e0SLoGin     /// ## 返回值
21840fe15e0SLoGin     ///
21940fe15e0SLoGin     /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址
22040fe15e0SLoGin     pub unsafe fn push_at(
22140fe15e0SLoGin         &self,
22240fe15e0SLoGin         ustack: &mut UserStack,
22340fe15e0SLoGin     ) -> Result<(VirtAddr, VirtAddr), SystemError> {
22440fe15e0SLoGin         // 先把程序的名称压入栈中
225865f4ba4SGnoCiYeH         self.push_str(ustack, &self.proc_name)?;
22640fe15e0SLoGin 
22740fe15e0SLoGin         // 然后把环境变量压入栈中
22840fe15e0SLoGin         let envps = self
22940fe15e0SLoGin             .envs
23040fe15e0SLoGin             .iter()
23140fe15e0SLoGin             .map(|s| {
23240fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
23340fe15e0SLoGin                 ustack.sp()
23440fe15e0SLoGin             })
23540fe15e0SLoGin             .collect::<Vec<_>>();
23640fe15e0SLoGin 
23740fe15e0SLoGin         // 然后把参数压入栈中
23840fe15e0SLoGin         let argps = self
23940fe15e0SLoGin             .args
24040fe15e0SLoGin             .iter()
24140fe15e0SLoGin             .map(|s| {
24240fe15e0SLoGin                 self.push_str(ustack, s.as_str()).expect("push_str failed");
24340fe15e0SLoGin                 ustack.sp()
24440fe15e0SLoGin             })
24540fe15e0SLoGin             .collect::<Vec<_>>();
24640fe15e0SLoGin 
24740fe15e0SLoGin         // 压入auxv
24840fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?;
24940fe15e0SLoGin         for (&k, &v) in self.auxv.iter() {
25040fe15e0SLoGin             self.push_slice(ustack, &[k as usize, v])?;
25140fe15e0SLoGin         }
25240fe15e0SLoGin 
25340fe15e0SLoGin         // 把环境变量指针压入栈中
25440fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
25540fe15e0SLoGin         self.push_slice(ustack, envps.as_slice())?;
25640fe15e0SLoGin 
25740fe15e0SLoGin         // 把参数指针压入栈中
25840fe15e0SLoGin         self.push_slice(ustack, &[null::<u8>()])?;
25940fe15e0SLoGin         self.push_slice(ustack, argps.as_slice())?;
26040fe15e0SLoGin 
26140fe15e0SLoGin         let argv_ptr = ustack.sp();
26240fe15e0SLoGin 
26340fe15e0SLoGin         // 把argc压入栈中
26440fe15e0SLoGin         self.push_slice(ustack, &[self.args.len()])?;
26540fe15e0SLoGin 
26640fe15e0SLoGin         return Ok((ustack.sp(), argv_ptr));
26740fe15e0SLoGin     }
26840fe15e0SLoGin 
26940fe15e0SLoGin     fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> {
27040fe15e0SLoGin         let mut sp = ustack.sp();
271b5b571e0SLoGin         sp -= core::mem::size_of_val(slice);
27240fe15e0SLoGin         sp -= sp.data() % core::mem::align_of::<T>();
27340fe15e0SLoGin 
27440fe15e0SLoGin         unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) }
27540fe15e0SLoGin             .copy_from_slice(slice);
27640fe15e0SLoGin         unsafe {
27740fe15e0SLoGin             ustack.set_sp(sp);
27840fe15e0SLoGin         }
27940fe15e0SLoGin 
28040fe15e0SLoGin         return Ok(());
28140fe15e0SLoGin     }
28240fe15e0SLoGin 
28340fe15e0SLoGin     fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> {
28440fe15e0SLoGin         self.push_slice(ustack, &[b'\0'])?;
28540fe15e0SLoGin         self.push_slice(ustack, s.as_bytes())?;
28640fe15e0SLoGin         return Ok(());
28740fe15e0SLoGin     }
28840fe15e0SLoGin }
289