From afc4bf75200182dee9283678a6ef102fa25e56b9 Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Wed, 3 Apr 2024 15:28:15 +0800 Subject: [PATCH] Modify the behavior of mapping segment vmo --- .../process/program_loader/elf/load_elf.rs | 57 ++++++++++++------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs b/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs index 223bb16d0..f1a1b404f 100644 --- a/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs +++ b/kernel/aster-nix/src/process/program_loader/elf/load_elf.rs @@ -27,7 +27,7 @@ use crate::{ vm::{ perms::VmPerms, vmar::Vmar, - vmo::{Vmo, VmoFlags, VmoOptions, VmoRightsOp}, + vmo::{Vmo, VmoOptions, VmoRightsOp}, }, }; @@ -198,8 +198,14 @@ pub fn map_segment_vmos(elf: &Elf, root_vmar: &Vmar, elf_file: &Dentry) -> .map_err(|_| Error::with_message(Errno::ENOEXEC, "parse program header type fails"))?; if type_ == program::Type::Load { check_segment_align(program_header)?; - let vmo = init_segment_vmo(program_header, elf_file)?; - map_segment_vmo(program_header, vmo, root_vmar, base_addr)?; + let (vmo, anonymous_map_size) = init_segment_vmo(program_header, elf_file)?; + map_segment_vmo( + program_header, + vmo, + anonymous_map_size, + root_vmar, + base_addr, + )?; } } Ok(base_addr) @@ -234,6 +240,7 @@ fn base_map_addr(elf: &Elf, root_vmar: &Vmar) -> Result { fn map_segment_vmo( program_header: &ProgramHeader64, vmo: Vmo, + anonymous_map_size: usize, root_vmar: &Vmar, base_addr: Vaddr, ) -> Result<()> { @@ -245,15 +252,28 @@ fn map_segment_vmo( program_header.mem_size, perms ); + let vmo_size = vmo.size(); let mut vm_map_options = root_vmar.new_map(vmo, perms)?.can_overwrite(true); let offset = base_addr + offset; vm_map_options = vm_map_options.offset(offset); let map_addr = vm_map_options.build()?; + + if anonymous_map_size > 0 { + let anonymous_vmo = { + let options: VmoOptions = VmoOptions::new(anonymous_map_size); + options.alloc()? + }; + let mut anonymous_map_options = + root_vmar.new_map(anonymous_vmo, perms)?.can_overwrite(true); + anonymous_map_options = anonymous_map_options.offset(offset + vmo_size); + let anonymous_map_addr = anonymous_map_options.build()?; + } Ok(()) } -/// create vmo for each segment -fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result { +/// Create VMO for each segment. Return the segment VMO and the size of +/// additional anonymous mapping it needs. +fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Result<(Vmo, usize)> { trace!( "mem range = 0x{:x} - 0x{:x}, mem_size = 0x{:x}", program_header.virtual_addr, @@ -277,6 +297,11 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu "executable has no page cache", ))? }; + let vmo_size = { + let vmap_start = virtual_addr.align_down(PAGE_SIZE); + let vmap_end = (virtual_addr + program_header.mem_size as usize).align_up(PAGE_SIZE); + vmap_end - vmap_start + }; let segment_vmo = { let parent_range = { @@ -284,20 +309,14 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu let end = (file_offset + program_header.file_size as usize).align_up(PAGE_SIZE); start..end }; - let vmo_size = { - let vmap_start = virtual_addr.align_down(PAGE_SIZE); - let vmap_end = (virtual_addr + program_header.mem_size as usize).align_up(PAGE_SIZE); - vmap_end - vmap_start - }; debug_assert!(vmo_size >= (program_header.file_size as usize).align_up(PAGE_SIZE)); - let segment_vmo = page_cache_vmo - .new_cow_child(parent_range)? - .flags(VmoFlags::RESIZABLE) - .alloc()?; - if vmo_size > segment_vmo.size() { - segment_vmo.resize(vmo_size)?; - }; - segment_vmo + page_cache_vmo.new_cow_child(parent_range)?.alloc()? + }; + + let anonymous_map_size: usize = if vmo_size > segment_vmo.size() { + vmo_size - segment_vmo.size() + } else { + 0 }; // Write zero as paddings. There are head padding and tail padding. @@ -319,7 +338,7 @@ fn init_segment_vmo(program_header: &ProgramHeader64, elf_file: &Dentry) -> Resu let buffer = vec![0u8; (segment_vmo_size - tail_padding_offset) % PAGE_SIZE]; segment_vmo.write_bytes(tail_padding_offset, &buffer)?; } - Ok(segment_vmo.to_dyn()) + Ok((segment_vmo.to_dyn(), anonymous_map_size)) } fn parse_segment_perm(flags: xmas_elf::program::Flags) -> VmPerm {