pub async fn load_executable(
    job: &zx::Job,
    executable: zx::Vmo,
    loader_service: ClientEnd<fldsvc::LoaderMarker>,
    params: &ProcessParameters,
) -> Result<ProcessContext, Error> {
    let loader_service = loader_service.into_proxy()?;

    job.set_name(&params.name)?;
    let (process, root_vmar) = job.create_child_process(params.name.as_bytes())?;

    let main_elf = load_elf(&executable, &root_vmar).context("Main ELF failed to load")?;
    let interp_elf = if let Some(interp_hdr) =
        main_elf.headers.program_header_with_type(elf_parse::SegmentType::Interp)?
    {
        let mut interp = vec![0; interp_hdr.filesz as usize];
        executable.read(&mut interp, interp_hdr.offset as u64)?;
        let interp = CStr::from_bytes_with_nul(&interp)?.to_str()?;
        let (status, interp_vmo) = loader_service.load_object(interp).await?;
        zx::Status::ok(status)?;
        let interp_vmo = interp_vmo.ok_or_else(|| anyhow!("didn't get a vmo back"))?;
        Some(load_elf(&interp_vmo, &root_vmar).context("Interpreter ELF failed to load")?)
    } else {
        None
    };

    let entry_elf = (&interp_elf).as_ref().unwrap_or(&main_elf);
    let entry = entry_elf.headers.file_header().entry.wrapping_add(entry_elf.bias);

    // TODO(tbodt): implement MAP_GROWSDOWN and then reset this to 1 page. The current value of
    // this is based on adding 0x1000 each time a segfault appears.
    let stack_size: usize = 0x4000;
    let stack_vmo = zx::Vmo::create(stack_size as u64)?;
    stack_vmo.set_name(CStr::from_bytes_with_nul(b"[stack]\0")?)?;
    let stack_base = root_vmar
        .map(0, &stack_vmo, 0, stack_size, zx::VmarFlags::PERM_READ | zx::VmarFlags::PERM_WRITE)
        .context("failed to map stack")?;
    let stack = stack_base + stack_size - 8;

    let exceptions = fasync::Channel::from_channel(process.create_exception_channel()?)?;
    let process = ProcessContext {
        handle: process,
        exceptions,
        mm: MemoryManager::new(root_vmar),
        security: SecurityContext { uid: 3, gid: 3, euid: 3, egid: 3 },
    };

    let auxv = vec![
        (AT_UID, process.security.uid as u64),
        (AT_EUID, process.security.euid as u64),
        (AT_GID, process.security.gid as u64),
        (AT_EGID, process.security.egid as u64),
        (AT_BASE, interp_elf.map_or(0, |interp| interp.base as u64)),
        (AT_PHDR, main_elf.bias.wrapping_add(main_elf.headers.file_header().phoff) as u64),
        (AT_PHNUM, main_elf.headers.file_header().phnum as u64),
        (AT_SECURE, 0),
    ];
    let stack = populate_initial_stack(&stack_vmo, &params, auxv, stack_base, stack)?;

    let main_thread = process.handle.create_thread("initial-thread".as_bytes())?;
    process.handle.start(&main_thread, entry, stack, zx::Handle::invalid(), 0)?;

    Ok(process)
}
// When it's time to implement execve, this should be changed to return an errno.
When it's time to implement execve, this should be changed to return an errno.
When it ' s time to implement execve this should be changed to return an errno .
pub async fn load_executable(
    job: &zx::Job,
    executable: zx::Vmo,
    loader_service: ClientEnd<fldsvc::LoaderMarker>,
    params: &ProcessParameters,
) -> Result<ProcessContext, Error> {
    let loader_service = loader_service.into_proxy()?;
    job.set_name(&params.name)?;
    let (process, root_vmar) = job.create_child_process(params.name.as_bytes())?;
    let main_elf = load_elf(&executable, &root_vmar).context("Main ELF failed to load")?;
    let interp_elf = if let Some(interp_hdr) =
        main_elf.headers.program_header_with_type(elf_parse::SegmentType::Interp)?
    {
        let mut interp = vec![0; interp_hdr.filesz as usize];
        executable.read(&mut interp, interp_hdr.offset as u64)?;
        let interp = CStr::from_bytes_with_nul(&interp)?.to_str()?;
        let (status, interp_vmo) = loader_service.load_object(interp).await?;
        zx::Status::ok(status)?;
        let interp_vmo = interp_vmo.ok_or_else(|| anyhow!("didn't get a vmo back"))?;
        Some(load_elf(&interp_vmo, &root_vmar).context("Interpreter ELF failed to load")?)
    } else {
        None
    };
    let entry_elf = (&interp_elf).as_ref().unwrap_or(&main_elf);
    let entry = entry_elf.headers.file_header().entry.wrapping_add(entry_elf.bias);
    // TODO(tbodt): implement MAP_GROWSDOWN and then reset this to 1 page. The current value of
    // this is based on adding 0x1000 each time a segfault appears.
    let stack_size: usize = 0x4000;
    let stack_vmo = zx::Vmo::create(stack_size as u64)?;
    stack_vmo.set_name(CStr::from_bytes_with_nul(b"[stack]\0")?)?;
    let stack_base = root_vmar
        .map(0, &stack_vmo, 0, stack_size, zx::VmarFlags::PERM_READ | zx::VmarFlags::PERM_WRITE)
        .context("failed to map stack")?;
    let stack = stack_base + stack_size - 8;
    let exceptions = fasync::Channel::from_channel(process.create_exception_channel()?)?;
    let process = ProcessContext {
        handle: process,
        exceptions,
        mm: MemoryManager::new(root_vmar),
        security: SecurityContext { uid: 3, gid: 3, euid: 3, egid: 3 },
    };
    let auxv = vec![
        (AT_UID, process.security.uid as u64),
        (AT_EUID, process.security.euid as u64),
        (AT_GID, process.security.gid as u64),
        (AT_EGID, process.security.egid as u64),
        (AT_BASE, interp_elf.map_or(0, |interp| interp.base as u64)),
        (AT_PHDR, main_elf.bias.wrapping_add(main_elf.headers.file_header().phoff) as u64),
        (AT_PHNUM, main_elf.headers.file_header().phnum as u64),
        (AT_SECURE, 0),
    ];
    let stack = populate_initial_stack(&stack_vmo, &params, auxv, stack_base, stack)?;
    let main_thread = process.handle.create_thread("initial-thread".as_bytes())?;
    process.handle.start(&main_thread, entry, stack, zx::Handle::invalid(), 0)?;
    Ok(process)
}
pub async fn load_executable ( job : & zx :: Job , executable : zx :: Vmo , loader_service : ClientEnd < fldsvc :: LoaderMarker > , params : & ProcessParameters , ) -> Result < ProcessContext , Error > { let loader_service = loader_service . into_proxy ( ) ? ; job . set_name ( & params . name ) ? ; let ( process , root_vmar ) = job . create_child_process ( params . name . as_bytes ( ) ) ? ; let main_elf = load_elf ( & executable , & root_vmar ) . context ( " " ) ? ; let interp_elf = if let Some ( interp_hdr ) = main_elf . headers . program_header_with_type ( elf_parse :: SegmentType :: Interp ) ? { let mut interp = vec ! [ 0 interp_hdr filesz as usize ] ; executable . read ( & mut interp , interp_hdr . offset as u64 ) ? ; let interp = CStr :: from_bytes_with_nul ( & interp ) ? . to_str ( ) ? ; let ( status , interp_vmo ) = loader_service . load_object ( interp ) . await ? ; zx :: Status :: ok ( status ) ? ; let interp_vmo = interp_vmo . ok_or_else ( | | anyhow ! ( " " ) ) ? ; Some ( load_elf ( & interp_vmo , & root_vmar ) . context ( " " ) ? ) } else { None } ; let entry_elf = ( & interp_elf ) . as_ref ( ) . unwrap_or ( & main_elf ) ; let entry = entry_elf . headers . file_header ( ) . entry . wrapping_add ( entry_elf . bias ) ; // TODO(tbodt): implement MAP_GROWSDOWN and then reset this to 1 page. The current value of // this is based on adding 0x1000 each time a segfault appears. let stack_size : usize = 0x4000 ; let stack_vmo = zx :: Vmo :: create ( stack_size as u64 ) ? ; stack_vmo . set_name ( CStr :: from_bytes_with_nul ( b" \0 " ) ? ) ? ; let stack_base = root_vmar . map ( 0 , & stack_vmo , 0 , stack_size , zx :: VmarFlags :: PERM_READ | zx :: VmarFlags :: PERM_WRITE ) . context ( " " ) ? ; let stack = stack_base + stack_size - 8 ; let exceptions = fasync :: Channel :: from_channel ( process . create_exception_channel ( ) ? ) ? ; let process = ProcessContext { handle : process , exceptions , mm : MemoryManager :: new ( root_vmar ) , security : SecurityContext { uid : 3 , gid : 3 , euid : 3 , egid : 3 } , } ; let auxv = vec ! [ ( AT_UID process security uid as u64 ) ( AT_EUID process security euid as u64 ) ( AT_GID process security gid as u64 ) ( AT_EGID process security egid as u64 ) ( AT_BASE interp_elf map_or ( 0 interp interp base as u64 ) ) ( AT_PHDR main_elf bias wrapping_add ( main_elf headers file_header ( ) phoff ) as u64 ) ( AT_PHNUM main_elf headers file_header ( ) phnum as u64 ) ( AT_SECURE 0 ) ] ; let stack = populate_initial_stack ( & stack_vmo , & params , auxv , stack_base , stack ) ? ; let main_thread = process . handle . create_thread ( " " . as_bytes ( ) ) ? ; process . handle . start ( & main_thread , entry , stack , zx :: Handle :: invalid ( ) , 0 ) ? ; Ok ( process ) }
When it's time to implement execve, this should be changed to return an errno.
When it ' s time to implement execve this should be changed to return an errno .
job
&zx::Job
executable
zx::Vmo
loader_service
ClientEnd<fldsvc::LoaderMarker>
params
&ProcessParameters
job
&zx::Job
executable
zx::Vmo
loader_service
ClientEnd<fldsvc::LoaderMarker>
params
&ProcessParameters