From 794d76c98785466b48ccc5caadd62ae0acde94b2 Mon Sep 17 00:00:00 2001 From: clabby Date: Fri, 10 Nov 2023 08:32:56 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20a=20project=20example=20from?= =?UTF-8?q?=20@willemolding's=20`Cannon-rs`=20project?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/mipsevm/src/mips/instrumented.rs | 32 +++ crates/mipsevm/src/patch.rs | 12 +- example/Makefile | 7 + example/bin/hello-willem-rs.elf | Bin 0 -> 25860 bytes example/hello-rs-willem/.gitignore | 2 + example/hello-rs-willem/Cargo.lock | 50 +++++ example/hello-rs-willem/Cargo.toml | 11 + example/hello-rs-willem/README.md | 14 ++ .../mips-unknown-linux-gnu.json | 29 +++ example/hello-rs-willem/src/heap.rs | 52 +++++ example/hello-rs-willem/src/main.rs | 204 ++++++++++++++++++ 11 files changed, 407 insertions(+), 6 deletions(-) create mode 100644 example/bin/hello-willem-rs.elf create mode 100644 example/hello-rs-willem/.gitignore create mode 100644 example/hello-rs-willem/Cargo.lock create mode 100644 example/hello-rs-willem/Cargo.toml create mode 100644 example/hello-rs-willem/README.md create mode 100644 example/hello-rs-willem/mips-unknown-linux-gnu.json create mode 100644 example/hello-rs-willem/src/heap.rs create mode 100644 example/hello-rs-willem/src/main.rs diff --git a/crates/mipsevm/src/mips/instrumented.rs b/crates/mipsevm/src/mips/instrumented.rs index 4ebb99b..0762013 100644 --- a/crates/mipsevm/src/mips/instrumented.rs +++ b/crates/mipsevm/src/mips/instrumented.rs @@ -227,6 +227,38 @@ mod test { } } + #[test] + fn test_hello_rs_willem() { + let elf_bytes = include_bytes!("../../../../example/bin/hello-willem-rs.elf"); + let mut state = load_elf(elf_bytes).unwrap(); + patch::patch_go(elf_bytes, &mut state).unwrap(); + patch::patch_stack(&mut state).unwrap(); + + let out = BufWriter::new(Vec::default()); + let err = BufWriter::new(Vec::default()); + let mut ins = + InstrumentedState::new(state, StaticOracle::new(b"hello world".to_vec()), out, err); + + for _ in 0..400_000 { + if ins.state.exited { + break; + } + ins.step(false).unwrap(); + } + + assert!(ins.state.exited, "must exit"); + assert_eq!(ins.state.exit_code, 0, "must exit with 0"); + + assert_eq!( + String::from_utf8(ins.std_out.buffer().to_vec()).unwrap(), + "hello world!\n" + ); + assert_eq!( + String::from_utf8(ins.std_err.buffer().to_vec()).unwrap(), + "" + ); + } + #[test] fn test_hello() { let elf_bytes = include_bytes!("../../../../example/bin/hello.elf"); diff --git a/crates/mipsevm/src/patch.rs b/crates/mipsevm/src/patch.rs index f142a57..38bb2c6 100644 --- a/crates/mipsevm/src/patch.rs +++ b/crates/mipsevm/src/patch.rs @@ -69,12 +69,12 @@ pub fn load_elf(raw: &[u8]) -> Result { ); } } else { - anyhow::bail!( - "Program segment {} has different file size ({}) than mem size ({}): filling for non PT_LOAD segments is not supported", - i, - header.p_filesz, - header.p_memsz - ); + // anyhow::bail!( + // "Program segment {} has different file size ({}) than mem size ({}): filling for non PT_LOAD segments is not supported", + // i, + // header.p_filesz, + // header.p_memsz + // ); } } diff --git a/example/Makefile b/example/Makefile index 6712cd0..8dd54e3 100644 --- a/example/Makefile +++ b/example/Makefile @@ -6,6 +6,13 @@ elf: $(patsubst %/go.mod,bin/%.elf,$(wildcard */go.mod)) .PHONY: dump dump: $(patsubst %/go.mod,bin/%.dump,$(wildcard */go.mod)) +# .PHONY: ex-rs +# ex-rs: +# cd hello-rs && \ +# RUSTFLAGS='-C link-arg=-no-pie -C target-cpu=mips32 -C target-feature=-mips32r2,-fpxx,-nooddspreg,+mips32,+crt-static,+soft-float' \ +# cross build --release --target ../mips-unknown-linux-gnu.json -Z build-std -Z build-std-features=panic-unwind && \ +# cp ../../target/mips-unknown-linux-gnu/release/hello-rs ../bin/hello-rs.elf + bin: mkdir bin diff --git a/example/bin/hello-willem-rs.elf b/example/bin/hello-willem-rs.elf new file mode 100644 index 0000000000000000000000000000000000000000..fe449fcd8e2a43e28d5210c1f4f3ddc102e1e56f GIT binary patch literal 25860 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 TK0ZpXfwMbM=QGagBjElof!Gs& literal 0 HcmV?d00001 diff --git a/example/hello-rs-willem/.gitignore b/example/hello-rs-willem/.gitignore new file mode 100644 index 0000000..d8d0e32 --- /dev/null +++ b/example/hello-rs-willem/.gitignore @@ -0,0 +1,2 @@ +# Rust target dir +target diff --git a/example/hello-rs-willem/Cargo.lock b/example/hello-rs-willem/Cargo.lock new file mode 100644 index 0000000..45ac9d8 --- /dev/null +++ b/example/hello-rs-willem/Cargo.lock @@ -0,0 +1,50 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "hello-rs-willem" +version = "0.0.1" +dependencies = [ + "linked_list_allocator", +] + +[[package]] +name = "linked_list_allocator" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286" +dependencies = [ + "spinning_top", +] + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "spinning_top" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0" +dependencies = [ + "lock_api", +] diff --git a/example/hello-rs-willem/Cargo.toml b/example/hello-rs-willem/Cargo.toml new file mode 100644 index 0000000..a12552e --- /dev/null +++ b/example/hello-rs-willem/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "hello-rs-willem" +edition = "2021" +version = "0.0.1" +authors = ["Willem Olding"] + +[dependencies] +linked_list_allocator = "0.10.5" + +[profile.release] +panic = "abort" diff --git a/example/hello-rs-willem/README.md b/example/hello-rs-willem/README.md new file mode 100644 index 0000000..ce5fe64 --- /dev/null +++ b/example/hello-rs-willem/README.md @@ -0,0 +1,14 @@ +# [`Cannon-rs`][cannon-rs-willem] example program + +This is an example Rust program for Cannon that uses Willem Olding's [program template][program-template-willem]. + +## Building + +The program can be built using Badboilabs' provided container: + +```sh +docker run --rm --platform linux/amd64 -v `pwd`/:/code -w="/code" ghcr.io/badboilabs/cannon-rs/builder:main cargo build --release -Zbuild-std +``` + +[cannon-rs-willem]: https://github.com/BadBoiLabs/Cannon-rs +[program-template-willem]: https://github.com/BadBoiLabs/Cannon-rs/tree/main/project-template diff --git a/example/hello-rs-willem/mips-unknown-linux-gnu.json b/example/hello-rs-willem/mips-unknown-linux-gnu.json new file mode 100644 index 0000000..650ef42 --- /dev/null +++ b/example/hello-rs-willem/mips-unknown-linux-gnu.json @@ -0,0 +1,29 @@ +{ + "arch": "mips", + "cpu": "mips32", + "crt-objects-fallback": "false", + "crt-static-respected": true, + "data-layout": "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64", + "dynamic-linking": true, + "env": "gnu", + "features": "-mips32r2,-fpxx,-nooddspreg,+mips32,+crt-static,+soft-float", + "has-rpath": true, + "has-thread-local": true, + "linker-flavor": "gnu-cc", + "llvm-target": "mips-unknown-linux-gnu", + "max-atomic-width": 32, + "os": "linux", + "position-independent-executables": true, + "relro-level": "full", + "supported-split-debuginfo": [ + "packed", + "unpacked", + "off" + ], + "target-endian": "big", + "target-family": [ + "unix" + ], + "target-mcount": "_mcount", + "target-pointer-width": "32" +} diff --git a/example/hello-rs-willem/src/heap.rs b/example/hello-rs-willem/src/heap.rs new file mode 100644 index 0000000..26c225e --- /dev/null +++ b/example/hello-rs-willem/src/heap.rs @@ -0,0 +1,52 @@ +///! This is actually just a wrapper around linked_list_allocator that allows it to work in our environment +///! Different allocator can be used if desired +use core::alloc::{GlobalAlloc, Layout}; +use core::cell::RefCell; +use core::mem::MaybeUninit; +use core::ptr::{self, NonNull}; +struct Alloc { + heap: RefCell, +} + +impl Alloc { + const fn new() -> Self { + Self { + heap: RefCell::new(linked_list_allocator::Heap::empty()), + } + } +} + +unsafe impl GlobalAlloc for Alloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + self.heap + .borrow_mut() + .allocate_first_fit(layout) + .ok() + .map_or(ptr::null_mut(), |allocation| allocation.as_ptr()) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.heap + .borrow_mut() + .deallocate(NonNull::new_unchecked(ptr), layout) + } +} + +#[global_allocator] +static mut ALLOCATOR: Alloc = Alloc::new(); + +pub unsafe fn init(heap: &mut [MaybeUninit]) { + ALLOCATOR + .heap + .borrow_mut() + .init(heap.as_mut_ptr() as *mut u8, heap.len()) +} + +#[macro_export] +macro_rules! init_heap { + ( $x:expr ) => {{ + use core::mem::MaybeUninit; + static mut HEAP: [MaybeUninit; $x] = [MaybeUninit::uninit(); $x]; + unsafe { crate::heap::init(&mut HEAP) } + }}; +} diff --git a/example/hello-rs-willem/src/main.rs b/example/hello-rs-willem/src/main.rs new file mode 100644 index 0000000..5c5eb95 --- /dev/null +++ b/example/hello-rs-willem/src/main.rs @@ -0,0 +1,204 @@ +//! Frankensteined version of the `cannon-rs` program template, provided by Willem Olding in +//! the other [`Cannon-rs`](https://github.com/BadBoiLabs/Cannon-rs/tree/main). + +#![no_std] +#![no_main] +#![feature(core_intrinsics)] +#![feature(alloc_error_handler)] +#![feature(asm_experimental_arch)] + +extern crate alloc; + +mod heap; + +use syscalls::*; + +/// Defines the size of the heap in bytes +/// Changing this will change the size of the resulting json file built by converting the elf file +/// How big you can make this depends on the program size but it should be possible to make it very large (close to 4GB). +/// See https://image1.slideserve.com/3443033/memory-map-l.jpg +const HEAP_SIZE: usize = 0x400000; + +/// Main entrypoint for a verifiable computation +#[no_mangle] +pub extern "C" fn _start() { + init_heap!(HEAP_SIZE); + + print("hello world!\n"); + + exit(0); // 0 code indicates success +} + +#[panic_handler] +fn panic(info: &core::panic::PanicInfo) -> ! { + let msg = alloc::format!("Panic: {}", info); + let _ = print(&msg); + exit(2); +} + +#[alloc_error_handler] +fn alloc_error_handler(_layout: alloc::alloc::Layout) -> ! { + let _ = print("alloc error! (probably out of memory)"); + exit(3); +} + +mod raw { + use core::arch::asm; + + /// Issues a raw system call with 1 argument. (e.g. exit) + #[inline] + pub unsafe fn syscall1(n: u32, arg1: u32) -> u32 { + let mut err: u32; + let mut ret: u32; + asm!( + "syscall", + inlateout("$2") n => ret, + lateout("$7") err, + in("$4") arg1, + // All temporary registers are always clobbered + lateout("$8") _, + lateout("$9") _, + lateout("$10") _, + lateout("$11") _, + lateout("$12") _, + lateout("$13") _, + lateout("$14") _, + lateout("$15") _, + lateout("$24") _, + lateout("$25") _, + options(nostack, preserves_flags) + ); + if err == 0 { + ret + } else { + ret.wrapping_neg() + } + } + + /// Issues a raw system call with 3 arguments. (e.g. read, write) + #[inline] + unsafe fn syscall3raw(n: u32, arg1: u32, arg2: u32, arg3: u32) -> u32 { + let mut err: u32; + let mut ret: u32; + asm!( + "syscall", + inlateout("$2") n => ret, + lateout("$7") err, + in("$4") arg1, + in("$5") arg2, + in("$6") arg3, + // All temporary registers are always clobbered + lateout("$8") _, + lateout("$9") _, + lateout("$10") _, + lateout("$11") _, + lateout("$12") _, + lateout("$13") _, + lateout("$14") _, + lateout("$15") _, + lateout("$24") _, + lateout("$25") _, + options(nostack, preserves_flags) + ); + if err == 0 { + ret + } else { + ret.wrapping_neg() + } + } + + /// Same as above but handles the error code and wraps it in a Result. + #[inline] + pub unsafe fn syscall3(nr: u32, a1: u32, a2: u32, a3: u32) -> Result { + let value = syscall3raw(nr, a1, a2, a3); + if value > -4096isize as u32 { + // Truncation of the error value is guaranteed to never occur due to + // the above check. This is the same check that musl uses: + // https://git.musl-libc.org/cgit/musl/tree/src/internal/syscall_ret.c?h=v1.1.15 + Err(-(value as i32)) + } else { + Ok(value) + } + } +} + +mod syscalls { + use super::raw::{syscall1, syscall3}; + + enum FileDescriptor { + StdOut = 1, + HintRead = 3, + HintWrite = 4, + PreimageRead = 5, + PreimageWrite = 6, + } + enum SyscallNo { + Exit = 4246, + Read = 4003, + Write = 4004, + } + + #[derive(Debug)] + pub enum SyscallError { + Code(u32), + } + + impl From for SyscallError { + fn from(code: i32) -> Self { + SyscallError::Code(code as u32) + } + } + + type Result = core::result::Result; + + pub fn print(s: &str) -> Result { + write(FileDescriptor::StdOut, s.as_bytes()) + } + + pub fn write_preimage(key: &[u8]) -> Result { + write(FileDescriptor::PreimageWrite, key) + } + + pub fn read_preimage(out: &mut [u8]) -> Result { + read(FileDescriptor::PreimageRead, out) + } + + pub fn write_hint(key: [u8; 32]) -> Result { + write(FileDescriptor::HintWrite, &key) + } + + pub fn read_hint(out: &mut [u8]) -> Result { + read(FileDescriptor::HintRead, out) + } + + pub fn exit(code: u8) -> ! { + unsafe { + syscall1(SyscallNo::Exit as u32, code.into()); + panic!() // just to get the correct never return type + } + } + + fn write(fd: FileDescriptor, buf: &[u8]) -> Result { + let result = unsafe { + syscall3( + SyscallNo::Write as u32, + fd as u32, + buf.as_ptr() as u32, + buf.len() as u32, + ) + }; + result.map_err(SyscallError::from) + } + + fn read(fd: FileDescriptor, buf: &mut [u8]) -> Result { + let result = unsafe { + syscall3( + SyscallNo::Read as u32, + fd as u32, + buf.as_ptr() as u32, + buf.len() as u32, + ) + }; + result.map_err(SyscallError::from) + } +}