Stop preventing WASI apps including unimplemented syscalls

The recent wasi-libc includes some new syscalls not implemented in
@wasmer-js/wasi and we currently disable `--gc-sections` (see
https://github.com/swiftwasm/swift/issues/5128), so binaries built with
SwiftWasm 5.9 toolchain contains references to those unimplemented
syscalls.
This commit allows running such binaries by inserting dummy functions
for unimplemented syscalls.
This commit is contained in:
Yuta Saito 2024-01-16 12:39:31 +00:00
parent 7fc43f0c21
commit 33eafb077f
1 changed files with 28 additions and 8 deletions

View File

@ -43,9 +43,9 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => {
}, },
}); });
const createWasmImportObject = (extraWasmImports) => { const createWasmImportObject = (extraWasmImports, wasmModule) => {
const importObject = { const importObject = {
wasi_snapshot_preview1: wrapWASI(wasi), wasi_snapshot_preview1: wrapWASI(wasi, wasmModule),
}; };
if (swift) { if (swift) {
@ -72,11 +72,10 @@ export const WasmRunner = (rawOptions, SwiftRuntime) => {
throw new Error("Detected stack buffer overflow."); throw new Error("Detected stack buffer overflow.");
}, },
}; };
const importObject = createWasmImportObject(extraWasmImports); const module = await WebAssembly.compile(wasmBytes);
const module = await WebAssembly.instantiate(wasmBytes, importObject); const importObject = createWasmImportObject(extraWasmImports, module);
console.log(importObject)
// Node support const instance = await WebAssembly.instantiate(module, importObject);
const instance = "instance" in module ? module.instance : module;
if (swift && instance.exports.swjs_library_version) { if (swift && instance.exports.swjs_library_version) {
swift.setInstance(instance); swift.setInstance(instance);
@ -132,7 +131,7 @@ const createWasmFS = (onStdout, onStderr) => {
return wasmFs; return wasmFs;
}; };
const wrapWASI = (wasiObject) => { const wrapWASI = (wasiObject, wasmModule) => {
// PATCH: @wasmer-js/wasi@0.x forgets to call `refreshMemory` in `clock_res_get`, // PATCH: @wasmer-js/wasi@0.x forgets to call `refreshMemory` in `clock_res_get`,
// which writes its result to memory view. Without the refresh the memory view, // which writes its result to memory view. Without the refresh the memory view,
// it accesses a detached array buffer if the memory is grown by malloc. // it accesses a detached array buffer if the memory is grown by malloc.
@ -148,5 +147,26 @@ const wrapWASI = (wasiObject) => {
wasiObject.refreshMemory(); wasiObject.refreshMemory();
return original_clock_res_get(clockId, resolution); return original_clock_res_get(clockId, resolution);
}; };
// @wasmer-js/wasi polyfill does not support all WASI syscalls like `sock_accept`.
// So we need to insert a dummy function for unimplemented syscalls.
const __WASI_ERRNO_NOTSUP = 58;
for (const importEntry of WebAssembly.Module.imports(wasmModule)) {
const { importModule, importName, importKind } = importEntry;
// Skip dummy import entries for non-WASI and already implemented syscalls.
if (
importModule !== "wasi_snapshot_preview1" ||
importKind !== "function" ||
wasiObject.wasiImport[importName]
) {
continue;
}
wasiObject.wasiImport[importName] = () => {
console.warn(`WASI syscall ${importModule}.${importName} is not supported, returning ENOTSUP.`);
return __WASI_ERRNO_NOTSUP;
}
}
return wasiObject.wasiImport; return wasiObject.wasiImport;
}; };