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