1 use alloc::{string::String, vec::Vec}; 2 3 use crate::{ 4 arch::{ 5 interrupt::TrapFrame, 6 process::table::{USER_CS, USER_DS}, 7 CurrentIrqArch, 8 }, 9 exception::InterruptArch, 10 mm::ucontext::AddressSpace, 11 process::{ 12 exec::{load_binary_file, ExecParam, ExecParamFlags}, 13 ProcessManager, 14 }, 15 syscall::{Syscall, SystemError}, 16 }; 17 18 impl Syscall { 19 pub fn do_execve( 20 path: String, 21 argv: Vec<String>, 22 envp: Vec<String>, 23 regs: &mut TrapFrame, 24 ) -> Result<(), SystemError> { 25 // kdebug!( 26 // "tmp_rs_execve: path: {:?}, argv: {:?}, envp: {:?}\n", 27 // path, 28 // argv, 29 // envp 30 // ); 31 // 关中断,防止在设置地址空间的时候,发生中断,然后进调度器,出现错误。 32 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 33 let pcb = ProcessManager::current_pcb(); 34 35 let mut basic_info = pcb.basic_mut(); 36 // 暂存原本的用户地址空间的引用(因为如果在切换页表之前释放了它,可能会造成内存use after free) 37 let old_address_space = basic_info.user_vm(); 38 39 // 在pcb中原来的用户地址空间 40 unsafe { 41 basic_info.set_user_vm(None); 42 } 43 // 创建新的地址空间并设置为当前地址空间 44 let address_space = AddressSpace::new(true).expect("Failed to create new address space"); 45 unsafe { 46 basic_info.set_user_vm(Some(address_space.clone())); 47 } 48 49 // to avoid deadlock 50 drop(basic_info); 51 52 assert!( 53 AddressSpace::is_current(&address_space), 54 "Failed to set address space" 55 ); 56 // kdebug!("Switch to new address space"); 57 58 // 切换到新的用户地址空间 59 unsafe { address_space.read().user_mapper.utable.make_current() }; 60 61 drop(old_address_space); 62 drop(irq_guard); 63 // kdebug!("to load binary file"); 64 let mut param = ExecParam::new(path.as_str(), address_space.clone(), ExecParamFlags::EXEC); 65 66 // 加载可执行文件 67 let load_result = load_binary_file(&mut param) 68 .unwrap_or_else(|e| panic!("Failed to load binary file: {:?}, path: {:?}", e, path)); 69 // kdebug!("load binary file done"); 70 // kdebug!("argv: {:?}, envp: {:?}", argv, envp); 71 param.init_info_mut().args = argv; 72 param.init_info_mut().envs = envp; 73 74 // 把proc_init_info写到用户栈上 75 76 let (user_sp, argv_ptr) = unsafe { 77 param 78 .init_info() 79 .push_at( 80 address_space 81 .write() 82 .user_stack_mut() 83 .expect("No user stack found"), 84 ) 85 .expect("Failed to push proc_init_info to user stack") 86 }; 87 88 // kdebug!("write proc_init_info to user stack done"); 89 90 // (兼容旧版libc)把argv的指针写到寄存器内 91 // TODO: 改写旧版libc,不再需要这个兼容 92 regs.rdi = param.init_info().args.len() as u64; 93 regs.rsi = argv_ptr.data() as u64; 94 95 // 设置系统调用返回时的寄存器状态 96 // TODO: 中断管理重构后,这里的寄存器状态设置要删掉!!!改为对trap frame的设置。要增加架构抽象。 97 regs.rsp = user_sp.data() as u64; 98 regs.rbp = user_sp.data() as u64; 99 regs.rip = load_result.entry_point().data() as u64; 100 101 regs.cs = USER_CS.bits() as u64; 102 regs.ds = USER_DS.bits() as u64; 103 regs.ss = USER_DS.bits() as u64; 104 regs.es = 0; 105 regs.rflags = 0x200; 106 regs.rax = 1; 107 108 // kdebug!("regs: {:?}\n", regs); 109 110 // kdebug!( 111 // "tmp_rs_execve: done, load_result.entry_point()={:?}", 112 // load_result.entry_point() 113 // ); 114 115 return Ok(()); 116 } 117 } 118