#![deny(clippy::all)]
#![deny(missing_docs)]
#![feature(asm)]
mod backend;
mod cli;
mod protobuf;
mod workldr;
use backend::{Backend, Command};
use std::convert::TryInto;
use std::fs::File;
use std::os::unix::io::AsRawFd;
use anyhow::Result;
use log::info;
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
#[structopt(
setting = structopt::clap::AppSettings::DeriveDisplayOrder,
)]
struct Options {
#[structopt(flatten)]
log: cli::LogOptions,
#[structopt(flatten)]
cmd: cli::Command,
}
fn main() -> Result<()> {
let opts = Options::from_args();
opts.log.init_logger();
info!("logging initialized!");
info!("CLI opts: {:?}", &opts);
match opts.cmd {
cli::Command::Info(info) => info.display(),
cli::Command::Exec(exec) => {
let backend = exec.backend.pick()?;
let binary = mmarinus::Kind::Private.load::<mmarinus::perms::Read, _>(&exec.binpath)?;
keep_exec(backend, backend.shim(), binary)
}
cli::Command::Run(run) => {
let modfile = File::open(run.module)?;
let open_fd = modfile.as_raw_fd();
assert!(open_fd == 3, "module got unexpected fd {}", open_fd);
let backend = run.backend.pick()?;
let workldr = run.workldr.pick()?;
keep_exec(backend, backend.shim(), workldr.exec())
}
}
}
fn keep_exec(backend: &dyn Backend, shim: impl AsRef<[u8]>, exec: impl AsRef<[u8]>) -> Result<()> {
let keep = backend.keep(shim.as_ref(), exec.as_ref())?;
let mut thread = keep.clone().spawn()?.unwrap();
loop {
match thread.enter()? {
Command::SysCall(block) => unsafe {
block.msg.rep = block.msg.req.syscall();
},
Command::CpuId(block) => unsafe {
let cpuid = core::arch::x86_64::__cpuid_count(
block.msg.req.arg[0].try_into().unwrap(),
block.msg.req.arg[1].try_into().unwrap(),
);
block.msg.req.arg[0] = cpuid.eax.into();
block.msg.req.arg[1] = cpuid.ebx.into();
block.msg.req.arg[2] = cpuid.ecx.into();
block.msg.req.arg[3] = cpuid.edx.into();
},
Command::Continue => (),
}
}
}