Skip to content

Commit

Permalink
x86-64: Updates for futures rework
Browse files Browse the repository at this point in the history
  • Loading branch information
encounter committed Aug 13, 2024
1 parent 67beabf commit 7265fd6
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 17 deletions.
6 changes: 2 additions & 4 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[cfg(not(feature = "x86-64"))]
mod debugger;
mod host;
mod logging;
Expand All @@ -13,8 +14,6 @@ mod resv32;
use anyhow::anyhow;
use std::borrow::Cow;
use std::process::ExitCode;
use std::task::{Context, Poll};
use win32::shims::BoxFuture;
use win32::winapi::types::win32_error_str;
use win32::Host;

Expand Down Expand Up @@ -125,14 +124,13 @@ fn main() -> anyhow::Result<ExitCode> {
.join(" ");
let mut machine = win32::Machine::new(Box::new(host.clone()), cmdline);

#[allow(unused)]
let addrs = machine
.load_exe(&buf, &exe, None)
.map_err(|err| anyhow!("loading {}: {}", exe.display(), err))?;
_ = addrs;

#[cfg(feature = "x86-64")]
let exit_code = {
assert!(args.trace_points.is_none());
unsafe {
let ptr: *mut win32::Machine = &mut machine;
machine.emu.shims.set_machine_hack(ptr, addrs.stack_pointer);
Expand Down
11 changes: 9 additions & 2 deletions memory/src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ pub struct Mem<'m> {
}

impl<'m> Mem<'m> {
pub fn new(ptr: *mut u8, end: *mut u8) -> Mem<'m> {
Mem {
ptr,
end,
_marker: std::marker::PhantomData,
}
}

pub fn from_slice(s: &'m [u8]) -> Mem<'m> {
let range = s.as_ptr_range();
Mem {
Expand Down Expand Up @@ -236,8 +244,7 @@ impl<'m> Extensions<'m> for Mem<'m> {
}

fn slicez(self, ofs: u32) -> &'m [u8] {
let ofs = ofs as usize;
let slice = &self.as_slice_todo()[ofs..];
let slice = self.slice(ofs..);
let nul = slice.iter().position(|&c| c == 0).unwrap();
&slice[..nul]
}
Expand Down
24 changes: 16 additions & 8 deletions win32/src/machine_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use crate::{
};
use memory::Mem;
use std::collections::HashMap;
use std::path::Path;

#[derive(Default)]
pub struct RawMem {}

impl RawMem {
pub fn mem(&self) -> Mem {
let s = unsafe { std::slice::from_raw_parts(0 as *const u8, 1 << 30) };
Mem::from_slice(s)
Mem::new(std::ptr::null_mut(), (1 << 30) as *mut u8)
}
pub fn len(&self) -> u32 {
0xFFFF_FFFF
Expand Down Expand Up @@ -46,6 +46,7 @@ impl MachineX<Emulator> {
host,
state,
labels: HashMap::new(),
exe_path: Default::default(),
}
}

Expand All @@ -57,10 +58,11 @@ impl MachineX<Emulator> {
pub fn load_exe(
&mut self,
buf: &[u8],
filename: &str,
path: impl AsRef<Path>,
relocate: Option<Option<u32>>,
) -> anyhow::Result<LoadedAddrs> {
let exe = pe::load_exe(self, buf, filename, relocate)?;
let path = path.as_ref();
let exe = pe::load_exe(self, buf, path, relocate)?;

let stack = self.state.kernel32.mappings.alloc(
exe.stack_size,
Expand All @@ -69,6 +71,7 @@ impl MachineX<Emulator> {
);
let stack_pointer = stack.addr + stack.size - 4;

self.exe_path = path.to_path_buf();
Ok(LoadedAddrs {
entry_point: exe.entry_point,
stack_pointer,
Expand All @@ -87,13 +90,18 @@ impl MachineX<Emulator> {
// that calls from/to it can be managed with 32-bit pointers.
// (This arrangement is set up by the linker flags.)
let mem_3gb_range = 0xc000_0000u64..0x1_0000_0000u64;
let fn_addr = &Self::jump_to_entry_point as *const _ as u64;
assert!(mem_3gb_range.contains(&fn_addr));
let fn_addr = Self::jump_to_entry_point as *const fn() as u64;
assert!(mem_3gb_range.contains(&fn_addr), "fn_addr ({fn_addr:x}) not in 3-4gb range");

println!("entry point at {:x}, about to jump", entry_point);
std::io::stdin().read_line(&mut String::new()).unwrap();
log::info!("entry point at {entry_point:x}, about to jump");
// std::io::stdin().read_line(&mut String::new()).unwrap();

let pin = std::pin::pin!(self.call_x86(entry_point, vec![]));
crate::shims::call_sync(pin);
}

pub fn exit(&mut self, code: u32) {
let code = u8::try_from(code).unwrap_or(255);
std::process::exit(code as i32);
}
}
2 changes: 1 addition & 1 deletion win32/src/shims.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub struct Shim {

/// Synchronously evaluate a Future, under the assumption that it is always immediately Ready.
#[allow(deref_nullptr)]
pub fn call_sync<T>(future: std::pin::Pin<&mut impl std::future::Future<Output = T>>) -> T {
pub fn call_sync<T>(future: std::pin::Pin<&mut (impl std::future::Future<Output = T> + ?Sized)>) -> T {
let context: &mut std::task::Context = unsafe { &mut *std::ptr::null_mut() };
match future.poll(context) {
std::task::Poll::Pending => unreachable!(),
Expand Down
12 changes: 10 additions & 2 deletions win32/src/shims_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
//! This module implements Shims for non-emulated cpu case, using raw 32-bit memory.
//! See doc/x86-64.md for an overview.
use crate::shims::Handler;
use crate::{ldt::LDT, shims::Shim, Machine};
use memory::Extensions;
use std::pin::pin;

type Trampoline = [u8; 16];

Expand Down Expand Up @@ -48,7 +50,13 @@ unsafe extern "C" fn call64() -> u32 {
Ok(shim) => shim,
Err(name) => unimplemented!("{}", name),
};
(shim.func)(machine, STACK32 + 8)
match shim.func {
Handler::Sync(handler) => handler(machine, STACK32 + 8),
Handler::Async(handler) => {
let mut future = pin!(handler(machine, STACK32 + 8));
crate::shims::call_sync(future.as_mut())
}
}
}

// trans64 is the code we jump to when transitioning from 32->64-bit.
Expand Down Expand Up @@ -211,7 +219,7 @@ pub async fn call_x86(machine: &mut Machine, func: u32, args: Vec<u32>) -> u32 {
STACK32 = esp;

#[allow(unused_mut)]
let mut ret = 0;
let mut ret;
std::arch::asm!(
// We need to back up all non-scratch registers (rbx/rbp),
// because even callee-saved registers will only be saved as 32-bit,
Expand Down

0 comments on commit 7265fd6

Please sign in to comment.