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