140fe15e0SLoGin use core::{ 2a02ce654SChiichen cmp::{max, min}, 3a02ce654SChiichen fmt::Debug, 440fe15e0SLoGin intrinsics::{likely, unlikely}, 540fe15e0SLoGin ops::Range, 640fe15e0SLoGin }; 740fe15e0SLoGin 840fe15e0SLoGin use alloc::vec::Vec; 9a02ce654SChiichen use elf::{ 10a02ce654SChiichen abi::{PT_GNU_PROPERTY, PT_INTERP}, 11a02ce654SChiichen endian::AnyEndian, 12a02ce654SChiichen file::FileHeader, 13a02ce654SChiichen segment::ProgramHeader, 14a02ce654SChiichen }; 15*2eab6dd7S曾俊 use log::error; 1691e9d4abSLoGin use system_error::SystemError; 1740fe15e0SLoGin 1840fe15e0SLoGin use crate::{ 19a02ce654SChiichen arch::{CurrentElfArch, MMArch}, 20b087521eSChiichen driver::base::block::SeekFrom, 21a02ce654SChiichen filesystem::vfs::file::File, 2240fe15e0SLoGin libs::align::page_align_up, 2340fe15e0SLoGin mm::{ 2440fe15e0SLoGin allocator::page_frame::{PageFrameCount, VirtPageFrame}, 2540fe15e0SLoGin syscall::{MapFlags, ProtFlags}, 2640fe15e0SLoGin ucontext::InnerAddressSpace, 2740fe15e0SLoGin MemoryManagementArch, VirtAddr, 2840fe15e0SLoGin }, 2940fe15e0SLoGin process::{ 3040fe15e0SLoGin abi::AtType, 3140fe15e0SLoGin exec::{BinaryLoader, BinaryLoaderResult, ExecError, ExecLoadMode, ExecParam}, 32a02ce654SChiichen ProcessFlags, ProcessManager, 3340fe15e0SLoGin }, 3491e9d4abSLoGin syscall::user_access::{clear_user, copy_to_user}, 3540fe15e0SLoGin }; 3640fe15e0SLoGin 3740fe15e0SLoGin use super::rwlock::RwLockWriteGuard; 3840fe15e0SLoGin 39a02ce654SChiichen // 存放跟架构相关的Elf属性, 40a02ce654SChiichen pub trait ElfArch: Clone + Copy + Debug { 41a02ce654SChiichen const ELF_ET_DYN_BASE: usize; 42a02ce654SChiichen const ELF_PAGE_SIZE: usize; 43a02ce654SChiichen } 44a02ce654SChiichen 4540fe15e0SLoGin #[derive(Debug)] 4640fe15e0SLoGin pub struct ElfLoader; 4740fe15e0SLoGin 4840fe15e0SLoGin pub const ELF_LOADER: ElfLoader = ElfLoader::new(); 4940fe15e0SLoGin 5040fe15e0SLoGin impl ElfLoader { 5140fe15e0SLoGin /// 读取文件的缓冲区大小 5240fe15e0SLoGin pub const FILE_READ_BUF_SIZE: usize = 512 * 1024; 5340fe15e0SLoGin new() -> Self5440fe15e0SLoGin pub const fn new() -> Self { 5540fe15e0SLoGin Self 5640fe15e0SLoGin } 5740fe15e0SLoGin inner_probe_common( &self, param: &ExecParam, ehdr: &FileHeader<AnyEndian>, ) -> Result<(), ExecError>584fda81ceSLoGin fn inner_probe_common( 5940fe15e0SLoGin &self, 6040fe15e0SLoGin param: &ExecParam, 6140fe15e0SLoGin ehdr: &FileHeader<AnyEndian>, 6240fe15e0SLoGin ) -> Result<(), ExecError> { 6340fe15e0SLoGin // 只支持 64 位的 ELF 文件 6440fe15e0SLoGin if ehdr.class != elf::file::Class::ELF64 { 6540fe15e0SLoGin return Err(ExecError::WrongArchitecture); 6640fe15e0SLoGin } 6740fe15e0SLoGin 6840fe15e0SLoGin // 判断是否以可执行文件的形式加载 6940fe15e0SLoGin if param.load_mode() == ExecLoadMode::Exec { 7040fe15e0SLoGin // 检查文件类型是否为可执行文件 71a02ce654SChiichen if ElfType::from(ehdr.e_type) != ElfType::Executable 72a02ce654SChiichen && ElfType::from(ehdr.e_type) != ElfType::DSO 73a02ce654SChiichen { 7440fe15e0SLoGin return Err(ExecError::NotExecutable); 7540fe15e0SLoGin } 7640fe15e0SLoGin } else { 7740fe15e0SLoGin return Err(ExecError::NotSupported); 7840fe15e0SLoGin } 7940fe15e0SLoGin 8040fe15e0SLoGin return Ok(()); 8140fe15e0SLoGin } 8240fe15e0SLoGin 834fda81ceSLoGin #[cfg(target_arch = "x86_64")] probe_x86_64( &self, param: &ExecParam, ehdr: &FileHeader<AnyEndian>, ) -> Result<(), ExecError>844fda81ceSLoGin pub fn probe_x86_64( 854fda81ceSLoGin &self, 864fda81ceSLoGin param: &ExecParam, 874fda81ceSLoGin ehdr: &FileHeader<AnyEndian>, 884fda81ceSLoGin ) -> Result<(), ExecError> { 894fda81ceSLoGin // 判断架构是否匹配 904fda81ceSLoGin if ElfMachine::from(ehdr.e_machine) != ElfMachine::X86_64 { 914fda81ceSLoGin return Err(ExecError::WrongArchitecture); 924fda81ceSLoGin } 934fda81ceSLoGin return self.inner_probe_common(param, ehdr); 944fda81ceSLoGin } 954fda81ceSLoGin 964fda81ceSLoGin #[cfg(target_arch = "riscv64")] probe_riscv( &self, param: &ExecParam, ehdr: &FileHeader<AnyEndian>, ) -> Result<(), ExecError>974fda81ceSLoGin pub fn probe_riscv( 984fda81ceSLoGin &self, 994fda81ceSLoGin param: &ExecParam, 1004fda81ceSLoGin ehdr: &FileHeader<AnyEndian>, 1014fda81ceSLoGin ) -> Result<(), ExecError> { 1024fda81ceSLoGin // 判断架构是否匹配 1034fda81ceSLoGin if ElfMachine::from(ehdr.e_machine) != ElfMachine::RiscV { 1044fda81ceSLoGin return Err(ExecError::WrongArchitecture); 1054fda81ceSLoGin } 1064fda81ceSLoGin return self.inner_probe_common(param, ehdr); 1074fda81ceSLoGin } 1084fda81ceSLoGin 10940fe15e0SLoGin /// 设置用户堆空间,映射[start, end)区间的虚拟地址,并把brk指针指向end 11040fe15e0SLoGin /// 11140fe15e0SLoGin /// ## 参数 11240fe15e0SLoGin /// 11340fe15e0SLoGin /// - `user_vm_guard` - 用户虚拟地址空间 11440fe15e0SLoGin /// - `start` - 本次映射的起始地址 11540fe15e0SLoGin /// - `end` - 本次映射的结束地址(不包含) 11640fe15e0SLoGin /// - `prot_flags` - 本次映射的权限 set_elf_brk( &self, user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>, start: VirtAddr, end: VirtAddr, prot_flags: ProtFlags, ) -> Result<(), ExecError>11740fe15e0SLoGin fn set_elf_brk( 11840fe15e0SLoGin &self, 11940fe15e0SLoGin user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>, 12040fe15e0SLoGin start: VirtAddr, 12140fe15e0SLoGin end: VirtAddr, 12240fe15e0SLoGin prot_flags: ProtFlags, 12340fe15e0SLoGin ) -> Result<(), ExecError> { 12440fe15e0SLoGin let start = self.elf_page_start(start); 12540fe15e0SLoGin let end = self.elf_page_align_up(end); 126*2eab6dd7S曾俊 // debug!("set_elf_brk: start={:?}, end={:?}", start, end); 12740fe15e0SLoGin if end > start { 12840fe15e0SLoGin let r = user_vm_guard.map_anonymous( 12940fe15e0SLoGin start, 13040fe15e0SLoGin end - start, 13140fe15e0SLoGin prot_flags, 13240fe15e0SLoGin MapFlags::MAP_ANONYMOUS | MapFlags::MAP_FIXED_NOREPLACE, 13340fe15e0SLoGin false, 134a17651b1SMemoryShore true, 13540fe15e0SLoGin ); 136*2eab6dd7S曾俊 // debug!("set_elf_brk: map_anonymous: r={:?}", r); 13740fe15e0SLoGin if r.is_err() { 138*2eab6dd7S曾俊 error!("set_elf_brk: map_anonymous failed, err={:?}", r); 13940fe15e0SLoGin return Err(ExecError::OutOfMemory); 14040fe15e0SLoGin } 14140fe15e0SLoGin } 14240fe15e0SLoGin user_vm_guard.elf_brk_start = end; 14340fe15e0SLoGin user_vm_guard.elf_brk = end; 14440fe15e0SLoGin return Ok(()); 14540fe15e0SLoGin } 14640fe15e0SLoGin 14740fe15e0SLoGin /// 计算addr在ELF PAGE内的偏移 elf_page_offset(&self, addr: VirtAddr) -> usize14840fe15e0SLoGin fn elf_page_offset(&self, addr: VirtAddr) -> usize { 149a02ce654SChiichen addr.data() & (CurrentElfArch::ELF_PAGE_SIZE - 1) 15040fe15e0SLoGin } 15140fe15e0SLoGin elf_page_start(&self, addr: VirtAddr) -> VirtAddr15240fe15e0SLoGin fn elf_page_start(&self, addr: VirtAddr) -> VirtAddr { 153a02ce654SChiichen VirtAddr::new(addr.data() & (!(CurrentElfArch::ELF_PAGE_SIZE - 1))) 15440fe15e0SLoGin } 15540fe15e0SLoGin elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr15640fe15e0SLoGin fn elf_page_align_up(&self, addr: VirtAddr) -> VirtAddr { 157a02ce654SChiichen VirtAddr::new( 158a02ce654SChiichen (addr.data() + CurrentElfArch::ELF_PAGE_SIZE - 1) 159a02ce654SChiichen & (!(CurrentElfArch::ELF_PAGE_SIZE - 1)), 160a02ce654SChiichen ) 16140fe15e0SLoGin } 16240fe15e0SLoGin 16340fe15e0SLoGin /// 根据ELF的p_flags生成对应的ProtFlags make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags16440fe15e0SLoGin fn make_prot(&self, p_flags: u32, _has_interpreter: bool, _is_interpreter: bool) -> ProtFlags { 16540fe15e0SLoGin let mut prot = ProtFlags::empty(); 16640fe15e0SLoGin if p_flags & elf::abi::PF_R != 0 { 16740fe15e0SLoGin prot |= ProtFlags::PROT_READ; 16840fe15e0SLoGin } 16940fe15e0SLoGin if p_flags & elf::abi::PF_W != 0 { 17040fe15e0SLoGin prot |= ProtFlags::PROT_WRITE; 17140fe15e0SLoGin } 17240fe15e0SLoGin if p_flags & elf::abi::PF_X != 0 { 17340fe15e0SLoGin prot |= ProtFlags::PROT_EXEC; 17440fe15e0SLoGin } 17540fe15e0SLoGin 17640fe15e0SLoGin // todo: 增加与架构相关的处理 177e7071df6SLoGin // ref: https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#572 17840fe15e0SLoGin 17940fe15e0SLoGin return prot; 18040fe15e0SLoGin } 18140fe15e0SLoGin 18240fe15e0SLoGin /// 加载ELF文件到用户空间 18340fe15e0SLoGin /// 18440fe15e0SLoGin /// 参考Linux的elf_map函数 185e7071df6SLoGin /// https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#365 18640fe15e0SLoGin /// ## 参数 18740fe15e0SLoGin /// 18840fe15e0SLoGin /// - `user_vm_guard`:用户空间地址空间 18940fe15e0SLoGin /// - `param`:执行参数 19040fe15e0SLoGin /// - `phent`:ELF文件的ProgramHeader 19140fe15e0SLoGin /// - `addr_to_map`:当前段应该被加载到的内存地址 19240fe15e0SLoGin /// - `prot`:保护标志 19340fe15e0SLoGin /// - `map_flags`:映射标志 19440fe15e0SLoGin /// - `total_size`:ELF文件的总大小 19540fe15e0SLoGin /// 19640fe15e0SLoGin /// ## 返回值 19740fe15e0SLoGin /// 19840fe15e0SLoGin /// - `Ok((VirtAddr, bool))`:如果成功加载,则bool值为true,否则为false. VirtAddr为加载的地址 199b5b571e0SLoGin #[allow(clippy::too_many_arguments)] load_elf_segment( &self, user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>, param: &mut ExecParam, phent: &ProgramHeader, mut addr_to_map: VirtAddr, prot: &ProtFlags, map_flags: &MapFlags, total_size: usize, ) -> Result<(VirtAddr, bool), SystemError>20040fe15e0SLoGin fn load_elf_segment( 20140fe15e0SLoGin &self, 20240fe15e0SLoGin user_vm_guard: &mut RwLockWriteGuard<'_, InnerAddressSpace>, 20340fe15e0SLoGin param: &mut ExecParam, 20440fe15e0SLoGin phent: &ProgramHeader, 20540fe15e0SLoGin mut addr_to_map: VirtAddr, 20640fe15e0SLoGin prot: &ProtFlags, 20740fe15e0SLoGin map_flags: &MapFlags, 20840fe15e0SLoGin total_size: usize, 20940fe15e0SLoGin ) -> Result<(VirtAddr, bool), SystemError> { 210*2eab6dd7S曾俊 // debug!("load_elf_segment: addr_to_map={:?}", addr_to_map); 21140fe15e0SLoGin 21240fe15e0SLoGin // 映射位置的偏移量(页内偏移) 21340fe15e0SLoGin let beginning_page_offset = self.elf_page_offset(addr_to_map); 21440fe15e0SLoGin addr_to_map = self.elf_page_start(addr_to_map); 21540fe15e0SLoGin // 计算要映射的内存的大小 2166d81180bSLoGin let map_size = phent.p_filesz as usize + beginning_page_offset; 21740fe15e0SLoGin let map_size = self.elf_page_align_up(VirtAddr::new(map_size)).data(); 21840fe15e0SLoGin // 当前段在文件中的大小 21940fe15e0SLoGin let seg_in_file_size = phent.p_filesz as usize; 22040fe15e0SLoGin // 当前段在文件中的偏移量 22140fe15e0SLoGin let file_offset = phent.p_offset as usize; 22240fe15e0SLoGin 22340fe15e0SLoGin // 如果当前段的大小为0,则直接返回. 22440fe15e0SLoGin // 段在文件中的大小为0,是合法的,但是段在内存中的大小不能为0 22540fe15e0SLoGin if map_size == 0 { 22640fe15e0SLoGin return Ok((addr_to_map, true)); 22740fe15e0SLoGin } 22840fe15e0SLoGin 22940fe15e0SLoGin let map_err_handler = |err: SystemError| { 23040fe15e0SLoGin if err == SystemError::EEXIST { 231*2eab6dd7S曾俊 error!( 2321496ba7bSLoGin "Pid: {:?}, elf segment at {:p} overlaps with existing mapping", 2331496ba7bSLoGin ProcessManager::current_pcb().pid(), 23440fe15e0SLoGin addr_to_map.as_ptr::<u8>() 23540fe15e0SLoGin ); 23640fe15e0SLoGin } 23740fe15e0SLoGin err 23840fe15e0SLoGin }; 23940fe15e0SLoGin // 由于后面需要把ELF文件的内容加载到内存,因此暂时把当前段的权限设置为可写 24040fe15e0SLoGin let tmp_prot = if !prot.contains(ProtFlags::PROT_WRITE) { 24140fe15e0SLoGin *prot | ProtFlags::PROT_WRITE 24240fe15e0SLoGin } else { 24340fe15e0SLoGin *prot 24440fe15e0SLoGin }; 24540fe15e0SLoGin 24640fe15e0SLoGin // 映射到的虚拟地址。请注意,这个虚拟地址是user_vm_guard这个地址空间的虚拟地址。不一定是当前进程地址空间的 24740fe15e0SLoGin let map_addr: VirtAddr; 24840fe15e0SLoGin 24940fe15e0SLoGin // total_size is the size of the ELF (interpreter) image. 25040fe15e0SLoGin // The _first_ mmap needs to know the full size, otherwise 25140fe15e0SLoGin // randomization might put this image into an overlapping 25240fe15e0SLoGin // position with the ELF binary image. (since size < total_size) 25340fe15e0SLoGin // So we first map the 'big' image - and unmap the remainder at 25440fe15e0SLoGin // the end. (which unmap is needed for ELF images with holes.) 25540fe15e0SLoGin if total_size != 0 { 25640fe15e0SLoGin let total_size = self.elf_page_align_up(VirtAddr::new(total_size)).data(); 25740fe15e0SLoGin 25840fe15e0SLoGin map_addr = user_vm_guard 259a17651b1SMemoryShore .map_anonymous(addr_to_map, total_size, tmp_prot, *map_flags, false, true) 26040fe15e0SLoGin .map_err(map_err_handler)? 26140fe15e0SLoGin .virt_address(); 26240fe15e0SLoGin 26340fe15e0SLoGin let to_unmap = map_addr + map_size; 26440fe15e0SLoGin let to_unmap_size = total_size - map_size; 26540fe15e0SLoGin 26640fe15e0SLoGin user_vm_guard.munmap( 26740fe15e0SLoGin VirtPageFrame::new(to_unmap), 26840fe15e0SLoGin PageFrameCount::from_bytes(to_unmap_size).unwrap(), 26940fe15e0SLoGin )?; 27040fe15e0SLoGin 27140fe15e0SLoGin // 加载文件到内存 27240fe15e0SLoGin self.do_load_file( 27340fe15e0SLoGin map_addr + beginning_page_offset, 27440fe15e0SLoGin seg_in_file_size, 27540fe15e0SLoGin file_offset, 27640fe15e0SLoGin param, 27740fe15e0SLoGin )?; 27840fe15e0SLoGin if tmp_prot != *prot { 27940fe15e0SLoGin user_vm_guard.mprotect( 28040fe15e0SLoGin VirtPageFrame::new(map_addr), 28140fe15e0SLoGin PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(), 28240fe15e0SLoGin *prot, 28340fe15e0SLoGin )?; 28440fe15e0SLoGin } 28540fe15e0SLoGin } else { 286*2eab6dd7S曾俊 // debug!("total size = 0"); 28740fe15e0SLoGin 28840fe15e0SLoGin map_addr = user_vm_guard 289a17651b1SMemoryShore .map_anonymous(addr_to_map, map_size, tmp_prot, *map_flags, false, true)? 29040fe15e0SLoGin .virt_address(); 291*2eab6dd7S曾俊 // debug!( 29240fe15e0SLoGin // "map ok: addr_to_map={:?}, map_addr={map_addr:?},beginning_page_offset={beginning_page_offset:?}", 29340fe15e0SLoGin // addr_to_map 29440fe15e0SLoGin // ); 29540fe15e0SLoGin 29640fe15e0SLoGin // 加载文件到内存 29740fe15e0SLoGin self.do_load_file( 29840fe15e0SLoGin map_addr + beginning_page_offset, 29940fe15e0SLoGin seg_in_file_size, 30040fe15e0SLoGin file_offset, 30140fe15e0SLoGin param, 30240fe15e0SLoGin )?; 30340fe15e0SLoGin 30440fe15e0SLoGin if tmp_prot != *prot { 30540fe15e0SLoGin user_vm_guard.mprotect( 30640fe15e0SLoGin VirtPageFrame::new(map_addr), 30740fe15e0SLoGin PageFrameCount::from_bytes(page_align_up(map_size)).unwrap(), 30840fe15e0SLoGin *prot, 30940fe15e0SLoGin )?; 31040fe15e0SLoGin } 31140fe15e0SLoGin } 312*2eab6dd7S曾俊 // debug!("load_elf_segment OK: map_addr={:?}", map_addr); 31340fe15e0SLoGin return Ok((map_addr, true)); 31440fe15e0SLoGin } 31540fe15e0SLoGin 31640fe15e0SLoGin /// 加载ELF文件到用户空间 31740fe15e0SLoGin /// 31840fe15e0SLoGin /// ## 参数 31940fe15e0SLoGin /// 32040fe15e0SLoGin /// - `vaddr`:要加载到的虚拟地址 32140fe15e0SLoGin /// - `size`:要加载的大小 32240fe15e0SLoGin /// - `offset_in_file`:在文件内的偏移量 32340fe15e0SLoGin /// - `param`:执行参数 do_load_file( &self, mut vaddr: VirtAddr, size: usize, offset_in_file: usize, param: &mut ExecParam, ) -> Result<(), SystemError>32440fe15e0SLoGin fn do_load_file( 32540fe15e0SLoGin &self, 32640fe15e0SLoGin mut vaddr: VirtAddr, 32740fe15e0SLoGin size: usize, 32840fe15e0SLoGin offset_in_file: usize, 32940fe15e0SLoGin param: &mut ExecParam, 33040fe15e0SLoGin ) -> Result<(), SystemError> { 33140fe15e0SLoGin let file = param.file_mut(); 33240fe15e0SLoGin if (file.metadata()?.size as usize) < offset_in_file + size { 33340fe15e0SLoGin return Err(SystemError::ENOEXEC); 33440fe15e0SLoGin } 33540fe15e0SLoGin let buf_size = min(size, Self::FILE_READ_BUF_SIZE); 33640fe15e0SLoGin let mut buf = vec![0u8; buf_size]; 33740fe15e0SLoGin 33840fe15e0SLoGin let mut remain = size; 33940fe15e0SLoGin 34040fe15e0SLoGin file.lseek(SeekFrom::SeekSet(offset_in_file as i64))?; 34140fe15e0SLoGin 34240fe15e0SLoGin while remain > 0 { 34340fe15e0SLoGin let read_size = min(remain, buf_size); 34440fe15e0SLoGin file.read(read_size, &mut buf[..read_size])?; 345*2eab6dd7S曾俊 // debug!("copy_to_user: vaddr={:?}, read_size = {read_size}", vaddr); 34640fe15e0SLoGin unsafe { 34740fe15e0SLoGin copy_to_user(vaddr, &buf[..read_size]).map_err(|_| SystemError::EFAULT)?; 34840fe15e0SLoGin } 34940fe15e0SLoGin 35040fe15e0SLoGin vaddr += read_size; 35140fe15e0SLoGin remain -= read_size; 35240fe15e0SLoGin } 35340fe15e0SLoGin return Ok(()); 35440fe15e0SLoGin } 35540fe15e0SLoGin 35640fe15e0SLoGin /// 我们需要显式的把数据段之后剩余的内存页都清零。 pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError>35740fe15e0SLoGin fn pad_zero(&self, elf_bss: VirtAddr) -> Result<(), SystemError> { 35840fe15e0SLoGin let nbyte = self.elf_page_offset(elf_bss); 35940fe15e0SLoGin if nbyte > 0 { 360a02ce654SChiichen let nbyte = CurrentElfArch::ELF_PAGE_SIZE - nbyte; 36140fe15e0SLoGin unsafe { clear_user(elf_bss, nbyte).map_err(|_| SystemError::EFAULT) }?; 36240fe15e0SLoGin } 36340fe15e0SLoGin return Ok(()); 36440fe15e0SLoGin } 36540fe15e0SLoGin 36640fe15e0SLoGin /// 创建auxv 36740fe15e0SLoGin /// 36840fe15e0SLoGin /// ## 参数 36940fe15e0SLoGin /// 37040fe15e0SLoGin /// - `param`:执行参数 37140fe15e0SLoGin /// - `entrypoint_vaddr`:程序入口地址 37240fe15e0SLoGin /// - `phdr_vaddr`:程序头表地址 37340fe15e0SLoGin /// - `elf_header`:ELF文件头 create_auxv( &self, param: &mut ExecParam, entrypoint_vaddr: VirtAddr, phdr_vaddr: Option<VirtAddr>, ehdr: &elf::file::FileHeader<AnyEndian>, ) -> Result<(), ExecError>37440fe15e0SLoGin fn create_auxv( 37540fe15e0SLoGin &self, 37640fe15e0SLoGin param: &mut ExecParam, 37740fe15e0SLoGin entrypoint_vaddr: VirtAddr, 37840fe15e0SLoGin phdr_vaddr: Option<VirtAddr>, 37940fe15e0SLoGin ehdr: &elf::file::FileHeader<AnyEndian>, 38040fe15e0SLoGin ) -> Result<(), ExecError> { 38140fe15e0SLoGin let phdr_vaddr = phdr_vaddr.unwrap_or(VirtAddr::new(0)); 38240fe15e0SLoGin 38340fe15e0SLoGin let init_info = param.init_info_mut(); 38440fe15e0SLoGin init_info 38540fe15e0SLoGin .auxv 38640fe15e0SLoGin .insert(AtType::PhEnt as u8, ehdr.e_phentsize as usize); 38740fe15e0SLoGin init_info 38840fe15e0SLoGin .auxv 38940fe15e0SLoGin .insert(AtType::PageSize as u8, MMArch::PAGE_SIZE); 39040fe15e0SLoGin init_info.auxv.insert(AtType::Phdr as u8, phdr_vaddr.data()); 39140fe15e0SLoGin init_info 39240fe15e0SLoGin .auxv 39340fe15e0SLoGin .insert(AtType::PhNum as u8, ehdr.e_phnum as usize); 39440fe15e0SLoGin init_info 39540fe15e0SLoGin .auxv 39640fe15e0SLoGin .insert(AtType::Entry as u8, entrypoint_vaddr.data()); 39740fe15e0SLoGin 39840fe15e0SLoGin return Ok(()); 39940fe15e0SLoGin } 40040fe15e0SLoGin 40140fe15e0SLoGin /// 解析文件的ehdr parse_ehdr(data: &[u8]) -> Result<FileHeader<AnyEndian>, elf::ParseError>40240fe15e0SLoGin fn parse_ehdr(data: &[u8]) -> Result<FileHeader<AnyEndian>, elf::ParseError> { 40340fe15e0SLoGin let ident_buf = data.get_bytes(0..elf::abi::EI_NIDENT)?; 40440fe15e0SLoGin let ident = elf::file::parse_ident::<AnyEndian>(ident_buf)?; 40540fe15e0SLoGin 40640fe15e0SLoGin let tail_start = elf::abi::EI_NIDENT; 40740fe15e0SLoGin let tail_end = match ident.1 { 40840fe15e0SLoGin elf::file::Class::ELF32 => tail_start + elf::file::ELF32_EHDR_TAILSIZE, 40940fe15e0SLoGin elf::file::Class::ELF64 => tail_start + elf::file::ELF64_EHDR_TAILSIZE, 41040fe15e0SLoGin }; 41140fe15e0SLoGin let tail_buf = data.get_bytes(tail_start..tail_end)?; 41240fe15e0SLoGin 41340fe15e0SLoGin let ehdr: FileHeader<_> = FileHeader::parse_tail(ident, tail_buf)?; 41440fe15e0SLoGin return Ok(ehdr); 41540fe15e0SLoGin } 41640fe15e0SLoGin 41740fe15e0SLoGin /// 解析文件的program header table 41840fe15e0SLoGin /// 41940fe15e0SLoGin /// ## 参数 42040fe15e0SLoGin /// 42140fe15e0SLoGin /// - `param`:执行参数 42240fe15e0SLoGin /// - `ehdr`:文件头 42340fe15e0SLoGin /// - `data_buf`:用于缓存SegmentTable的Vec。 42440fe15e0SLoGin /// 这是因为SegmentTable的生命周期与data_buf一致。初始化这个Vec的大小为0即可。 42540fe15e0SLoGin /// 42640fe15e0SLoGin /// ## 说明 42740fe15e0SLoGin /// 42840fe15e0SLoGin /// 这个函数由elf库的`elf::elf_bytes::find_phdrs`修改而来。 parse_segments<'a>( param: &mut ExecParam, ehdr: &FileHeader<AnyEndian>, data_buf: &'a mut Vec<u8>, ) -> Result<Option<elf::segment::SegmentTable<'a, AnyEndian>>, elf::ParseError>42940fe15e0SLoGin fn parse_segments<'a>( 43040fe15e0SLoGin param: &mut ExecParam, 43140fe15e0SLoGin ehdr: &FileHeader<AnyEndian>, 43240fe15e0SLoGin data_buf: &'a mut Vec<u8>, 43340fe15e0SLoGin ) -> Result<Option<elf::segment::SegmentTable<'a, AnyEndian>>, elf::ParseError> { 43440fe15e0SLoGin // It's Ok to have no program headers 43540fe15e0SLoGin if ehdr.e_phoff == 0 { 43640fe15e0SLoGin return Ok(None); 43740fe15e0SLoGin } 43840fe15e0SLoGin let file = param.file_mut(); 43940fe15e0SLoGin // If the number of segments is greater than or equal to PN_XNUM (0xffff), 44040fe15e0SLoGin // e_phnum is set to PN_XNUM, and the actual number of program header table 44140fe15e0SLoGin // entries is contained in the sh_info field of the section header at index 0. 44240fe15e0SLoGin let mut phnum = ehdr.e_phnum as usize; 44340fe15e0SLoGin if phnum == elf::abi::PN_XNUM as usize { 44440fe15e0SLoGin let shoff: usize = ehdr.e_shoff.try_into()?; 44540fe15e0SLoGin 44640fe15e0SLoGin // 从磁盘读取shdr的前2个entry 44740fe15e0SLoGin file.lseek(SeekFrom::SeekSet(shoff as i64)) 44840fe15e0SLoGin .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?; 44940fe15e0SLoGin let shdr_buf_size = ehdr.e_shentsize * 2; 45040fe15e0SLoGin let mut shdr_buf = vec![0u8; shdr_buf_size as usize]; 45140fe15e0SLoGin file.read(shdr_buf_size as usize, &mut shdr_buf) 45240fe15e0SLoGin .map_err(|_| elf::ParseError::BadOffset(shoff as u64))?; 45340fe15e0SLoGin 45440fe15e0SLoGin let mut offset = 0; 45540fe15e0SLoGin let shdr0 = <elf::section::SectionHeader as elf::parse::ParseAt>::parse_at( 45640fe15e0SLoGin ehdr.endianness, 45740fe15e0SLoGin ehdr.class, 45840fe15e0SLoGin &mut offset, 45940fe15e0SLoGin &shdr_buf, 46040fe15e0SLoGin )?; 46140fe15e0SLoGin phnum = shdr0.sh_info.try_into()?; 46240fe15e0SLoGin } 46340fe15e0SLoGin 46440fe15e0SLoGin // Validate phentsize before trying to read the table so that we can error early for corrupted files 46540fe15e0SLoGin let entsize = <ProgramHeader as elf::parse::ParseAt>::validate_entsize( 46640fe15e0SLoGin ehdr.class, 46740fe15e0SLoGin ehdr.e_phentsize as usize, 46840fe15e0SLoGin )?; 46940fe15e0SLoGin let phoff: usize = ehdr.e_phoff.try_into()?; 47040fe15e0SLoGin let size = entsize 47140fe15e0SLoGin .checked_mul(phnum) 47240fe15e0SLoGin .ok_or(elf::ParseError::IntegerOverflow)?; 47340fe15e0SLoGin phoff 47440fe15e0SLoGin .checked_add(size) 47540fe15e0SLoGin .ok_or(elf::ParseError::IntegerOverflow)?; 47640fe15e0SLoGin 47740fe15e0SLoGin // 读取program header table 47840fe15e0SLoGin 47940fe15e0SLoGin file.lseek(SeekFrom::SeekSet(phoff as i64)) 48040fe15e0SLoGin .map_err(|_| elf::ParseError::BadOffset(phoff as u64))?; 48140fe15e0SLoGin data_buf.clear(); 48240fe15e0SLoGin data_buf.resize(size, 0); 48340fe15e0SLoGin 48440fe15e0SLoGin file.read(size, data_buf) 48540fe15e0SLoGin .expect("read program header table failed"); 48640fe15e0SLoGin let buf = data_buf.get_bytes(0..size)?; 48740fe15e0SLoGin 48840fe15e0SLoGin return Ok(Some(elf::segment::SegmentTable::new( 48940fe15e0SLoGin ehdr.endianness, 49040fe15e0SLoGin ehdr.class, 49140fe15e0SLoGin buf, 49240fe15e0SLoGin ))); 49340fe15e0SLoGin } 494a02ce654SChiichen 495a02ce654SChiichen // 解析 PT_GNU_PROPERTY 类型的段 496a02ce654SChiichen // 参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#767 parse_gnu_property() -> Result<(), ExecError>497a02ce654SChiichen fn parse_gnu_property() -> Result<(), ExecError> { 498a02ce654SChiichen return Ok(()); 499a02ce654SChiichen } 50040fe15e0SLoGin } 50140fe15e0SLoGin 50240fe15e0SLoGin impl BinaryLoader for ElfLoader { probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError>503b5b571e0SLoGin fn probe(&'static self, param: &ExecParam, buf: &[u8]) -> Result<(), ExecError> { 50440fe15e0SLoGin // let elf_bytes = 50540fe15e0SLoGin // ElfBytes::<AnyEndian>::minimal_parse(buf).map_err(|_| ExecError::NotExecutable)?; 50640fe15e0SLoGin 50740fe15e0SLoGin let ehdr = Self::parse_ehdr(buf).map_err(|_| ExecError::NotExecutable)?; 50840fe15e0SLoGin 50940fe15e0SLoGin #[cfg(target_arch = "x86_64")] 51040fe15e0SLoGin return self.probe_x86_64(param, &ehdr); 51140fe15e0SLoGin 5124fda81ceSLoGin #[cfg(target_arch = "riscv64")] 5134fda81ceSLoGin return self.probe_riscv(param, &ehdr); 5144fda81ceSLoGin 5154fda81ceSLoGin #[cfg(not(any(target_arch = "x86_64", target_arch = "riscv64")))] 5164fda81ceSLoGin compile_error!("BinaryLoader: Unsupported architecture"); 51740fe15e0SLoGin } 51840fe15e0SLoGin load( &'static self, param: &mut ExecParam, head_buf: &[u8], ) -> Result<BinaryLoaderResult, ExecError>51940fe15e0SLoGin fn load( 520b5b571e0SLoGin &'static self, 52140fe15e0SLoGin param: &mut ExecParam, 52240fe15e0SLoGin head_buf: &[u8], 52340fe15e0SLoGin ) -> Result<BinaryLoaderResult, ExecError> { 52440fe15e0SLoGin // 解析elf文件头 52540fe15e0SLoGin let ehdr = Self::parse_ehdr(head_buf).map_err(|_| ExecError::NotExecutable)?; 52640fe15e0SLoGin 52740fe15e0SLoGin // 参考linux-5.19的load_elf_binary函数 528e7071df6SLoGin // https://code.dragonos.org.cn/xref/linux-5.19.10/fs/binfmt_elf.c?r=&mo=22652&fi=824#1034 52940fe15e0SLoGin 53040fe15e0SLoGin let elf_type = ElfType::from(ehdr.e_type); 531*2eab6dd7S曾俊 // debug!("ehdr = {:?}", ehdr); 53240fe15e0SLoGin 53340fe15e0SLoGin let binding = param.vm().clone(); 53440fe15e0SLoGin let mut user_vm = binding.write(); 53540fe15e0SLoGin 53640fe15e0SLoGin // todo: 增加对user stack上的内存是否具有可执行权限的处理(方法:寻找phdr里面的PT_GNU_STACK段) 53740fe15e0SLoGin 538*2eab6dd7S曾俊 // debug!("to parse segments"); 53940fe15e0SLoGin // 加载ELF文件并映射到用户空间 54040fe15e0SLoGin let mut phdr_buf = Vec::new(); 541a02ce654SChiichen let phdr_table = Self::parse_segments(param, &ehdr, &mut phdr_buf) 54240fe15e0SLoGin .map_err(|_| ExecError::ParseError)? 543a02ce654SChiichen .ok_or(ExecError::ParseError)?; 544a02ce654SChiichen let mut _gnu_property_data: Option<ProgramHeader> = None; 545a02ce654SChiichen let interpreter: Option<File> = None; 546a02ce654SChiichen for seg in phdr_table { 547a02ce654SChiichen if seg.p_type == PT_GNU_PROPERTY { 548b5b571e0SLoGin _gnu_property_data = Some(seg); 549a02ce654SChiichen continue; 550a02ce654SChiichen } 551a02ce654SChiichen if seg.p_type != PT_INTERP { 552a02ce654SChiichen continue; 553a02ce654SChiichen } 554471d65cfSLoGin 555a02ce654SChiichen // 接下来处理这个 .interpreter 段以及动态链接器 556a02ce654SChiichen // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#881 557a02ce654SChiichen 558a02ce654SChiichen if seg.p_filesz > 4096 || seg.p_filesz < 2 { 559a02ce654SChiichen return Err(ExecError::NotExecutable); 560a02ce654SChiichen } 561a02ce654SChiichen 562a02ce654SChiichen let interpreter_ptr = unsafe { 563a02ce654SChiichen core::slice::from_raw_parts( 564a02ce654SChiichen seg.p_offset as *const u8, 565a02ce654SChiichen seg.p_filesz.try_into().unwrap(), 566a02ce654SChiichen ) 567a02ce654SChiichen }; 568a02ce654SChiichen let _interpreter_path = core::str::from_utf8(interpreter_ptr).map_err(|e| { 569a02ce654SChiichen ExecError::Other(format!( 570a02ce654SChiichen "Failed to parse the path of dynamic linker with error {}", 571a02ce654SChiichen e 572a02ce654SChiichen )) 573a02ce654SChiichen })?; 574a02ce654SChiichen 575a02ce654SChiichen //TODO 加入对动态链接器的加载,参照 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#890 576a02ce654SChiichen } 577a02ce654SChiichen if interpreter.is_some() { 578a02ce654SChiichen /* Some simple consistency checks for the interpreter */ 579a02ce654SChiichen // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#950 580a02ce654SChiichen } 581a02ce654SChiichen Self::parse_gnu_property()?; 58240fe15e0SLoGin 58340fe15e0SLoGin let mut elf_brk = VirtAddr::new(0); 58440fe15e0SLoGin let mut elf_bss = VirtAddr::new(0); 58540fe15e0SLoGin let mut start_code: Option<VirtAddr> = None; 58640fe15e0SLoGin let mut end_code: Option<VirtAddr> = None; 58740fe15e0SLoGin let mut start_data: Option<VirtAddr> = None; 58840fe15e0SLoGin let mut end_data: Option<VirtAddr> = None; 58940fe15e0SLoGin 590a02ce654SChiichen // 加载的时候的偏移量(这个偏移量在加载动态链接段的时候产生) 591a02ce654SChiichen let mut load_bias = 0usize; 59240fe15e0SLoGin let mut bss_prot_flags = ProtFlags::empty(); 59340fe15e0SLoGin // 是否是第一个加载的段 59440fe15e0SLoGin let mut first_pt_load = true; 59540fe15e0SLoGin // program header的虚拟地址 59640fe15e0SLoGin let mut phdr_vaddr: Option<VirtAddr> = None; 597a02ce654SChiichen let mut _reloc_func_desc = 0usize; 598a02ce654SChiichen // 参考https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1158,获取要加载的total_size 599a02ce654SChiichen let mut has_load = false; 600a02ce654SChiichen let mut min_address = VirtAddr::new(usize::MAX); 601a02ce654SChiichen let mut max_address = VirtAddr::new(0usize); 602a02ce654SChiichen let loadable_sections = phdr_table 603a02ce654SChiichen .into_iter() 604a02ce654SChiichen .filter(|seg| seg.p_type == elf::abi::PT_LOAD); 605471d65cfSLoGin 606a02ce654SChiichen for seg_to_load in loadable_sections { 607a02ce654SChiichen min_address = min( 608a02ce654SChiichen min_address, 609a02ce654SChiichen self.elf_page_start(VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap())), 610a02ce654SChiichen ); 611a02ce654SChiichen max_address = max( 612a02ce654SChiichen max_address, 613a02ce654SChiichen VirtAddr::new( 614a02ce654SChiichen (seg_to_load.p_vaddr + seg_to_load.p_memsz) 615a02ce654SChiichen .try_into() 616a02ce654SChiichen .unwrap(), 617a02ce654SChiichen ), 618a02ce654SChiichen ); 619a02ce654SChiichen has_load = true; 620a02ce654SChiichen } 621a02ce654SChiichen let total_size = if has_load { 622a02ce654SChiichen max_address - min_address 623a02ce654SChiichen } else { 624a02ce654SChiichen 0 625a02ce654SChiichen }; 626a02ce654SChiichen let loadable_sections = phdr_table 627a02ce654SChiichen .into_iter() 628a02ce654SChiichen .filter(|seg| seg.p_type == elf::abi::PT_LOAD); 62940fe15e0SLoGin for seg_to_load in loadable_sections { 630*2eab6dd7S曾俊 // debug!("seg_to_load = {:?}", seg_to_load); 63140fe15e0SLoGin if unlikely(elf_brk > elf_bss) { 632*2eab6dd7S曾俊 // debug!( 63340fe15e0SLoGin // "to set brk, elf_brk = {:?}, elf_bss = {:?}", 63440fe15e0SLoGin // elf_brk, 63540fe15e0SLoGin // elf_bss 63640fe15e0SLoGin // ); 63740fe15e0SLoGin self.set_elf_brk( 63840fe15e0SLoGin &mut user_vm, 63940fe15e0SLoGin elf_bss + load_bias, 64040fe15e0SLoGin elf_brk + load_bias, 64140fe15e0SLoGin bss_prot_flags, 64240fe15e0SLoGin )?; 64340fe15e0SLoGin let nbyte = self.elf_page_offset(elf_bss); 64440fe15e0SLoGin if nbyte > 0 { 645a02ce654SChiichen let nbyte = min(CurrentElfArch::ELF_PAGE_SIZE - nbyte, elf_brk - elf_bss); 64640fe15e0SLoGin unsafe { 64740fe15e0SLoGin // This bss-zeroing can fail if the ELF file specifies odd protections. 64840fe15e0SLoGin // So we don't check the return value. 64940fe15e0SLoGin clear_user(elf_bss + load_bias, nbyte).ok(); 65040fe15e0SLoGin } 65140fe15e0SLoGin } 65240fe15e0SLoGin } 65340fe15e0SLoGin 65440fe15e0SLoGin // 生成ProtFlags. 655a02ce654SChiichen let elf_prot_flags = self.make_prot(seg_to_load.p_flags, interpreter.is_some(), false); 65640fe15e0SLoGin 65740fe15e0SLoGin let mut elf_map_flags = MapFlags::MAP_PRIVATE; 65840fe15e0SLoGin 659a02ce654SChiichen let vaddr = VirtAddr::new(seg_to_load.p_vaddr.try_into().unwrap()); 66040fe15e0SLoGin 661b5b571e0SLoGin #[allow(clippy::if_same_then_else)] 66240fe15e0SLoGin if !first_pt_load { 66340fe15e0SLoGin elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE); 66440fe15e0SLoGin } else if elf_type == ElfType::Executable { 66540fe15e0SLoGin /* 66640fe15e0SLoGin * This logic is run once for the first LOAD Program 66740fe15e0SLoGin * Header for ET_EXEC binaries. No special handling 66840fe15e0SLoGin * is needed. 66940fe15e0SLoGin */ 67040fe15e0SLoGin elf_map_flags.insert(MapFlags::MAP_FIXED_NOREPLACE); 67140fe15e0SLoGin } else if elf_type == ElfType::DSO { 67240fe15e0SLoGin // TODO: 支持动态链接 673a02ce654SChiichen if interpreter.is_some() { 674a02ce654SChiichen load_bias = CurrentElfArch::ELF_ET_DYN_BASE; 675a02ce654SChiichen if ProcessManager::current_pcb() 676a02ce654SChiichen .flags() 677a02ce654SChiichen .contains(ProcessFlags::RANDOMIZE) 678a02ce654SChiichen { 679a02ce654SChiichen //这里x86下需要一个随机加载的方法,但是很多架构,比如Risc-V都是0,就暂时不写了 680a02ce654SChiichen } else { 681a02ce654SChiichen load_bias = 0; 682a02ce654SChiichen } 683a02ce654SChiichen } 684a02ce654SChiichen load_bias = self 685a02ce654SChiichen .elf_page_start(VirtAddr::new( 686a02ce654SChiichen load_bias - TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(), 687a02ce654SChiichen )) 688a02ce654SChiichen .data(); 689a02ce654SChiichen if total_size == 0 { 690a02ce654SChiichen return Err(ExecError::InvalidParemeter); 691a02ce654SChiichen } 69240fe15e0SLoGin } 69340fe15e0SLoGin 69440fe15e0SLoGin // 加载这个段到用户空间 695*2eab6dd7S曾俊 // debug!("to load elf segment"); 69640fe15e0SLoGin let e = self 69740fe15e0SLoGin .load_elf_segment( 69840fe15e0SLoGin &mut user_vm, 69940fe15e0SLoGin param, 70040fe15e0SLoGin &seg_to_load, 70140fe15e0SLoGin vaddr + load_bias, 70240fe15e0SLoGin &elf_prot_flags, 70340fe15e0SLoGin &elf_map_flags, 704a02ce654SChiichen total_size, 70540fe15e0SLoGin ) 706471d65cfSLoGin .map_err(|e| { 707*2eab6dd7S曾俊 error!("load_elf_segment failed: {:?}", e); 708471d65cfSLoGin match e { 70940fe15e0SLoGin SystemError::EFAULT => ExecError::BadAddress(None), 71040fe15e0SLoGin SystemError::ENOMEM => ExecError::OutOfMemory, 71140fe15e0SLoGin _ => ExecError::Other(format!("load_elf_segment failed: {:?}", e)), 712471d65cfSLoGin } 71340fe15e0SLoGin })?; 71440fe15e0SLoGin 71540fe15e0SLoGin // 如果地址不对,那么就报错 71640fe15e0SLoGin if !e.1 { 71740fe15e0SLoGin return Err(ExecError::BadAddress(Some(e.0))); 71840fe15e0SLoGin } 71940fe15e0SLoGin 72040fe15e0SLoGin if first_pt_load { 72140fe15e0SLoGin first_pt_load = false; 72240fe15e0SLoGin if elf_type == ElfType::DSO { 72340fe15e0SLoGin // todo: 在这里增加对load_bias和reloc_func_desc的更新代码 724a02ce654SChiichen load_bias += e.0.data() 725a02ce654SChiichen - self 726a02ce654SChiichen .elf_page_start(VirtAddr::new( 727a02ce654SChiichen load_bias 728a02ce654SChiichen + TryInto::<usize>::try_into(seg_to_load.p_vaddr).unwrap(), 729a02ce654SChiichen )) 730a02ce654SChiichen .data(); 731a02ce654SChiichen _reloc_func_desc = load_bias; 73240fe15e0SLoGin } 73340fe15e0SLoGin } 73440fe15e0SLoGin 735*2eab6dd7S曾俊 // debug!("seg_to_load.p_offset={}", seg_to_load.p_offset); 736*2eab6dd7S曾俊 // debug!("e_phoff={}", ehdr.e_phoff); 737*2eab6dd7S曾俊 // debug!("seg_to_load.p_filesz={}", seg_to_load.p_filesz); 73840fe15e0SLoGin // Figure out which segment in the file contains the Program Header Table, 73940fe15e0SLoGin // and map to the associated virtual address. 74040fe15e0SLoGin if (seg_to_load.p_offset <= ehdr.e_phoff) 74140fe15e0SLoGin && (ehdr.e_phoff < (seg_to_load.p_offset + seg_to_load.p_filesz)) 74240fe15e0SLoGin { 74340fe15e0SLoGin phdr_vaddr = Some(VirtAddr::new( 74440fe15e0SLoGin (ehdr.e_phoff - seg_to_load.p_offset + seg_to_load.p_vaddr) as usize, 74540fe15e0SLoGin )); 74640fe15e0SLoGin } 74740fe15e0SLoGin 74840fe15e0SLoGin let p_vaddr = VirtAddr::new(seg_to_load.p_vaddr as usize); 749b5b571e0SLoGin if (seg_to_load.p_flags & elf::abi::PF_X) != 0 750b5b571e0SLoGin && (start_code.is_none() || start_code.as_ref().unwrap() > &p_vaddr) 751b5b571e0SLoGin { 75240fe15e0SLoGin start_code = Some(p_vaddr); 75340fe15e0SLoGin } 75440fe15e0SLoGin 75540fe15e0SLoGin if start_data.is_none() 75640fe15e0SLoGin || (start_data.is_some() && start_data.as_ref().unwrap() > &p_vaddr) 75740fe15e0SLoGin { 75840fe15e0SLoGin start_data = Some(p_vaddr); 75940fe15e0SLoGin } 76040fe15e0SLoGin 76140fe15e0SLoGin // 如果程序段要加载的目标地址不在用户空间内,或者是其他不合法的情况,那么就报错 76240fe15e0SLoGin if !p_vaddr.check_user() 76340fe15e0SLoGin || seg_to_load.p_filesz > seg_to_load.p_memsz 7645d549a76SChiichen || self.elf_page_align_up(p_vaddr + seg_to_load.p_memsz as usize) 7655d549a76SChiichen >= MMArch::USER_END_VADDR 76640fe15e0SLoGin { 767*2eab6dd7S曾俊 // debug!("ERR: p_vaddr={p_vaddr:?}"); 76840fe15e0SLoGin return Err(ExecError::InvalidParemeter); 76940fe15e0SLoGin } 77040fe15e0SLoGin 77140fe15e0SLoGin // end vaddr of this segment(code+data+bss) 77240fe15e0SLoGin let seg_end_vaddr_f = self.elf_page_align_up(VirtAddr::new( 77340fe15e0SLoGin (seg_to_load.p_vaddr + seg_to_load.p_filesz) as usize, 77440fe15e0SLoGin )); 77540fe15e0SLoGin 77640fe15e0SLoGin if seg_end_vaddr_f > elf_bss { 77740fe15e0SLoGin elf_bss = seg_end_vaddr_f; 77840fe15e0SLoGin } 77940fe15e0SLoGin 78040fe15e0SLoGin if ((seg_to_load.p_flags & elf::abi::PF_X) != 0) 78140fe15e0SLoGin && (end_code.is_none() 78240fe15e0SLoGin || (end_code.is_some() && end_code.as_ref().unwrap() < &seg_end_vaddr_f)) 78340fe15e0SLoGin { 78440fe15e0SLoGin end_code = Some(seg_end_vaddr_f); 78540fe15e0SLoGin } 78640fe15e0SLoGin 78740fe15e0SLoGin if end_data.is_none() 78840fe15e0SLoGin || (end_data.is_some() && end_data.as_ref().unwrap() < &seg_end_vaddr_f) 78940fe15e0SLoGin { 79040fe15e0SLoGin end_data = Some(seg_end_vaddr_f); 79140fe15e0SLoGin } 79240fe15e0SLoGin 79340fe15e0SLoGin let seg_end_vaddr = VirtAddr::new((seg_to_load.p_vaddr + seg_to_load.p_memsz) as usize); 79440fe15e0SLoGin 79540fe15e0SLoGin if seg_end_vaddr > elf_brk { 79640fe15e0SLoGin bss_prot_flags = elf_prot_flags; 79740fe15e0SLoGin elf_brk = seg_end_vaddr; 79840fe15e0SLoGin } 79940fe15e0SLoGin } 800*2eab6dd7S曾俊 // debug!("elf load: phdr_vaddr={phdr_vaddr:?}"); 80140fe15e0SLoGin let program_entrypoint = VirtAddr::new(ehdr.e_entry as usize + load_bias); 802b5b571e0SLoGin let phdr_vaddr = phdr_vaddr.map(|phdr_vaddr| phdr_vaddr + load_bias); 80340fe15e0SLoGin 80440fe15e0SLoGin elf_bss += load_bias; 80540fe15e0SLoGin elf_brk += load_bias; 80640fe15e0SLoGin start_code = start_code.map(|v| v + load_bias); 80740fe15e0SLoGin end_code = end_code.map(|v| v + load_bias); 80840fe15e0SLoGin start_data = start_data.map(|v| v + load_bias); 80940fe15e0SLoGin end_data = end_data.map(|v| v + load_bias); 81040fe15e0SLoGin 811*2eab6dd7S曾俊 // debug!( 81240fe15e0SLoGin // "to set brk: elf_bss: {:?}, elf_brk: {:?}, bss_prot_flags: {:?}", 81340fe15e0SLoGin // elf_bss, 81440fe15e0SLoGin // elf_brk, 81540fe15e0SLoGin // bss_prot_flags 81640fe15e0SLoGin // ); 81740fe15e0SLoGin self.set_elf_brk(&mut user_vm, elf_bss, elf_brk, bss_prot_flags)?; 81840fe15e0SLoGin 81940fe15e0SLoGin if likely(elf_bss != elf_brk) && unlikely(self.pad_zero(elf_bss).is_err()) { 820*2eab6dd7S曾俊 // debug!("elf_bss = {elf_bss:?}, elf_brk = {elf_brk:?}"); 82140fe15e0SLoGin return Err(ExecError::BadAddress(Some(elf_bss))); 82240fe15e0SLoGin } 823a02ce654SChiichen if interpreter.is_some() { 824a02ce654SChiichen // TODO 添加对动态加载器的处理 825a02ce654SChiichen // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/fs/binfmt_elf.c#1249 826a02ce654SChiichen } 827*2eab6dd7S曾俊 // debug!("to create auxv"); 82840fe15e0SLoGin 82940fe15e0SLoGin self.create_auxv(param, program_entrypoint, phdr_vaddr, &ehdr)?; 83040fe15e0SLoGin 831*2eab6dd7S曾俊 // debug!("auxv create ok"); 83240fe15e0SLoGin user_vm.start_code = start_code.unwrap_or(VirtAddr::new(0)); 83340fe15e0SLoGin user_vm.end_code = end_code.unwrap_or(VirtAddr::new(0)); 83440fe15e0SLoGin user_vm.start_data = start_data.unwrap_or(VirtAddr::new(0)); 83540fe15e0SLoGin user_vm.end_data = end_data.unwrap_or(VirtAddr::new(0)); 83640fe15e0SLoGin 83740fe15e0SLoGin let result = BinaryLoaderResult::new(program_entrypoint); 838*2eab6dd7S曾俊 // debug!("elf load OK!!!"); 83940fe15e0SLoGin return Ok(result); 84040fe15e0SLoGin } 84140fe15e0SLoGin } 84240fe15e0SLoGin 84340fe15e0SLoGin /// Elf机器架构,对应于e_machine字段。在ABI中,以EM_开头的常量是e_machine字段的值。 84440fe15e0SLoGin #[derive(Debug, Eq, PartialEq)] 84540fe15e0SLoGin pub enum ElfMachine { 84640fe15e0SLoGin I386, 84740fe15e0SLoGin AArch32, 84840fe15e0SLoGin AArch64, 84940fe15e0SLoGin X86_64, 85040fe15e0SLoGin RiscV, 85140fe15e0SLoGin /// 龙芯架构 85240fe15e0SLoGin LoongArch, 85340fe15e0SLoGin /// 未知架构 85440fe15e0SLoGin Unknown, 85540fe15e0SLoGin } 85640fe15e0SLoGin 85740fe15e0SLoGin impl From<u16> for ElfMachine { from(machine: u16) -> Self85840fe15e0SLoGin fn from(machine: u16) -> Self { 85940fe15e0SLoGin match machine { 86040fe15e0SLoGin 0x03 => Self::I386, 86140fe15e0SLoGin 0x28 => Self::AArch32, 86240fe15e0SLoGin 0xb7 => Self::AArch64, 86340fe15e0SLoGin 0x3e => Self::X86_64, 86440fe15e0SLoGin 0xf3 => Self::RiscV, 86540fe15e0SLoGin 0x102 => Self::LoongArch, 86640fe15e0SLoGin // 未知架构 86740fe15e0SLoGin _ => Self::Unknown, 86840fe15e0SLoGin } 86940fe15e0SLoGin } 87040fe15e0SLoGin } 87140fe15e0SLoGin 87240fe15e0SLoGin /// Elf文件类型,对应于e_type字段。在ABI中,以ET_开头的常量是e_type字段的值。 87340fe15e0SLoGin #[derive(Debug, Eq, PartialEq)] 87440fe15e0SLoGin pub enum ElfType { 87540fe15e0SLoGin /// 可重定位文件 87640fe15e0SLoGin Relocatable, 87740fe15e0SLoGin /// 可执行文件 87840fe15e0SLoGin Executable, 87940fe15e0SLoGin /// 动态链接库 88040fe15e0SLoGin DSO, 88140fe15e0SLoGin /// 核心转储文件 88240fe15e0SLoGin Core, 88340fe15e0SLoGin /// 未知类型 88440fe15e0SLoGin Unknown, 88540fe15e0SLoGin } 88640fe15e0SLoGin 88740fe15e0SLoGin impl From<u16> for ElfType { from(elf_type: u16) -> Self88840fe15e0SLoGin fn from(elf_type: u16) -> Self { 88940fe15e0SLoGin match elf_type { 89040fe15e0SLoGin 0x01 => Self::Relocatable, 89140fe15e0SLoGin 0x02 => Self::Executable, 89240fe15e0SLoGin 0x03 => Self::DSO, 89340fe15e0SLoGin 0x04 => Self::Core, 89440fe15e0SLoGin _ => Self::Unknown, 89540fe15e0SLoGin } 89640fe15e0SLoGin } 89740fe15e0SLoGin } 89840fe15e0SLoGin 89940fe15e0SLoGin // Simple convenience extension trait to wrap get() with .ok_or(SliceReadError) 90040fe15e0SLoGin trait ReadBytesExt<'data> { get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError>90140fe15e0SLoGin fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError>; 90240fe15e0SLoGin } 90340fe15e0SLoGin impl<'data> ReadBytesExt<'data> for &'data [u8] { get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError>90440fe15e0SLoGin fn get_bytes(self, range: Range<usize>) -> Result<&'data [u8], elf::ParseError> { 90540fe15e0SLoGin let start = range.start; 90640fe15e0SLoGin let end = range.end; 90740fe15e0SLoGin self.get(range) 90840fe15e0SLoGin .ok_or(elf::ParseError::SliceReadError((start, end))) 90940fe15e0SLoGin } 91040fe15e0SLoGin } 911