Skip to content

Compiler error with malformed symbol generated #12551

@earwig

Description

@earwig

I'm tracking down a strange Emscripten error on a large project. Here's a minimal reproducible example:

#include <setjmp.h>

namespace foo {
    class Bar {
      public:
        void func() {}
    };
}

int main() {
    foo::Bar bar = foo::Bar();
    jmp_buf env;
    setjmp(env);
    bar.func();
}

The error (full text collapsed):

$ em++ -Wall main.cpp -o main.js
emscripten:ERROR: emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is:
{
...
  "declares": [
    "getTempRet0",
    "__invoke_void_%"class.foo::Bar"*",
    "emscripten_longjmp",
    "setTempRet0",
    "emscripten_resize_heap",
    "emscripten_memcpy_big"
  ],
...
}

Traceback (most recent call last):
...
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 869, in load_metadata_wasm
    metadata_json = json.loads(metadata_raw)
...
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 22 (char 146)
Full error
$ em++ -Wall main.cpp -o main.js
emscripten:ERROR: emscript: failure to parse metadata output from wasm-emscripten-finalize. raw output is:
{
  "staticBump": 536,
  "tableSize": 2,
  "initializers": [
    "__wasm_call_ctors"
  ],
  "declares": [
    "getTempRet0",
    "__invoke_void_%"class.foo::Bar"*",
    "emscripten_longjmp",
    "setTempRet0",
    "emscripten_resize_heap",
    "emscripten_memcpy_big"
  ],
  "externs": [
  ],
  "exports": [
    "__wasm_call_ctors",
    "malloc",
    "saveSetjmp",
    "testSetjmp",
    "free",
    "main",
    "__errno_location",
    "fflush",
    "stackSave",
    "stackRestore",
    "stackAlloc",
    "realloc",
    "setThrew"
  ],
  "namedGlobals": {
    "__data_end" : "1560"
  },
  "invokeFuncs": [
  ],
  "mainReadsParams": 1,
  "features": [
  ]
}

Traceback (most recent call last):
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/em++.py", line 14, in <module>
    sys.exit(emcc.run(sys.argv))
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emcc.py", line 2182, in run
    emscripten.run(tmp_wasm, final_js, memfile)
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 964, in run
    return temp_files.run_and_clean(lambda: emscript(
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/tools/tempfiles.py", line 105, in run_and_clean
    return func()
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 964, in <lambda>
    return temp_files.run_and_clean(lambda: emscript(
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 387, in emscript
    metadata = finalize_wasm(infile, memfile, DEBUG)
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 566, in finalize_wasm
    return load_metadata_wasm(stdout, DEBUG)
  File "/usr/local/Cellar/emscripten/2.0.7/libexec/emscripten.py", line 869, in load_metadata_wasm
    metadata_json = json.loads(metadata_raw)
  File "/usr/local/Cellar/python@3.8/3.8.6/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/__init__.py", line 357, in loads
    return _default_decoder.decode(s)
  File "/usr/local/Cellar/python@3.8/3.8.6/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/local/Cellar/python@3.8/3.8.6/Frameworks/Python.framework/Versions/3.8/lib/python3.8/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting ',' delimiter: line 9 column 22 (char 146)

A symbol named __invoke_void_%"class.foo::Bar"* is created, which is then dumped into JSON without any escaping.

Indeed, after setting EMCC_DEBUG=1 and inspecting the generated object file, the oddly named symbol is present:

$ llvm-objdump -t /.../emscripten_temp/main_0.o

main_0.o: file format wasm

SYMBOL TABLE:
00000001 g     F CODE .hidden __original_main
00000000         *UND* __stack_pointer
00000000       F *UND* malloc
00000000 l     O DATA .L__const.main.bar
00000000       F *UND* saveSetjmp
00000000       F *UND* getTempRet0
000001ad  w    F CODE .hidden _ZN3foo3Bar4funcEv
00000000       O *UND* __THREW__
00000000       F *UND* __invoke_void_%"class.foo::Bar"*
00000000       O *UND* __threwValue
00000000       F *UND* testSetjmp
00000000       F *UND* emscripten_longjmp
00000000       F *UND* setTempRet0
00000000       F *UND* free
000001cd g     F CODE .hidden main

I'm not sure if the bug is just (1) wasm-emscripten-finalize needs to escape symbols properly, or also (2) the symbol name is wrong. Certainly a symbol name with a double quote in it feels extremely wrong, but I'm not sure if it actually is.

Environment:

  • macOS 10.14.6 (I think this might be macOS-specific)
  • emcc 2.0.7
  • Apple clang 11.0.0
  • emscripten_temp.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions