min_platform_host/
main.rs1use wasmtime::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 libloading::os::unix::{Library, RTLD_GLOBAL, RTLD_NOW, Symbol};
12 use object::{Object, ObjectSymbol};
13 use wasmtime::{Config, Engine, bail, error::Context as _, format_err};
14
15 let mut args = std::env::args();
16 let _current_exe = args.next();
17 let triple = args
18 .next()
19 .ok_or_else(|| format_err!("missing argument 1: triple"))?;
20 let embedding_so_path = args
21 .next()
22 .ok_or_else(|| format_err!("missing argument 2: path to libembedding.so"))?;
23 let platform_so_path = args
24 .next()
25 .ok_or_else(|| format_err!("missing argument 3: path to libwasmtime-platform.so"))?;
26
27 let binary = std::fs::read(&embedding_so_path)?;
33 let object = object::File::parse(&binary[..])?;
34
35 for sym in object.symbols() {
45 if !sym.is_undefined() || sym.is_weak() {
46 continue;
47 }
48
49 match sym.name()? {
50 "memmove" | "memset" | "memcmp" | "memcpy" | "bcmp" | "__tls_get_addr" => {}
51 s if s.starts_with("wasmtime_") => {}
52 "embedding_publish_executable" | "embedding_unpublish_executable" => {}
55 other => {
56 panic!("unexpected dependency on symbol `{other}`")
57 }
58 }
59 }
60
61 let mut config = Config::new();
68 config.target(&triple)?;
69
70 if !cfg!(feature = "custom") {
74 config.memory_init_cow(false);
75 config.memory_reservation(0);
76 config.memory_guard_size(0);
77 config.memory_reservation_for_growth(0);
78 config.signals_based_traps(false);
79 }
80
81 if cfg!(target_arch = "x86_64") {
90 unsafe {
91 config.cranelift_flag_enable("has_sse3");
92 config.cranelift_flag_enable("has_ssse3");
93 config.cranelift_flag_enable("has_sse41");
94 config.cranelift_flag_enable("has_sse42");
95 config.cranelift_flag_enable("has_fma");
96 }
97 }
98
99 let engine = Engine::new(&config)?;
100 let smoke = engine.precompile_module(b"(module)")?;
101 let simple_add = engine.precompile_module(
102 br#"
103 (module
104 (func (export "add") (param i32 i32) (result i32)
105 (i32.add (local.get 0) (local.get 1)))
106 )
107 "#,
108 )?;
109 let simple_host_fn = engine.precompile_module(
110 br#"
111 (module
112 (import "host" "multiply" (func $multiply (param i32 i32) (result i32)))
113 (func (export "add_and_mul") (param i32 i32 i32) (result i32)
114 (i32.add (call $multiply (local.get 0) (local.get 1)) (local.get 2)))
115 )
116 "#,
117 )?;
118 let simple_floats = engine.precompile_module(
119 br#"
120 (module
121 (func (export "frob") (param f32 f32) (result f32)
122 (f32.ceil (local.get 0))
123 (f32.floor (local.get 1))
124 f32.add)
125 )
126 "#,
127 )?;
128
129 unsafe {
148 let _platform_symbols = Library::open(Some(&platform_so_path), RTLD_NOW | RTLD_GLOBAL)
149 .with_context(|| {
150 format!(
151 "failed to open {platform_so_path:?}; cwd = {:?}",
152 std::env::current_dir()
153 )
154 })?;
155
156 let lib = Library::new(&embedding_so_path).context("failed to create new library")?;
157 let run: Symbol<
158 extern "C" fn(
159 *mut u8,
160 usize,
161 *const u8,
162 usize,
163 *const u8,
164 usize,
165 *const u8,
166 usize,
167 *const u8,
168 usize,
169 ) -> usize,
170 > = lib
171 .get(b"run")
172 .context("failed to find the `run` symbol in the library")?;
173
174 let mut error_buf = Vec::with_capacity(1024);
175 let len = run(
176 error_buf.as_mut_ptr(),
177 error_buf.capacity(),
178 smoke.as_ptr(),
179 smoke.len(),
180 simple_add.as_ptr(),
181 simple_add.len(),
182 simple_host_fn.as_ptr(),
183 simple_host_fn.len(),
184 simple_floats.as_ptr(),
185 simple_floats.len(),
186 );
187 error_buf.set_len(len);
188
189 if len > 0 {
190 bail!("{}", String::from_utf8_lossy(&error_buf));
191 }
192
193 if !cfg!(feature = "custom") {
200 let concurrent = engine.precompile_module(
201 br#"
202 (module
203 (memory 1 1)
204 (func (export "add") (param i32 i32) (result i32)
205 (i32.add (local.get 0) (local.get 1)))
206 (func (export "unreachable")
207 unreachable)
208 (func (export "load") (param i32) (result i32)
209 (i32.load (local.get 0)))
210 )
211 "#,
212 )?;
213
214 let run_concurrent_module_load_test: Symbol<
215 extern "C" fn(*mut u8, usize, *const u8, usize, usize) -> usize,
216 > = lib.get(b"run_concurrent_module_load_test").context(
217 "failed to find the `run_concurrent_module_load_test` symbol in the library",
218 )?;
219
220 const THREADS: usize = 2;
221 const ITERATIONS: usize = 2000;
222 let barrier = std::sync::Barrier::new(THREADS);
223 std::thread::scope(|s| {
224 let threads = (0..THREADS)
225 .map(|_| {
226 s.spawn(|| {
227 barrier.wait();
228 let mut error_buf = Vec::with_capacity(1024);
229 let len = run_concurrent_module_load_test(
230 error_buf.as_mut_ptr(),
231 error_buf.capacity(),
232 concurrent.as_ptr(),
233 concurrent.len(),
234 ITERATIONS,
235 );
236 error_buf.set_len(len);
237 if len > 0 {
238 bail!("{}", String::from_utf8_lossy(&error_buf));
239 }
240 Ok(())
241 })
242 })
243 .collect::<Vec<_>>();
244 threads.into_iter().try_for_each(|t| t.join().unwrap())
245 })?;
246 }
247
248 #[cfg(feature = "wasi")]
249 {
250 let wasi_component_path = args
251 .next()
252 .ok_or_else(|| format_err!("missing argument 4: path to wasi component"))?;
253 let wasi_component = std::fs::read(&wasi_component_path)?;
254 let wasi_component = engine.precompile_component(&wasi_component)?;
255
256 let run_wasi: Symbol<extern "C" fn(*mut u8, *mut usize, *const u8, usize) -> usize> =
257 lib.get(b"run_wasi")
258 .context("failed to find the `run_wasi` symbol in the library")?;
259
260 const PRINT_CAPACITY: usize = 1024 * 1024;
261 let mut print_buf = Vec::with_capacity(PRINT_CAPACITY);
262 let mut print_len = PRINT_CAPACITY;
263 let status = run_wasi(
264 print_buf.as_mut_ptr(),
265 std::ptr::from_mut(&mut print_len),
266 wasi_component.as_ptr(),
267 wasi_component.len(),
268 );
269 print_buf.set_len(print_len);
270 let print_buf = String::from_utf8_lossy(&print_buf);
271
272 if status > 0 {
273 bail!("{print_buf}");
274 } else {
275 println!("{print_buf}");
276 }
277 }
278 }
279 Ok(())
280}