Skip to content

Commit

Permalink
use machine state to trigger exit
Browse files Browse the repository at this point in the history
  • Loading branch information
evmar committed Sep 25, 2024
1 parent 724ad40 commit 8c5491b
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 45 deletions.
14 changes: 1 addition & 13 deletions cli/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,11 @@ impl ReadDir for ReadDirFile {

pub struct Env {
gui: Option<GUI>,
exit_code: Option<u32>,
}

impl Env {
pub fn new() -> Self {
Env {
gui: None,
exit_code: None,
}
Env { gui: None }
}

pub fn ensure_gui(&mut self) -> anyhow::Result<&mut GUI> {
Expand All @@ -107,20 +103,12 @@ impl Env {
}
Ok(self.gui.as_mut().unwrap())
}

pub fn exit_code(&self) -> Option<u32> {
self.exit_code
}
}

#[derive(Clone)]
pub struct EnvRef(pub Rc<RefCell<Env>>);

impl win32::Host for EnvRef {
fn exit(&self, code: u32) {
self.0.borrow_mut().exit_code = Some(code);
}

fn ticks(&self) -> u32 {
let mut env = self.0.borrow_mut();
let gui = env.ensure_gui().unwrap();
Expand Down
28 changes: 19 additions & 9 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ fn main() -> anyhow::Result<ExitCode> {
.map_err(|err| anyhow!("loading {}: {}", exe.display(), err))?;
_ = addrs;

let exit_code: u32;

#[cfg(feature = "x86-64")]
{
assert!(args.trace_points.is_none());
Expand All @@ -150,6 +152,7 @@ fn main() -> anyhow::Result<ExitCode> {
machine.emu.shims.set_machine_hack(ptr, addrs.stack_pointer);
machine.jump_to_entry_point(addrs.entry_point);
}
exit_code = 0; // TODO: exit code path never hit
}

#[cfg(feature = "x86-emu")]
Expand Down Expand Up @@ -189,8 +192,11 @@ fn main() -> anyhow::Result<ExitCode> {
x86::CPUState::Error(error) => {
log::error!("{:?}", error);
machine.dump_state(0);
exit_code = 1;
}
x86::CPUState::Exit(code) => {
exit_code = *code;
}
x86::CPUState::Exit(_) => {}
x86::CPUState::Running | x86::CPUState::Blocked(_) | x86::CPUState::SysCall => {
unreachable!()
}
Expand All @@ -215,17 +221,21 @@ fn main() -> anyhow::Result<ExitCode> {
print_trace(&machine);
todo!();
} else {
machine.main(addrs.entry_point);
match machine.main(addrs.entry_point) {
win32::Status::Exit(code) => {
exit_code = *code;
}
win32::Status::Error { message } => {
log::error!("{}", message);
machine.dump_state();
exit_code = 1;
}
_ => unreachable!(),
}
}
}

let exit_code = host
.0
.borrow()
.exit_code()
.map(|c| ExitCode::from(c.try_into().unwrap_or(u8::MAX)))
.unwrap_or(ExitCode::SUCCESS);
Ok(exit_code)
Ok(ExitCode::from(exit_code as u8))
}

fn escape_arg(arg: &str) -> Cow<str> {
Expand Down
9 changes: 0 additions & 9 deletions web/glue/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,6 @@ fn message_from_event(event: web_sys::Event) -> anyhow::Result<win32::Message> {
#[wasm_bindgen(typescript_custom_section)]
const JSHOST_TS: &'static str = r#"
export interface JsHost {
exit(code: number): void;
ensure_timer(when: number): void;
get_event(): Event | undefined;
Expand All @@ -257,9 +255,6 @@ extern "C" {
#[wasm_bindgen(method)]
fn log(this: &JsHost, level: u8, msg: String);

#[wasm_bindgen(method)]
fn exit(this: &JsHost, exit_code: u32);

#[wasm_bindgen(method)]
fn ensure_timer(this: &JsHost, when: u32);

Expand All @@ -279,10 +274,6 @@ extern "C" {
}

impl win32::Host for JsHost {
fn exit(&self, exit_code: u32) {
JsHost::exit(self, exit_code)
}

fn ticks(&self) -> u32 {
web_sys::window().unwrap().performance().unwrap().now() as u32
}
Expand Down
1 change: 1 addition & 0 deletions web/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ export abstract class JsHost implements glue.JsHost, glue.JsLogger {
}
}

// TODO: now unused
exit(code: number) {
this.emuHost.exit(code);
}
Expand Down
1 change: 0 additions & 1 deletion win32/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ pub struct Message {
}

pub trait Host {
fn exit(&self, code: u32);
/// Get an arbitrary time counter, measured in milliseconds.
fn ticks(&self) -> u32;
fn system_time(&self) -> chrono::DateTime<chrono::Local>;
Expand Down
2 changes: 1 addition & 1 deletion win32/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@ mod shims_raw;
mod machine_unicorn;

pub use host::*;
pub use machine::Machine;
pub use machine::{Machine, Status};
8 changes: 6 additions & 2 deletions win32/src/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ pub enum Status {
/// All threads are blocked awaiting results.
Blocked,
/// CPU error.
Error { message: String, signal: u8 },
Error {
message: String,
// TODO:
// signal: u8
},
/// Process exited.
Exit { code: u32 },
Exit(u32),
}
1 change: 0 additions & 1 deletion win32/src/machine_emu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ impl MachineX<Emulator> {
}

pub fn exit(&mut self, exit_code: u32) {
self.host.exit(exit_code);
// Set the CPU state immediately here because otherwise the CPU will
// continue executing instructions after the exit call.
// TODO: this is unsatisfying.
Expand Down
4 changes: 2 additions & 2 deletions win32/src/machine_raw.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
host,
machine::{LoadedAddrs, MachineX},
machine::{LoadedAddrs, MachineX, Status},
pe,
shims::Shims,
shims_raw::retrowin32_syscall,
Expand Down Expand Up @@ -95,6 +95,6 @@ impl MachineX<Emulator> {
}

pub fn exit(&mut self, exit_code: u32) {
self.host.exit(exit_code);
self.status = Status::Exit(exit_code);
}
}
15 changes: 8 additions & 7 deletions win32/src/machine_unicorn.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
host,
machine::{LoadedAddrs, MachineX},
machine::{LoadedAddrs, MachineX, Status},
pe,
shims::{Handler, Shims},
winapi,
Expand Down Expand Up @@ -303,10 +303,11 @@ impl MachineX<Emulator> {

fn run(&mut self, eip: u32) {
let mut eip = eip as u64;
loop {
while matches!(self.status, Status::Running) {
if let Err(err) = self.emu.unicorn.emu_start(eip, MAGIC_ADDR, 0, 0) {
log::error!("machine_unicorn: {:?}", err);
self.dump_state();
self.status = Status::Error {
message: format!("unicorn: {:?}", err),
};
return;
}
eip = self.emu.unicorn.reg_read(RegisterX86::EIP).unwrap();
Expand All @@ -322,11 +323,12 @@ impl MachineX<Emulator> {
}
}

pub fn main(&mut self, entry_point: u32) {
pub fn main(&mut self, entry_point: u32) -> &Status {
self.emu.unicorn.reg_write(RegisterX86::EIP, 0).unwrap();
let retrowin32_main = winapi::kernel32::get_kernel32_builtin(self, "retrowin32_main");
self.setup_call_x86(retrowin32_main, vec![entry_point]);
self.run(retrowin32_main);
&self.status
}

pub fn add_breakpoint(&mut self, addr: u32) -> bool {
Expand Down Expand Up @@ -399,8 +401,7 @@ impl MachineX<Emulator> {
}

pub fn exit(&mut self, exit_code: u32) {
// TODO: interrupt unicorn run() loop.
self.host.exit(exit_code);
self.status = Status::Exit(exit_code);
}
}

Expand Down

0 comments on commit 8c5491b

Please sign in to comment.