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 { 97 file: File, 98 vm: Arc<AddressSpace>, 99 /// 一些标志位 100 flags: ExecParamFlags, 101 /// 用来初始化进程的一些信息。这些信息由二进制加载器和exec机制来共同填充 102 init_info: ProcInitInfo, 103 } 104 105 #[derive(Debug, Eq, PartialEq)] 106 pub enum ExecLoadMode { 107 /// 以可执行文件的形式加载 108 Exec, 109 /// 以动态链接库的形式加载 110 DSO, 111 } 112 113 #[allow(dead_code)] 114 impl ExecParam { 115 pub fn new( 116 file_path: &str, 117 vm: Arc<AddressSpace>, 118 flags: ExecParamFlags, 119 ) -> Result<Self, SystemError> { 120 let inode = ROOT_INODE().lookup(file_path)?; 121 122 // 读取文件头部,用于判断文件类型 123 let file = File::new(inode, FileMode::O_RDONLY)?; 124 125 Ok(Self { 126 file, 127 vm, 128 flags, 129 init_info: ProcInitInfo::new(), 130 }) 131 } 132 133 pub fn vm(&self) -> &Arc<AddressSpace> { 134 &self.vm 135 } 136 137 pub fn flags(&self) -> &ExecParamFlags { 138 &self.flags 139 } 140 141 pub fn init_info(&self) -> &ProcInitInfo { 142 &self.init_info 143 } 144 145 pub fn init_info_mut(&mut self) -> &mut ProcInitInfo { 146 &mut self.init_info 147 } 148 149 /// 获取加载模式 150 pub fn load_mode(&self) -> ExecLoadMode { 151 if self.flags.contains(ExecParamFlags::EXEC) { 152 ExecLoadMode::Exec 153 } else { 154 ExecLoadMode::DSO 155 } 156 } 157 158 pub fn file_mut(&mut self) -> &mut File { 159 &mut self.file 160 } 161 } 162 163 /// ## 加载二进制文件 164 pub fn load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError> { 165 // 读取文件头部,用于判断文件类型 166 let mut head_buf = [0u8; 512]; 167 param.file_mut().lseek(SeekFrom::SeekSet(0))?; 168 let _bytes = param.file_mut().read(512, &mut head_buf)?; 169 // kdebug!("load_binary_file: read {} bytes", _bytes); 170 171 let mut loader = None; 172 for bl in BINARY_LOADERS.iter() { 173 let probe_result = bl.probe(param, &head_buf); 174 if probe_result.is_ok() { 175 loader = Some(bl); 176 break; 177 } 178 } 179 // kdebug!("load_binary_file: loader: {:?}", loader); 180 if loader.is_none() { 181 return Err(SystemError::ENOEXEC); 182 } 183 184 let loader: &&dyn BinaryLoader = loader.unwrap(); 185 assert!(param.vm().is_current()); 186 // kdebug!("load_binary_file: to load with param: {:?}", param); 187 188 let result: BinaryLoaderResult = loader 189 .load(param, &head_buf) 190 .unwrap_or_else(|e| panic!("load_binary_file failed: error: {e:?}, param: {param:?}")); 191 192 // kdebug!("load_binary_file: load success"); 193 return Ok(result); 194 } 195 196 /// 程序初始化信息,这些信息会被压入用户栈中 197 #[derive(Debug)] 198 pub struct ProcInitInfo { 199 pub proc_name: String, 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 proc_name: String::new(), 209 args: Vec::new(), 210 envs: Vec::new(), 211 auxv: BTreeMap::new(), 212 } 213 } 214 215 /// 把程序初始化信息压入用户栈中 216 /// 这个函数会把参数、环境变量、auxv等信息压入用户栈中 217 /// 218 /// ## 返回值 219 /// 220 /// 返回值是一个元组,第一个元素是最终的用户栈顶地址,第二个元素是环境变量pointer数组的起始地址 221 pub unsafe fn push_at( 222 &self, 223 ustack: &mut UserStack, 224 ) -> Result<(VirtAddr, VirtAddr), SystemError> { 225 // 先把程序的名称压入栈中 226 self.push_str(ustack, &self.proc_name)?; 227 228 // 然后把环境变量压入栈中 229 let envps = self 230 .envs 231 .iter() 232 .map(|s| { 233 self.push_str(ustack, s.as_str()).expect("push_str failed"); 234 ustack.sp() 235 }) 236 .collect::<Vec<_>>(); 237 238 // 然后把参数压入栈中 239 let argps = self 240 .args 241 .iter() 242 .map(|s| { 243 self.push_str(ustack, s.as_str()).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 -= slice.len() * core::mem::size_of::<T>(); 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: &str) -> Result<(), SystemError> { 285 self.push_slice(ustack, &[b'\0'])?; 286 self.push_slice(ustack, s.as_bytes())?; 287 return Ok(()); 288 } 289 } 290