diff --git a/Cargo.lock b/Cargo.lock index 4729b107..370d3590 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -153,6 +153,15 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "bug-247" +version = "0.1.0" +dependencies = [ + "env_logger", + "polkavm", + "polkavm-linker", +] + [[package]] name = "bytemuck" version = "1.14.0" diff --git a/Cargo.toml b/Cargo.toml index a10f8aad..a16de66b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ members = [ "examples/doom", "examples/hello-world", + "examples/bug-247", ] [workspace.package] diff --git a/crates/polkavm-test-data/build.rs b/crates/polkavm-test-data/build.rs index 64e9dcd8..be5b70a2 100644 --- a/crates/polkavm-test-data/build.rs +++ b/crates/polkavm-test-data/build.rs @@ -65,6 +65,8 @@ fn main() -> Result<(), String> { build("test-blob", "no-lto", &target_64)?; build("bench-pinky", "release", &target_32)?; build("bench-pinky", "release", &target_64)?; + build("bug-247", "release", &target_32)?; + build("bug-247", "release", &target_64)?; Ok(()) } diff --git a/crates/polkavm-test-data/src/lib.rs b/crates/polkavm-test-data/src/lib.rs index 69e7316e..58f3ffc3 100644 --- a/crates/polkavm-test-data/src/lib.rs +++ b/crates/polkavm-test-data/src/lib.rs @@ -2,3 +2,5 @@ pub const BENCH_PINKY_32: &[u8] = include_bytes!("../../../guest-programs/target pub const BENCH_PINKY_64: &[u8] = include_bytes!("../../../guest-programs/target/riscv64emac-unknown-none-polkavm/release/bench-pinky"); pub const TEST_BLOB_32: &[u8] = include_bytes!("../../../guest-programs/target/riscv32emac-unknown-none-polkavm/no-lto/test-blob"); pub const TEST_BLOB_64: &[u8] = include_bytes!("../../../guest-programs/target/riscv64emac-unknown-none-polkavm/no-lto/test-blob"); +pub const BUG_247_32: &[u8] = include_bytes!("../../../guest-programs/target/riscv32emac-unknown-none-polkavm/release/bug-247"); +pub const BUG_247_64: &[u8] = include_bytes!("../../../guest-programs/target/riscv64emac-unknown-none-polkavm/release/bug-247"); diff --git a/examples/bug-247/Cargo.toml b/examples/bug-247/Cargo.toml new file mode 100644 index 00000000..5cfe76d1 --- /dev/null +++ b/examples/bug-247/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "bug-247" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +env_logger = { version = "0.10.0", default-features = false } +polkavm = { path = "../../crates/polkavm" } +polkavm-linker = { path = "../../crates/polkavm-linker" } diff --git a/examples/bug-247/src/main.rs b/examples/bug-247/src/main.rs new file mode 100644 index 00000000..e69f74b7 --- /dev/null +++ b/examples/bug-247/src/main.rs @@ -0,0 +1,48 @@ +use std::fs; +use polkavm::{Caller, Config, Engine, Error, InterruptKind, Linker, Module, ProgramBlob, Reg}; + +fn main() { + env_logger::init(); + + // compile + let input_path = std::env::var("INPUT").expect("no INPUT in env"); + + // link + let mut config = polkavm_linker::Config::default(); + config.set_optimize(false); + /* Disable DWARF processing: */ + config.set_strip(true); + + let orig = fs::read(input_path).expect("Failed to read {input_path:?}"); + let linked = polkavm_linker::program_from_elf(config, orig.as_ref()) + .unwrap(); + + let blob = ProgramBlob::parse(linked[..].into()).unwrap(); + + let config = Config::from_env().unwrap(); + let engine = Engine::new(&config).unwrap(); + let module = Module::from_blob(&engine, &Default::default(), blob).unwrap(); + + // High-level API. + let mut linker: Linker = Linker::new(); + + linker.define_typed( + "debug_message", + |caller: Caller<()>, buffer: u32, length: u32| { + let buffer = caller.instance.read_memory(buffer, length).unwrap(); + eprintln!("print: {:?}", String::from_utf8(buffer).unwrap()); + }, + ).unwrap(); + + // Link the host functions with the module. + let instance_pre = linker.instantiate_pre(&module).unwrap(); + + // Instantiate the module. + let mut instance = instance_pre.instantiate().unwrap(); + + // Grab the function and call it. + println!("Calling into the guest program:"); + let _result = instance + .call_typed_and_get_result::<(), ()>(&mut (), "deploy", ()) + .unwrap(); +} diff --git a/guest-programs/Cargo.lock b/guest-programs/Cargo.lock index 826ca1fd..171eee77 100644 --- a/guest-programs/Cargo.lock +++ b/guest-programs/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bench-minimal" version = "0.1.0" @@ -35,6 +41,15 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +[[package]] +name = "bug-247" +version = "0.1.0" +dependencies = [ + "polkavm-derive", + "spin", + "talc", +] + [[package]] name = "emumisc" version = "0.1.0" @@ -59,6 +74,16 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "mos6502" version = "0.1.0" @@ -126,6 +151,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "simplealloc" version = "0.18.0" @@ -136,6 +167,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "359a2aa2309eed307acc397678f7fbb43989db6ee417a11752248fc98451e696" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "syn" version = "1.0.109" @@ -158,6 +198,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "talc" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fcad3be1cfe36eb7d716a04791eba36a197da9d9b6ea1e28e64ac569da3701d" +dependencies = [ + "lock_api", +] + [[package]] name = "test-blob" version = "0.1.0" diff --git a/guest-programs/Cargo.toml b/guest-programs/Cargo.toml index dc2d73ca..40d9ca3e 100644 --- a/guest-programs/Cargo.toml +++ b/guest-programs/Cargo.toml @@ -22,6 +22,9 @@ members = [ # Tests "test-blob", + + # https://github.com/paritytech/polkavm/issues/247 + "bug-247" ] [workspace.lints.rust] diff --git a/guest-programs/bug-247/Cargo.toml b/guest-programs/bug-247/Cargo.toml new file mode 100644 index 00000000..a3357e91 --- /dev/null +++ b/guest-programs/bug-247/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "bug-247" +version = "0.1.0" +edition = "2021" +publish = false + +[[bin]] +name = "bug-247" +path = "src/main.rs" + +[dependencies] +spin = "0.9.8" +talc = "4.4.2" + +[target.'cfg(target_env = "polkavm")'.dependencies] +polkavm-derive = { path = "../../crates/polkavm-derive" } + +[lints] +workspace = true diff --git a/guest-programs/bug-247/src/main.rs b/guest-programs/bug-247/src/main.rs new file mode 100644 index 00000000..619df58f --- /dev/null +++ b/guest-programs/bug-247/src/main.rs @@ -0,0 +1,77 @@ +#![no_std] +#![no_main] + +extern crate core; +extern crate alloc; + +use polkavm_derive::polkavm_export; +use core::fmt::Write; + +#[repr(u32)] +pub enum Foo { + Success = 0, + CalleeTrapped = 1, + Unknown, +} + +impl ::core::fmt::Debug for Foo { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { + ::core::fmt::Formatter::write_str( + f, + match self { + Foo::Success => "Success", + Foo::CalleeTrapped => "CalleeTrapped", + Foo::Unknown => "Unknown", + }, + ) + } +} + +struct Writer; +impl core::fmt::Write for Writer { + fn write_str(&mut self, s: &str) -> core::fmt::Result { + unsafe { + crate::debug_message(s.as_ptr(), s.len() as u32); + } + Ok(()) + } +} + +#[polkavm_derive::polkavm_import] +extern "C" { + pub fn debug_message(str_ptr: *const u8, str_len: u32); +} + +#[polkavm_export(abi = polkavm_derive::default_abi)] +pub fn call() { } + +#[polkavm_export(abi = polkavm_derive::default_abi)] +pub fn deploy() { + // on heap + let foo = alloc::format!("heap: {:?}", Foo::Success); + unsafe { + crate::debug_message(foo.as_ptr(), foo.len() as u32); + } + + // on stack + let mut m = Writer {}; + let _ = write!(&mut m, "stack: {:?}", Foo::Success); +} + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + core::arch::asm!("unimp"); + core::hint::unreachable_unchecked(); + } +} + +use talc::*; +static mut ARENA: [u8; 10000] = [0; 10000]; + +#[global_allocator] +static ALLOCATOR: Talck, ClaimOnOom> = Talc::new(unsafe { + ClaimOnOom::new(Span::from_array(core::ptr::addr_of!(ARENA).cast_mut())) +}).lock(); +