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 other => {
53 panic!("unexpected dependency on symbol `{other}`")
54 }
55 }
56 }
57
58 let mut config = Config::new();
65 config.target(&triple)?;
66
67 if !cfg!(feature = "custom") {
71 config.memory_init_cow(false);
72 config.memory_reservation(0);
73 config.memory_guard_size(0);
74 config.memory_reservation_for_growth(0);
75 config.signals_based_traps(false);
76 }
77
78 if cfg!(target_arch = "x86_64") {
87 unsafe {
88 config.cranelift_flag_enable("has_sse3");
89 config.cranelift_flag_enable("has_ssse3");
90 config.cranelift_flag_enable("has_sse41");
91 config.cranelift_flag_enable("has_sse42");
92 config.cranelift_flag_enable("has_fma");
93 }
94 }
95
96 let engine = Engine::new(&config)?;
97 let smoke = engine.precompile_module(b"(module)")?;
98 let simple_add = engine.precompile_module(
99 br#"
100 (module
101 (func (export "add") (param i32 i32) (result i32)
102 (i32.add (local.get 0) (local.get 1)))
103 )
104 "#,
105 )?;
106 let simple_host_fn = engine.precompile_module(
107 br#"
108 (module
109 (import "host" "multiply" (func $multiply (param i32 i32) (result i32)))
110 (func (export "add_and_mul") (param i32 i32 i32) (result i32)
111 (i32.add (call $multiply (local.get 0) (local.get 1)) (local.get 2)))
112 )
113 "#,
114 )?;
115 let simple_floats = engine.precompile_module(
116 br#"
117 (module
118 (func (export "frob") (param f32 f32) (result f32)
119 (f32.ceil (local.get 0))
120 (f32.floor (local.get 1))
121 f32.add)
122 )
123 "#,
124 )?;
125
126 unsafe {
145 let _platform_symbols = Library::open(Some(&platform_so_path), RTLD_NOW | RTLD_GLOBAL)
146 .with_context(|| {
147 format!(
148 "failed to open {platform_so_path:?}; cwd = {:?}",
149 std::env::current_dir()
150 )
151 })?;
152
153 let lib = Library::new(&embedding_so_path).context("failed to create new library")?;
154 let run: Symbol<
155 extern "C" fn(
156 *mut u8,
157 usize,
158 *const u8,
159 usize,
160 *const u8,
161 usize,
162 *const u8,
163 usize,
164 *const u8,
165 usize,
166 ) -> usize,
167 > = lib
168 .get(b"run")
169 .context("failed to find the `run` symbol in the library")?;
170
171 let mut error_buf = Vec::with_capacity(1024);
172 let len = run(
173 error_buf.as_mut_ptr(),
174 error_buf.capacity(),
175 smoke.as_ptr(),
176 smoke.len(),
177 simple_add.as_ptr(),
178 simple_add.len(),
179 simple_host_fn.as_ptr(),
180 simple_host_fn.len(),
181 simple_floats.as_ptr(),
182 simple_floats.len(),
183 );
184 error_buf.set_len(len);
185
186 if len > 0 {
187 bail!("{}", String::from_utf8_lossy(&error_buf));
188 }
189
190 #[cfg(feature = "wasi")]
191 {
192 let wasi_component_path = args
193 .next()
194 .ok_or_else(|| format_err!("missing argument 4: path to wasi component"))?;
195 let wasi_component = std::fs::read(&wasi_component_path)?;
196 let wasi_component = engine.precompile_component(&wasi_component)?;
197
198 let run_wasi: Symbol<extern "C" fn(*mut u8, *mut usize, *const u8, usize) -> usize> =
199 lib.get(b"run_wasi")
200 .context("failed to find the `run_wasi` symbol in the library")?;
201
202 const PRINT_CAPACITY: usize = 1024 * 1024;
203 let mut print_buf = Vec::with_capacity(PRINT_CAPACITY);
204 let mut print_len = PRINT_CAPACITY;
205 let status = run_wasi(
206 print_buf.as_mut_ptr(),
207 std::ptr::from_mut(&mut print_len),
208 wasi_component.as_ptr(),
209 wasi_component.len(),
210 );
211 print_buf.set_len(print_len);
212 let print_buf = String::from_utf8_lossy(&print_buf);
213
214 if status > 0 {
215 bail!("{print_buf}");
216 } else {
217 println!("{print_buf}");
218 }
219 }
220 }
221 Ok(())
222}