WebAssembly / WebAssembly/binaryen

Use wasm customSections, to fix Binaryen WASM to text format round tripping failing for side module

Open
#1,582 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

help wanted
Dominant language
WebAssembly
Stars
8.6k
Forks
885
Avg merge
1d 19h
Merged PRs (30d)
69

Description

I have been investigating building a dynarec for an emulator using dynamic linking.
The hope was that i could manually modify WASM text and compile the side module using binaryen.js on the fly in a service worker.

As a POC i modified a emscripten unit test to:
[Listing1]
main.c

#include <dlfcn.h>
#include <stdio.h>
#include <emscripten.h>
void next(const char *z) {
    void *lib_handle = dlopen("library.wasm", 0);
    typedef void (*voidfunc)();
    voidfunc x = (voidfunc)dlsym(lib_handle, "library_func");
    if (!x) puts("cannot find side function");
    else x();  
}
int main() {
    puts("hello from main");
    emscripten_async_wget("library.wasm", "library.wasm", next, NULL);
    puts("async");
    return 0;
}

and library.c

#include <stdio.h>
void library_func() {
#ifdef USE_PRINTF
    printf("1 hello from library: %p\n", (int)&library_func);
#else
    puts("2 hello from library");
#endif
}

built with:
emcc main.c -s WASM=1 -s EMULATED_FUNCTION_POINTERS=1 -s RELOCATABLE=1 -s MAIN_MODULE=1 -O2 -o exe.html
and
emcc -s WASM=1 library.c -s SIDE_MODULE=1 -O2 -o library.wasm

and i get the expected output:
hello from main
async
2 hello from library

Using binaryen-1.37.38-x86_64-linux.tar.gz I then created a POC by converting library.wasm to text (via command line use of binaryen wasm-dis) and using a service worker:

[Listing2]
service-worker.js

self.importScripts('binaryen.js');
var wast = `
//wast/wat text
`;

self.addEventListener('install', event => {
    self.skipWaiting();
});
self.addEventListener('activate', event => {
    self.skipWaiting();
});
self.addEventListener('fetch', event => {
    let url = event.request.url;
    if (event.request.url.startsWith(self.location.origin)) {
        var index = url.indexOf('library');
        if(index == -1) {              
            return fetch(event.request).then(response => {
                return response;
            });
        } else {
        try {
          var module = Binaryen.parseText(wast);
          var binary = module.emitBinary();
          module.dispose();         
            var headers = {'Content-Type': 'application/wasm'};
            event.respondWith(
                new Response(binary, { headers })
            );
        }catch(e){
            console.log(e);
        }
      }
    }
});

However this did not work. error:

Assertion failed: need the dylink section to be first

It seems the text does not have all the information the binary file did. Taking the text output and building the WASM binary file from that and re-running [Listing1] showed the same error. The WASM binary file sizes are slightly different. Is this expected behaviour?

I should add I repeated the same with WABT: The WebAssembly Binary Toolkit, with the same result. So i guess this is not the right approach?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the round trip for library.wasm with wasm-dis, Binaryen.parseText, and module.emitBinary in service-worker.js. Compare the original and emitted binaries, focusing on the dylink section and the custom sections mentioned in the title. Done means the rebuilt side module loads without the “need the dylink section to be first” assertion.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, wasm
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.