emscripten-core/emscripten

Upstream: Safari - WebAssembly.instantiate throws Error: WebAssembly.Module doesn't parse at byte: invalid opcode, in function at index

Closed this issue · 13 comments

Found, what I would call a bug, when compiling using fastcomp vs upstream.

upstream:

Chrome and Firefox are fine. Safari 12 on desktop and mobile won't instantiate the wasm module throwing:

Error: WebAssembly.Module doesn't parse at byte 330: invalid opcode 252, in function at index 167

That's all, no other information from Safari.

It's working with fastcomp and with upstream in Firefox and Chrome.

So how would I go about fixing this?

Looks like this is a bulk memory operation.

AFAIK those shouldn't get emitted unless you've enabled them, explicitly or implicitly (maybe with something like pthreads, which also wouldn't be supported on Safari yet).

Threading is explicitly disabled for the emscripten export. What other C++ memory operations would cause that? I mean, It's instantiating fine in Chrome and Firefox, and using fastcomp it also works in Safari, so it can't be too wrong.

The easiest way to debug is probably to run your binary thought wabt-objdump or wasm-dis and take a look at the failing opcode and see which function it is in.

As @Brion said pthreads will automatically enable bulk memory, and AFAIK that's the only thing that should. Is there a chance some object file was compiled with threading? (As @sbc100 said, inspecting the binary may be the fastest way to find out if there isn't a quicker way.)

I can confirm the same behavior in one of my wasm builds. Works in Chrome/Firefox, but not in Safari. Works in all Browsers with the old fastcomp backend.

I get this error in Safari:
Unhandled Promise Rejection: Error: abort(Error: WebAssembly.Module doesn't parse at byte 2251: references are not enabled, in function at index 53). Build with -s ASSERTIONS=1 for more info. (evaluating 'new WebAssembly.RuntimeError("abort("+e+"). Build with -s ASSERTIONS=1 for more info.")')

Running wasm-strip on the binary i get 00075ef: error: unexpected opcode: 0xfc 0x6 ... with the fastcomp version it runs through without any problems.

I looks like 0xfc 0x6 is i64.trunc_sat_f64_s: https://github.com/WebAssembly/wabt/blob/b807819d5501ee7ba22a178d3acfb8fa6d6bcde7/src/opcode.def#L240

So the question is, how is this instruction ending in your binary? Can you use wasm-objdump or similar tool to find out which function includes this opcode? I'm pretty sure its off by default in llvm and emscripten doesn't pass -mnontrapping-fptoint to the compiler. Are you passing this flag to your build?

🤦‍♂ ... ooops, i actually do have -mnontrapping-fptoint somewhere in my Makefile
Sorry for the confusion...maybe if @MarcelKlammer has similar opcodes in the binary, then the solution is simple ;)

That's correct. I fell for the trap: "LLVM wasm backend
The LLVM wasm backend avoids traps by adding more code around each possible trap (basically clamping the value if it would trap). This can increase code size and decrease speed, if you don’t need that extra code. The proper solution for this is to use newer wasm instructions that do not trap, by calling emcc or clang with -mnontrapping-fptoint. That code may not run in older VMs, though."

of thinking, that this was a replacement for

-s "BINARYEN_TRAP_MODE='clamp'"

Maybe add a link to a list of browser showing their support for the newer vs the older VW?

If you can find such a link feel free to add it to the docs. My feeling is that they are pretty clear already but happy to accept a PR.

In the mean time I guess we can close this issue?

stale commented

This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 30 days. Feel free to re-open at any time if this issue is still relevant.

@haberbyte could you assist with a similar problem, as I'm new to wasm.

I get this error:

image

Here is my datastore of the wasm and core js files

image

and here is my code that loads the data and initializes both

let coreData = (await db.getFile("core")) as any;
        let wasmData = (await db.getFile("wasm")) as any;
        const coreBlob = new Blob([coreData.data], { type: "text/javascript"});
        const wasmBlob = new Blob([wasmData.data], { type: "application/wasm"});
        const ffmpeg = ffmpegRef.current;
        await ffmpeg.load({
            coreURL: fromBlobToURL(coreBlob),
            wasmURL: fromBlobToURL(wasmBlob),
        });

This works fine on android, and windows. but I get that error (first image) when testing on iOS iPhone 13 v16.3

@DeanVanGreunen perhaps you want to open a new issue? Can you share (in that issue) the full list of link flags you used to build the wasm binary, and the emscripten version? If you can perhaps attach the wasm file itself too.

@sbc100 I used this wasm version of ffmpeg ffmpeg-core 0.12.2 not sure what flags it was built with.