xref: /DragonOS/kernel/src/libs/elf.rs (revision 2eab6dd743e94a86a685f1f3c01e599adf86610a)
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