1 use core::{fmt::Debug, ptr::null}; 2 3 use alloc::{collections::BTreeMap, 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 /// 系统支持的所有二进制文件加载器的列表 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 proc_name: String, 201 pub args: Vec<String>, 202 pub envs: Vec<String>, 203 pub auxv: BTreeMap<u8, usize>, 204 } 205 206 impl ProcInitInfo { 207 pub fn new() -> Self { 208 Self { 209 proc_name: String::new(), 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.as_str()).expect("push_str failed"); 235 ustack.sp() 236 }) 237 .collect::<Vec<_>>(); 238 239 // 然后把参数压入栈中 240 let argps = self 241 .args 242 .iter() 243 .map(|s| { 244 self.push_str(ustack, s.as_str()).expect("push_str failed"); 245 ustack.sp() 246 }) 247 .collect::<Vec<_>>(); 248 249 // 压入auxv 250 self.push_slice(ustack, &[null::<u8>(), null::<u8>()])?; 251 for (&k, &v) in self.auxv.iter() { 252 self.push_slice(ustack, &[k as usize, v])?; 253 } 254 255 // 把环境变量指针压入栈中 256 self.push_slice(ustack, &[null::<u8>()])?; 257 self.push_slice(ustack, envps.as_slice())?; 258 259 // 把参数指针压入栈中 260 self.push_slice(ustack, &[null::<u8>()])?; 261 self.push_slice(ustack, argps.as_slice())?; 262 263 let argv_ptr = ustack.sp(); 264 265 // 把argc压入栈中 266 self.push_slice(ustack, &[self.args.len()])?; 267 268 return Ok((ustack.sp(), argv_ptr)); 269 } 270 271 fn push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError> { 272 let mut sp = ustack.sp(); 273 sp -= slice.len() * core::mem::size_of::<T>(); 274 sp -= sp.data() % core::mem::align_of::<T>(); 275 276 unsafe { core::slice::from_raw_parts_mut(sp.data() as *mut T, slice.len()) } 277 .copy_from_slice(slice); 278 unsafe { 279 ustack.set_sp(sp); 280 } 281 282 return Ok(()); 283 } 284 285 fn push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError> { 286 self.push_slice(ustack, &[b'\0'])?; 287 self.push_slice(ustack, s.as_bytes())?; 288 return Ok(()); 289 } 290 } 291