emscripten-core / emscripten-core/emscripten
DWARF debug info broken with unused exported function on wasm64
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
It seems that when the linker eliminates an unused exported function in wasm64 mode, the DWARF debug info gets messed up, or at least Chrome cannot read it anymore. It may also be that there are other circumstances that trigger this.
I'm not 100% sure who is 'to blame', but I think something goes wrong in the Emscripten linker, although it may also be an LLVM bug. I tried testing with Node.js but they [don't support DWARF](https://github.com/nodejs/node/issues/37984) yet. I also tried with `emsdk/upstream/bin/llvm-objdump`, but it seems to fully mess up line info in all cases, linking random emsdk stdlib `.c` files instead of my `main.cpp`, so I guess I'll create a separate issue (#23717) for that.
# Steps to reproduce
- First create `main.cpp` with the following contents:
```cpp
#include
void myfun() {}
int main() {
#ifndef NO_USE_MYFUN
myfun();
#endif
std::abort();
}
```
- Now compile with debug symbols as wasm64 with `NO_USE_MYFUN`:
```shell
em++ -g main.cpp -o hello.html -sMEMORY64 -DNO_USE_MYFUN
```
Verbose output
```
"/home/swdv/emsdk/upstream/bin/clang++" -target wasm64-unknown-emscripten -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr --sysroot=/home/swdv/emsdk/upstream/emscripten/cache/sysroot -DEMSCRIPTEN -Xclang -iwithsysroot/include/fakesdl -Xclang -iwithsysroot/include/compat -g3 -DNO_USE_MYFUN -v -c main.cpp -o /tmp/emscripten_temp_pe2lfvyf/main_0.o
clang version 21.0.0git (https:/github.com/llvm/llvm-project 6dc41a639334b913e762f65410fcd14a722b137f)
Target: wasm64-unknown-emscripten
Thread model: posix
InstalledDir: /home/swdv/emsdk/upstream/bin
(in-process)
"/home/swdv/emsdk/upstream/bin/clang-21" -cc1 -triple wasm64-unknown-emscripten -emit-obj -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mframe-pointer=none -ffp-contract=on -fno-rounding-math -mconstructor-aliases -target-cpu generic -fvisibility=hidden -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb -fdebug-compilation-dir=/home/swdv/Downloads/plainwasmtest -v -fcoverage-compilation-dir=/home/swdv/Downloads/plainwasmtest -resource-dir /home/swdv/emsdk/upstream/lib/clang/21 -D EMSCRIPTEN -D NO_USE_MYFUN -isysroot /home/swdv/emsdk/upstream/emscripten/cache/sysroot -internal-isystem /home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/wasm64-emscripten/c++/v1 -internal-isystem /home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1 -internal-isystem /home/swdv/emsdk/upstream/lib/clang/21/include -internal-isystem /home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/wasm64-emscripten -internal-isystem /home/swdv/emsdk/upstream/emscripten/cache/sysroot/include -fdeprecated-macro -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fignore-exceptions -fexceptions -fcolor-diagnostics -iwithsysroot/include/fakesdl -iwithsysroot/include/compat -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -o /tmp/emscripten_temp_pe2lfvyf/main_0.o -x c++ main.cpp
clang -cc1 version 21.0.0git based upon LLVM 21.0.0git default target x86_64-unknown-linux-gnu
ignoring nonexistent directory "/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/wasm64-emscripten/c++/v1"
ignoring nonexistent directory "/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/wasm64-emscripten"
#include "..." search starts here:
#include <...> search starts here:
/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/fakesdl
/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/compat
/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include/c++/v1
/home/swdv/emsdk/upstream/lib/clang/21/include
/home/swdv/emsdk/upstream/emscripten/cache/sysroot/include
End of search list.
/home/swdv/emsdk/upstream/bin/clang --version
/home/swdv/emsdk/upstream/bin/wasm-ld -o hello.wasm /tmp/emscripten_temp_pe2lfvyf/main_0.o -L/home/swdv/emsdk/upstream/emscripten/cache/sysroot/lib/wasm64-emscripten -L/home/swdv/emsdk/upstream/emscripten/src/lib -lGL-getprocaddr -lal -lhtml5 -lstubs-debug -lnoexit -lc-debug -ldlmalloc-debug -lcompiler_rt -lc++-noexcept -lc++abi-debug-noexcept -lsockets -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -mwasm64 /tmp/tmp5u5b29eklibemscripten_js_symbols.so --export=emscripten_stack_get_end --export=emscripten_stack_get_free --export=emscripten_stack_get_base --export=emscripten_stack_get_current --export=emscripten_stack_init --export=_emscripten_stack_alloc --export=__wasm_call_ctors --export=_emscripten_stack_restore --export-if-defined=__start_em_asm --export-if-defined=__stop_em_asm --export-if-defined=__start_em_lib_deps --export-if-defined=__stop_em_lib_deps --export-if-defined=__start_em_js --export-if-defined=__stop_em_js --export-if-defined=main --export-if-defined=__main_argc_argv --export-if-defined=fflush --export-table -z stack-size=65536 --no-growable-memory --initial-heap=16777216 --no-entry --stack-first --table-base=1
/home/swdv/emsdk/upstream/bin/llvm-objcopy hello.wasm hello.wasm --remove-section=producers
/home/swdv/emsdk/node/20.18.0_64bit/bin/node /home/swdv/emsdk/upstream/emscripten/src/compiler.mjs /tmp/tmp3fupbzr6.json
/home/swdv/emsdk/node/20.18.0_64bit/bin/node /home/swdv/emsdk/upstream/emscripten/tools/preprocessor.mjs /tmp/emscripten_temp_pe2lfvyf/settings.js shell.html
```
- Now spin up a webserver and open `hello.html` in the Chrome browser with the [DWARF extension](https://chromewebstore.google.com/detail/cc++-devtools-support-dwa/pdcpmagijalfljmkmjngeonclgbbannb) installed.
- Observe console log:
```
> hello.js:636 Aborted(native code called abort())
> hello.js:654 Uncaught RuntimeError: Aborted(native code called abort())
at abort (hello.js:654:11)
at __abort_js (hello.js:930:7)
at abort (abort.c:21)
at hello.wasm.__original_main (hello.wasm:0x1c5)
at hello.wasm.main (hello.wasm:0x1d1)
at hello.js:1003:49
at hello.js:688:12
at callMain (hello.js:1326:15)
at doRun (hello.js:1378:24)
at hello.js:1387:7
> [C/C++ DevTools Support (DWARF)] Loading debug symbols for http://127.0.0.1:5501/hello.wasm...
> [C/C++ DevTools Support (DWARF)] Loaded debug symbols for http://127.0.0.1:5501/hello.wasm, found 25 source file(s)
```
- Navigate to the `main.cpp` source file in the Sources tab
- Try to place a breakpoint on the `std::abort();` line
- Observe how we jump to the `hello.wasm` file and a breakpoint is placed directly in there and not visible in `main.cpp`
- Reload the page
- Observe how the breakpoint is hit but again we are not directed to the `main.cpp` source. Additionally, we see a message at the bottom of the screen: `No debug information for function "$__original_main`.
# Expected behavior
If we instead compile without `-sMEMORY64` or without `-DNO_USE_MYFUN`, we get what we would expect:
- In the stacktrace for the abort we get the right function name and source file: `main (main.cpp:9)` instead of `hello.wasm.__original_main (hello.wasm:0x1c5)`:
```
at abort (hello.js:654:11)
at __abort_js (hello.js:930:7)
at abort (abort.c:21)
at main (main.cpp:9)
at hello.wasm.main (hello.wasm:0x1dc)
at hello.js:1003:49
at hello.js:688:12
at callMain (hello.js:1326:15)
at doRun (hello.js:1378:24)
at hello.js:1387:7
```
- When placing a breakpoint, it gets placed in `main.cpp`
- When hitting the breakpoint, we are directed to `main.cpp`
# Version of emscripten/emsdk
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 4.0.3 (a9651ff57165f5710bb09a5fe52590fd6ddb72df)
clang version 21.0.0git (https:/github.com/llvm/llvm-project 6dc41a639334b913e762f65410fcd14a722b137f)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /home/swdv/emsdk/upstream/bin
```
# Chrome & OS version
- Chrome 135.0.7021.0 (Official Build) canary (64-bit)
- C/C++ DevTools Support (DWARF) extension 0.2.5854.1
- Pop!_OS 22.04 LTS
Contributor guide
Assessment
This issue has not been assessed yet.