min_platform_host/
main.rs1use anyhow::Result;
2
3#[cfg(not(target_os = "linux"))]
4fn main() -> Result<()> {
5 eprintln!("This example only runs on Linux right now");
6 Ok(())
7}
8
9#[cfg(target_os = "linux")]
10fn main() -> Result<()> {
11 use anyhow::{Context, anyhow, bail};
12 use libloading::os::unix::{Library, RTLD_GLOBAL, RTLD_NOW, Symbol};
13 use object::{Object, ObjectSymbol};
14 use wasmtime::{Config, Engine};
15
16 let mut args = std::env::args();
17 let _current_exe = args.next();
18 let triple = args
19 .next()
20 .ok_or_else(|| anyhow!("missing argument 1: triple"))?;
21 let embedding_so_path = args
22 .next()
23 .ok_or_else(|| anyhow!("missing argument 2: path to libembedding.so"))?;
24 let platform_so_path = args
25 .next()
26 .ok_or_else(|| anyhow!("missing argument 3: path to libwasmtime-platform.so"))?;
27
28 let binary = std::fs::read(&embedding_so_path)?;
34 let object = object::File::parse(&binary[..])?;
35
36 for sym in object.symbols() {
46 if !sym.is_undefined() || sym.is_weak() {
47 continue;
48 }
49
50 match sym.name()? {
51 "memmove" | "memset" | "memcmp" | "memcpy" | "bcmp" | "__tls_get_addr" => {}
52 s if s.starts_with("wasmtime_") => {}
53 other => {
54 panic!("unexpected dependency on symbol `{other}`")
55 }
56 }
57 }
58
59 let mut config = Config::new();
66 config.target(&triple)?;
67
68 if !cfg!(feature = "custom") {
72 config.memory_init_cow(false);
73 config.memory_reservation(0);
74 config.memory_guard_size(0);
75 config.memory_reservation_for_growth(0);
76 config.signals_based_traps(false);
77 }
78
79 if cfg!(target_arch = "x86_64") {
88 unsafe {
89 config.cranelift_flag_enable("has_sse3");
90 config.cranelift_flag_enable("has_ssse3");
91 config.cranelift_flag_enable("has_sse41");
92 config.cranelift_flag_enable("has_sse42");
93 config.cranelift_flag_enable("has_fma");
94 }
95 }
96
97 let engine = Engine::new(&config)?;
98 let smoke = engine.precompile_module(b"(module)")?;
99 let simple_add = engine.precompile_module(
100 br#"
101 (module
102 (func (export "add") (param i32 i32) (result i32)
103 (i32.add (local.get 0) (local.get 1)))
104 )
105 "#,
106 )?;
107 let simple_host_fn = engine.precompile_module(
108 br#"
109 (module
110 (import "host" "multiply" (func $multiply (param i32 i32) (result i32)))
111 (func (export "add_and_mul") (param i32 i32 i32) (result i32)
112 (i32.add (call $multiply (local.get 0) (local.get 1)) (local.get 2)))
113 )
114 "#,
115 )?;
116 let simple_floats = engine.precompile_module(
117 br#"
118 (module
119 (func (export "frob") (param f32 f32) (result f32)
120 (f32.ceil (local.get 0))
121 (f32.floor (local.get 1))
122 f32.add)
123 )
124 "#,
125 )?;
126
127 unsafe {
146 let _platform_symbols = Library::open(Some(&platform_so_path), RTLD_NOW | RTLD_GLOBAL)
147 .with_context(|| {
148 format!(
149 "failed to open {platform_so_path:?}; cwd = {:?}",
150 std::env::current_dir()
151 )
152 })?;
153
154 let lib = Library::new(&embedding_so_path).context("failed to create new library")?;
155 let run: Symbol<
156 extern "C" fn(
157 *mut u8,
158 usize,
159 *const u8,
160 usize,
161 *const u8,
162 usize,
163 *const u8,
164 usize,
165 *const u8,
166 usize,
167 ) -> usize,
168 > = lib
169 .get(b"run")
170 .context("failed to find the `run` symbol in the library")?;
171
172 let mut error_buf = Vec::with_capacity(1024);
173 let len = run(
174 error_buf.as_mut_ptr(),
175 error_buf.capacity(),
176 smoke.as_ptr(),
177 smoke.len(),
178 simple_add.as_ptr(),
179 simple_add.len(),
180 simple_host_fn.as_ptr(),
181 simple_host_fn.len(),
182 simple_floats.as_ptr(),
183 simple_floats.len(),
184 );
185 error_buf.set_len(len);
186
187 if len > 0 {
188 bail!("{}", String::from_utf8_lossy(&error_buf));
189 }
190
191 #[cfg(feature = "wasi")]
192 {
193 let wasi_component_path = args
194 .next()
195 .ok_or_else(|| anyhow!("missing argument 4: path to wasi component"))?;
196 let wasi_component = std::fs::read(&wasi_component_path)?;
197 let wasi_component = engine.precompile_component(&wasi_component)?;
198
199 let run_wasi: Symbol<extern "C" fn(*mut u8, *mut usize, *const u8, usize) -> usize> =
200 lib.get(b"run_wasi")
201 .context("failed to find the `run_wasi` symbol in the library")?;
202
203 const PRINT_CAPACITY: usize = 1024 * 1024;
204 let mut print_buf = Vec::with_capacity(PRINT_CAPACITY);
205 let mut print_len = PRINT_CAPACITY;
206 let status = run_wasi(
207 print_buf.as_mut_ptr(),
208 std::ptr::from_mut(&mut print_len),
209 wasi_component.as_ptr(),
210 wasi_component.len(),
211 );
212 print_buf.set_len(print_len);
213 let print_buf = String::from_utf8_lossy(&print_buf);
214
215 if status > 0 {
216 bail!("{print_buf}");
217 } else {
218 println!("{print_buf}");
219 }
220 }
221 }
222 Ok(())
223}