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::{
7 file::{File, FileMode},
8 ROOT_INODE,
9 },
10 io::SeekFrom,
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 /// 检查二进制文件是否为当前加载器支持的格式
probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>24 fn probe(self: &'static Self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
25
load( self: &'static Self, param: &mut ExecParam, head_buf: &[u8], ) -> Result<BinaryLoaderResult, ExecError>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 {
new(entry_point: VirtAddr) -> Self41 pub fn new(entry_point: VirtAddr) -> Self {
42 Self { entry_point }
43 }
44
entry_point(&self) -> VirtAddr45 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 {
into(self) -> SystemError73 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> {
new(file_path: &'a str, vm: Arc<AddressSpace>, flags: ExecParamFlags) -> Self116 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
file_path(&self) -> &'a str126 pub fn file_path(&self) -> &'a str {
127 self.file_path
128 }
129
vm(&self) -> &Arc<AddressSpace>130 pub fn vm(&self) -> &Arc<AddressSpace> {
131 &self.vm
132 }
133
flags(&self) -> &ExecParamFlags134 pub fn flags(&self) -> &ExecParamFlags {
135 &self.flags
136 }
137
init_info(&self) -> &ProcInitInfo138 pub fn init_info(&self) -> &ProcInitInfo {
139 &self.init_info
140 }
141
init_info_mut(&mut self) -> &mut ProcInitInfo142 pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
143 &mut self.init_info
144 }
145
146 /// 获取加载模式
load_mode(&self) -> ExecLoadMode147 pub fn load_mode(&self) -> ExecLoadMode {
148 if self.flags.contains(ExecParamFlags::EXEC) {
149 ExecLoadMode::Exec
150 } else {
151 ExecLoadMode::DSO
152 }
153 }
154
file_mut(&mut self) -> &mut File155 pub fn file_mut(&mut self) -> &mut File {
156 self.file.as_mut().unwrap()
157 }
158 }
159
160 /// ## 加载二进制文件
load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError>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 {
new() -> Self206 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数组的起始地址
push_at( &self, ustack: &mut UserStack, ) -> Result<(VirtAddr, VirtAddr), SystemError>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
push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError>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
push_str(&self, ustack: &mut UserStack, s: &str) -> Result<(), SystemError>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