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(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>; 25 26 fn load( 27 &'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 impl From<ExecError> for SystemError { 72 fn from(val: ExecError) -> Self { 73 match val { 74 ExecError::NotExecutable => SystemError::ENOEXEC, 75 ExecError::WrongArchitecture => SystemError::ENOEXEC, 76 ExecError::PermissionDenied => SystemError::EACCES, 77 ExecError::NotSupported => SystemError::ENOSYS, 78 ExecError::ParseError => SystemError::ENOEXEC, 79 ExecError::OutOfMemory => SystemError::ENOMEM, 80 ExecError::InvalidParemeter => SystemError::EINVAL, 81 ExecError::BadAddress(_addr) => SystemError::EFAULT, 82 ExecError::Other(_msg) => SystemError::ENOEXEC, 83 } 84 } 85 } 86 87 bitflags! { 88 pub struct ExecParamFlags: u32 { 89 // 是否以可执行文件的形式加载 90 const EXEC = 1 << 0; 91 } 92 } 93 94 #[derive(Debug)] 95 pub struct ExecParam { 96 file: File, 97 vm: Arc<AddressSpace>, 98 /// 一些标志位 99 flags: ExecParamFlags, 100 /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充 101 init_info: ProcInitInfo, 102 } 103 104 #[derive(Debug, Eq, PartialEq)] 105 pub enum ExecLoadMode { 106 /// 以可执行文件的形式加载 107 Exec, 108 /// 以动态链接库的形式加载 109 DSO, 110 } 111 112 #[allow(dead_code)] 113 impl ExecParam { 114 pub fn new( 115 file_path: &str, 116 vm: Arc<AddressSpace>, 117 flags: ExecParamFlags, 118 ) -> Result<Self, SystemError> { 119 let inode = ROOT_INODE().lookup(file_path)?; 120 121 // 读取文件头部,用于判断文件类型 122 let file = File::new(inode, FileMode::O_RDONLY)?; 123 124 Ok(Self { 125 file, 126 vm, 127 flags, 128 init_info: ProcInitInfo::new(), 129 }) 130 } 131 132 pub fn vm(&self) -> &Arc<AddressSpace> { 133 &self.vm 134 } 135 136 pub fn flags(&self) -> &ExecParamFlags { 137 &self.flags 138 } 139 140 pub fn init_info(&self) -> &ProcInitInfo { 141 &self.init_info 142 } 143 144 pub fn init_info_mut(&mut self) -> &mut ProcInitInfo { 145 &mut self.init_info 146 } 147 148 /// 获取加载模式 149 pub fn load_mode(&self) -> ExecLoadMode { 150 if self.flags.contains(ExecParamFlags::EXEC) { 151 ExecLoadMode::Exec 152 } else { 153 ExecLoadMode::DSO 154 } 155 } 156 157 pub fn file_mut(&mut self) -> &mut File { 158 &mut self.file 159 } 160 } 161 162 /// ## 加载二进制文件 163 pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> { 164 // 读取文件头部,用于判断文件类型 165 let mut head_buf = [0u8; 512]; 166 param.file_mut().lseek(SeekFrom::SeekSet(0))?; 167 let _bytes = param.file_mut().read(512, &mut head_buf)?; 168 // kdebug!("load_binary_file: read {} bytes", _bytes); 169 170 let mut loader = None; 171 for bl in BINARY_LOADERS.iter() { 172 let probe_result = bl.probe(param, &head_buf); 173 if probe_result.is_ok() { 174 loader = Some(bl); 175 break; 176 } 177 } 178 // kdebug!("load_binary_file: loader: {:?}", loader); 179 if loader.is_none() { 180 return Err(SystemError::ENOEXEC); 181 } 182 183 let loader: &&dyn BinaryLoader = loader.unwrap(); 184 assert!(param.vm().is_current()); 185 // kdebug!("load_binary_file: to load with param: {:?}", param); 186 187 let result: BinaryLoaderResult = loader 188 .load(param, &head_buf) 189 .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}")); 190 191 // kdebug!("load_binary_file: load success"); 192 return Ok(result); 193 } 194 195 /// 程序初始化信息,这些信息会被压入用户栈中 196 #[derive(Debug)] 197 pub struct ProcInitInfo { 198 pub proc_name: String, 199 pub args: Vec<String>, 200 pub envs: Vec<String>, 201 pub auxv: BTreeMap<u8, usize>, 202 } 203 204 impl ProcInitInfo { 205 pub fn new() -> Self { 206 Self { 207 proc_name: String::new(), 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.proc_name)?; 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 -= core::mem::size_of_val(slice); 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