Revert "`ProgramToLoad` only needs a `elf_inode: Arc<dyn Inode>` instead of a `Path`"

This reverts commit 71632a51b5.
This commit is contained in:
Wang Siyuan 2026-01-25 13:12:11 +00:00 committed by Tate, Hongliang Tian
parent 66ac28c4c2
commit fb8c9e0c27
4 changed files with 29 additions and 33 deletions

View File

@ -54,9 +54,8 @@ pub fn do_execve(
envp
);
let elf_inode = elf_file.inode();
let program_to_load =
ProgramToLoad::build_from_inode(elf_inode.clone(), &path_resolver, argv, envp)?;
ProgramToLoad::build_from_file(elf_file.clone(), &path_resolver, argv, envp)?;
let new_vmar = Vmar::new(ProcessVm::new(elf_file.clone()));
let elf_load_info = program_to_load.load_to_vmar(new_vmar.as_ref(), &path_resolver)?;

View File

@ -110,7 +110,7 @@ fn create_init_task(
let path_resolver = fs.resolver().read();
let program_to_load =
ProgramToLoad::build_from_inode(elf_path.inode().clone(), &path_resolver, argv, envp)?;
ProgramToLoad::build_from_file(elf_path.clone(), &path_resolver, argv, envp)?;
let vmar = process.lock_vmar();
let elf_load_info = program_to_load.load_to_vmar(vmar.unwrap(), &path_resolver)?;
let elf_abs_path = path_resolver.make_abs_path(&elf_path).into_string();

View File

@ -9,10 +9,7 @@ use super::{
relocate::RelocatedRange,
};
use crate::{
fs::{
path::{FsPath, Path, PathResolver},
utils::Inode,
},
fs::path::{FsPath, Path, PathResolver},
prelude::*,
process::{
process_vm::{AuxKey, AuxVec},
@ -22,7 +19,6 @@ use crate::{
vm::{
perms::VmPerms,
vmar::{VMAR_CAP_ADDR, VMAR_LOWEST_ADDR, Vmar},
vmo::Vmo,
},
};
@ -51,20 +47,20 @@ pub struct ElfLoadInfo {
/// initialize the init stack and heap.
pub fn load_elf_to_vmar(
vmar: &Vmar,
elf_inode: &Arc<dyn Inode>,
elf_file: Path,
path_resolver: &PathResolver,
elf_headers: ElfHeaders,
argv: Vec<CString>,
envp: Vec<CString>,
) -> Result<ElfLoadInfo> {
let ldso = lookup_and_parse_ldso(&elf_headers, elf_inode, path_resolver)?;
let ldso = lookup_and_parse_ldso(&elf_headers, &elf_file, path_resolver)?;
#[cfg_attr(
not(any(target_arch = "x86_64", target_arch = "riscv64")),
expect(unused_mut)
)]
let (elf_mapped_info, entry_point, mut aux_vec) =
map_vmos_and_build_aux_vec(vmar, ldso, &elf_headers, elf_inode)?;
map_vmos_and_build_aux_vec(vmar, ldso, &elf_headers, &elf_file)?;
// Map the vDSO and set the entry.
// Since the vDSO does not require being mapped to any specific address,
@ -93,12 +89,12 @@ pub fn load_elf_to_vmar(
fn lookup_and_parse_ldso(
headers: &ElfHeaders,
elf_inode: &Arc<dyn Inode>,
elf_file: &Path,
path_resolver: &PathResolver,
) -> Result<Option<(Path, ElfHeaders)>> {
let ldso_file = {
let ldso_path = if let Some(interp_phdr) = headers.interp_phdr() {
interp_phdr.read_ldso_path(elf_inode)?
interp_phdr.read_ldso_path(elf_file.inode())?
} else {
return Ok(None);
};
@ -139,7 +135,7 @@ fn map_vmos_and_build_aux_vec(
vmar: &Vmar,
ldso: Option<(Path, ElfHeaders)>,
parsed_elf: &ElfHeaders,
elf_inode: &Arc<dyn Inode>,
elf_file: &Path,
) -> Result<(ElfMappedInfo, Vaddr, AuxVec)> {
let ldso_load_info = if let Some((ldso_file, ldso_elf)) = ldso {
Some(load_ldso(vmar, &ldso_file, &ldso_elf)?)
@ -147,7 +143,7 @@ fn map_vmos_and_build_aux_vec(
None
};
let elf_mapped_info = map_segment_vmos(parsed_elf, vmar, elf_inode, ldso_load_info.is_some())?;
let elf_mapped_info = map_segment_vmos(parsed_elf, vmar, elf_file, ldso_load_info.is_some())?;
let mut aux_vec = {
let ldso_base = ldso_load_info
@ -157,7 +153,7 @@ fn map_vmos_and_build_aux_vec(
};
// Set AT_SECURE based on setuid/setgid bits of the executable file.
let mode = elf_inode.mode()?;
let mode = elf_file.inode().mode()?;
let secure = if mode.has_set_uid() || mode.has_set_gid() {
1
} else {
@ -192,7 +188,7 @@ struct LdsoLoadInfo {
}
fn load_ldso(vmar: &Vmar, ldso_file: &Path, ldso_elf: &ElfHeaders) -> Result<LdsoLoadInfo> {
let elf_mapped_info = map_segment_vmos(ldso_elf, vmar, ldso_file.inode(), false)?;
let elf_mapped_info = map_segment_vmos(ldso_elf, vmar, ldso_file, false)?;
let range = elf_mapped_info.full_range;
let entry_point = range
.relocated_addr_of(ldso_elf.entry_point())
@ -226,7 +222,7 @@ struct ElfMappedInfo {
fn map_segment_vmos(
elf: &ElfHeaders,
vmar: &Vmar,
elf_inode: &Arc<dyn Inode>,
elf_file: &Path,
has_interpreter: bool,
) -> Result<ElfMappedInfo> {
let elf_va_range = elf.calc_total_vaddr_bounds();
@ -330,14 +326,11 @@ fn map_segment_vmos(
let relocated_range = RelocatedRange::new(elf_va_range, map_range.start)
.expect("`map_range` should not overflow");
let Some(elf_vmo) = elf_inode.page_cache() else {
return_errno_with_message!(Errno::ENOEXEC, "the executable has no page cache");
};
for loadable_phdr in elf.loadable_phdrs() {
let map_at = relocated_range
.relocated_addr_of(loadable_phdr.virt_range().start)
.expect("`calc_total_vaddr_bounds()` should cover all segments");
map_segment_vmo(loadable_phdr, &elf_vmo, vmar, map_at)?;
map_segment_vmo(loadable_phdr, elf_file, vmar, map_at)?;
}
// Calculate the data segment size.
@ -358,10 +351,14 @@ fn map_segment_vmos(
/// this applies to the `.bss` segment.
fn map_segment_vmo(
loadable_phdr: &LoadablePhdr,
elf_vmo: &Arc<Vmo>,
elf_file: &Path,
vmar: &Vmar,
map_at: Vaddr,
) -> Result<()> {
let Some(elf_vmo) = elf_file.inode().page_cache() else {
return_errno_with_message!(Errno::ENOEXEC, "the executable has no page cache");
};
let virt_range = loadable_phdr.virt_range();
let file_range = loadable_phdr.file_range();
trace!(

View File

@ -9,7 +9,7 @@ use self::{
};
use crate::{
fs::{
path::{FsPath, PathResolver},
path::{FsPath, Path, PathResolver},
utils::{Inode, InodeType, Permission},
},
prelude::*,
@ -21,22 +21,22 @@ use crate::{
/// This struct encapsulates the ELF file to be executed along with its header data,
/// the `argv` and the `envp` which is required for the program execution.
pub(super) struct ProgramToLoad {
elf_inode: Arc<dyn Inode>,
elf_file: Path,
elf_headers: ElfHeaders,
argv: Vec<CString>,
envp: Vec<CString>,
}
impl ProgramToLoad {
/// Constructs a new `ProgramToLoad` from an inode and handles shebang interpretation if
/// Constructs a new `ProgramToLoad` from a file and handles shebang interpretation if
/// necessary.
pub(super) fn build_from_inode(
mut elf_inode: Arc<dyn Inode>,
pub(super) fn build_from_file(
mut elf_file: Path,
path_resolver: &PathResolver,
mut argv: Vec<CString>,
envp: Vec<CString>,
) -> Result<Self> {
check_executable_inode(elf_inode.as_ref())?;
check_executable_inode(elf_file.inode().as_ref())?;
// A limit to the recursion depth of shebang executables.
//
@ -48,7 +48,7 @@ impl ProgramToLoad {
// Read the first page of the file, which should contain a shebang or an ELF header.
let (file_first_page, len) = {
let mut buffer = Box::new([0u8; PAGE_SIZE]);
let len = elf_inode.read_bytes_at(0, &mut *buffer)?;
let len = elf_file.inode().read_bytes_at(0, &mut *buffer)?;
(buffer, len)
};
@ -71,13 +71,13 @@ impl ProgramToLoad {
// Update the argument list and the executable inode. Then, try again.
new_argv.extend(argv);
argv = new_argv;
elf_inode = interpreter.inode().clone();
elf_file = interpreter;
};
let elf_headers = ElfHeaders::parse(&file_first_page[..len])?;
Ok(Self {
elf_inode,
elf_file,
elf_headers,
argv,
envp,
@ -94,7 +94,7 @@ impl ProgramToLoad {
) -> Result<ElfLoadInfo> {
let elf_load_info = load_elf_to_vmar(
vmar,
&self.elf_inode,
self.elf_file,
path_resolver,
self.elf_headers,
self.argv,