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 /// 检查二进制文件是否为当前加载器支持的格式
probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>26 fn probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>;
27
load( &'static self, param: &mut ExecParam, head_buf: &[u8], ) -> Result<BinaryLoaderResult, ExecError>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 {
new(entry_point: VirtAddr) -> Self43 pub fn new(entry_point: VirtAddr) -> Self {
44 Self { entry_point }
45 }
46
entry_point(&self) -> VirtAddr47 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 {
from(val: ExecError) -> Self74 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 {
new( file_path: &str, vm: Arc<AddressSpace>, flags: ExecParamFlags, ) -> Result<Self, SystemError>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
vm(&self) -> &Arc<AddressSpace>134 pub fn vm(&self) -> &Arc<AddressSpace> {
135 &self.vm
136 }
137
flags(&self) -> &ExecParamFlags138 pub fn flags(&self) -> &ExecParamFlags {
139 &self.flags
140 }
141
init_info(&self) -> &ProcInitInfo142 pub fn init_info(&self) -> &ProcInitInfo {
143 &self.init_info
144 }
145
init_info_mut(&mut self) -> &mut ProcInitInfo146 pub fn init_info_mut(&mut self) -> &mut ProcInitInfo {
147 &mut self.init_info
148 }
149
150 /// 获取加载模式
load_mode(&self) -> ExecLoadMode151 pub fn load_mode(&self) -> ExecLoadMode {
152 if self.flags.contains(ExecParamFlags::EXEC) {
153 ExecLoadMode::Exec
154 } else {
155 ExecLoadMode::DSO
156 }
157 }
158
file_mut(&mut self) -> &mut File159 pub fn file_mut(&mut self) -> &mut File {
160 &mut self.file
161 }
162 }
163
164 /// ## 加载二进制文件
load_binary_file(param: &mut ExecParam) -> Result<BinaryLoaderResult, SystemError>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 {
new(proc_name: &str) -> Self207 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数组的起始地址
push_at( &self, ustack: &mut UserStack, ) -> Result<(VirtAddr, VirtAddr), SystemError>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
push_slice<T: Copy>(&self, ustack: &mut UserStack, slice: &[T]) -> Result<(), SystemError>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
push_str(&self, ustack: &mut UserStack, s: &CString) -> Result<(), SystemError>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