Skip to content

Instantly share code, notes, and snippets.

@devsnek
Created February 11, 2023 23:08
Show Gist options
  • Save devsnek/ce17a9fa0e0f51bc7305dce6f4e92cbc to your computer and use it in GitHub Desktop.
Save devsnek/ce17a9fa0e0f51bc7305dce6f4e92cbc to your computer and use it in GitHub Desktop.
use std::io::Write;
fn make_code(ptr: *mut u8) -> usize {
use cranelift::prelude::*;
let mut flag_builder = settings::builder();
flag_builder.set("is_pic", "true").unwrap();
flag_builder.set("opt_level", "speed_and_size").unwrap();
let flags = settings::Flags::new(flag_builder);
let isa = cranelift_native::builder().unwrap().finish(flags);
let mut sig = cranelift::codegen::ir::Signature::new(isa.default_call_conv());
sig.params.push(AbiParam::new(types::I32));
sig.params.push(AbiParam::new(types::I32));
let mut ctx = cranelift::codegen::Context::new();
let mut fn_builder_ctx = FunctionBuilderContext::new();
ctx.func = cranelift::codegen::ir::Function::with_name_signature(
ExternalName::testcase("_test"),
sig,
);
let mut f = FunctionBuilder::new(&mut ctx.func, &mut fn_builder_ctx);
{
let block = f.create_block();
f.append_block_params_for_function_params(block);
f.switch_to_block(block);
let v0 = f.block_params(block)[0];
let v1 = f.block_params(block)[1];
let v2 = f.ins().iadd(v0, v1);
let addr = f.ins().iconst(types::I64, 0x42);
f.ins().store(MemFlags::trusted(), v2, addr, 0);
f.ins().trap(TrapCode::UnreachableCodeReached);
}
f.seal_all_blocks();
f.finalize();
cranelift::codegen::verifier::verify_function(&ctx.func, isa.flags()).unwrap();
let code_info = ctx.compile(&*isa).unwrap();
unsafe {
ctx.emit_to_memory(
ptr,
&mut cranelift::codegen::binemit::NullRelocSink {},
&mut cranelift::codegen::binemit::NullTrapSink {},
&mut cranelift::codegen::binemit::NullStackMapSink {},
);
}
code_info.total_size as usize
}
fn main() {
let kvm = kvm_ioctls::Kvm::new().unwrap();
let vm = kvm.create_vm().unwrap();
let mem_size = 0x4000;
let guest_addr = 0x1000;
let load_addr: *mut u8 = unsafe {
libc::mmap(
std::ptr::null_mut(),
mem_size,
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_ANONYMOUS | libc::MAP_SHARED | libc::MAP_NORESERVE,
-1,
0,
) as *mut u8
};
let mem_region = kvm_bindings::kvm_userspace_memory_region {
slot: 0,
guest_phys_addr: guest_addr,
memory_size: mem_size as u64,
userspace_addr: load_addr as u64,
flags: 0,
};
unsafe { vm.set_user_memory_region(mem_region).unwrap() };
make_code(load_addr);
let vcpu_fd = vm.create_vcpu(0).unwrap();
let mut vcpu_sregs = vcpu_fd.get_sregs().unwrap();
vcpu_sregs.cs.base = 0;
vcpu_sregs.cs.selector = 0;
vcpu_fd.set_sregs(&vcpu_sregs).unwrap();
let mut vcpu_regs = vcpu_fd.get_regs().unwrap();
vcpu_regs.rip = guest_addr;
vcpu_regs.rax = 2;
vcpu_regs.rbx = 3;
vcpu_regs.rflags = 2;
vcpu_fd.set_regs(&vcpu_regs).unwrap();
loop {
use kvm_ioctls::VcpuExit;
match vcpu_fd.run().expect("run failed") {
VcpuExit::IoOut(addr, data) => {
match addr {
0x80 => {
break;
}
0x3f8 => {
std::io::stdout().write(data).unwrap();
}
_ => panic!("{}", addr),
}
}
e @ VcpuExit::InternalError => panic!("{:?}", e),
r => println!("Unexpected exit reason: {:?}", r),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment