LLDBをEmscriptenでビルドしたい
これはマジで辛い(でかいので)
ClangとかLLVM自体は他に例があった気がするけど、LLDBを直接的にブラウザで提供している例は見当たらなかった。
Host tripleが自動検出できない
CMake Warning at cmake/modules/GetHostTriple.cmake:46 (message):
unable to determine host target triple
Call Stack (most recent call first):
cmake/config-ix.cmake:413 (get_host_triple)
CMakeLists.txt:733 (include)
これは -DCMAKE_CROSSCOMPILING=1 -DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten
で良いね。
CMakeのconfigure中にハングする
-- Looking for os_signpost_interval_begin - not found
-- Found Python3: C:/Python39/python3.exe (found suitable version "3.9.1", minimum required is "3.6") found components: Interpreter
Change Dir: F:/wasmlldb/wasm/CMakeFiles/CMakeTmp
Run Build Command(s):C:/Python39/Scripts/ninja.exe cmTC_47276 && [1/2] Building CXX object CMakeFiles/cmTC_47276.dir/getErrc.cpp.o
em++: warning: linker setting ignored during compilation: 'PROXY_POSIX_SOCKETS' [-Wunused-command-line-argument]
em++: warning: linker setting ignored during compilation: 'PROXY_TO_PTHREAD' [-Wunused-command-line-argument]
em++: warning: argument unused during compilation: '-lwebsocket.js' [-Wunused-command-line-argument]
[2/2] Linking CXX executable cmTC_47276.js
-- Failed to get errc messages
うーん。。多分 GetErrcMessages.cmake
のものだけど、そもそもクロスコンパイルだと try_run
自体できないからどうしようも無い気が。。
とりあえず node
をkillして先に進ませる。 emcmake
コマンドが
CMAKE_CROSSCOMPILING_EMULATOR:UNINITIALIZED=F:/emscripten/emsdk/node/14.18.2_64bit/bin/node.exe;--experimental-wasm-threads
のように CMAKE_CROSSCOMPILING_EMULATOR
を設定してしまうので実行自体を避けられない。
LLDB_TABLEGEN_EXE
を指定しないと Native 版をビルドしようとする
無意味だから止めてくれ〜
-DLLDB_TABLEGEN_EXE=f:\wasmlldb\native\bin\lldb-tblgen.exe
のような感じで、同じコンフィギュレーションで事前にビルドしておいたネイティブ版のビルドディレクトリ bin/
以下のファイルを指定すれば良い。
メモリ不足になり怪奇現象が多発する
LLVMをNinjaでビルドするときは LLVM_PARALLEL_LINK_JOBS
でリンクの並列度を調整できる。
-DLLVM_PARALLEL_LINK_JOBS=1
あと、 wasm-emscripten-finalize
もバカみてぇにメモリを喰うので一旦 -g0
をコンパイラオプションに指定してみる。
grep
が必要
何故かビルドに [1/75] Creating export file for liblldb
FAILED: tools/lldb/source/API/liblldb.exports
cmd.exe /C "cd /D F:\wasmlldb\wasm\tools\lldb\source\API && echo "LLVM_15 {" > liblldb.exports && ( grep -q [[:alnum:]] F:/wasmlldb/llvm-project/lldb/source/API/liblldb.exports && echo " global:" >> liblldb.exports || : ) && sed -e s/$/;/ -e "s/^/ /" < F:/wasmlldb/llvm-project/lldb/source/API/liblldb.exports >> liblldb.exports && echo " local: *;" >> liblldb.exports && echo }; >> liblldb.exports"
'grep' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
':' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
そもそもWebAssemblyはELFではないのでシンボルversioningを使うのは誤り。 cmake/modules/HandleLLVMOptions.cmake
で 変数 LLVM_HAVE_LINK_VERSION_SCRIPT
を 0
に設定する。
... これはそもそもLLVMはEmscriptenに移植されていない可能性が濃厚な気がするな。。
in6addr_loopback
in6addr_any
が無い
BSD socketエミュレーションライブラリ内に FAILED: bin/lldb.js
cmd.exe /C "cd . && F:\emscripten\emsdk\upstream\emscripten\em++.bat -pthread -lwebsocket.js -sPROXY_POSIX_SOCKETS -sUSE_PTHREADS -sPROXY_TO_PTHREAD -fvisibility-inlines-hidden -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -fdiagnostics-color -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-deprecated-register -Wno-vla-extension -g -Wl,--color-diagnostics @CMakeFiles\lldb.rsp -o bin\lldb.js && cd ."
wasm-ld: error: initial memory too small, 21247728 bytes needed
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_loopback
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_loopback
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_any
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_any
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_any
wasm-ld: error: lib/liblldbHost.a(SocketAddress.cpp.o): undefined symbol: in6addr_loopback
em++: error: 'F:/emscripten/emsdk/upstream/bin\wasm-ld.exe @C:\Users\oku\AppData\Local\Temp\emscripten_b4kc8iei.rsp.utf-8' failed (returned 1)
ninja: build stopped: cannot make progress due to previous errors.
うーん。。普通に libcのソースコードには有る んだけど。。
まぁ SocketAddress.cpp
に同等の内容を追記すれば十分なはず。
extern "C" {
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
};
RAM 32GiBではビルド不能だった
ちょっとダイエットを考えないとイカンな。。
cmake -GNinja "-DLLVM_TARGETS_TO_BUILD=WebAssembly;X86;ARM;AVR" \
-DLLVM_ENABLE_PROJECTS="clang;lldb" \
-DCMAKE_C_FLAGS="-pthread -lwebsocket.js
-sPROXY_POSIX_SOCKETS -sUSE_PTHREADS -sPROXY_TO_PTHREAD -g0" \
-DCMAKE_CXX_FLAGS="-pthread -lwebsocket.js -sPROXY_POSIX_SOCKETS -sUSE_PTHREADS -sPROXY_TO_PTHREAD -g0" \
-DLLVM_TABLEGEN=f:\wasmlldb\native\bin\llvm-tblgen.exe \
-DCLANG_TABLEGEN=f:\wasmlldb\native\bin\clang-tblgen.exe \
-DLLDB_ENABLE_PYTHON=0 -DCMAKE_CROSSCOMPILING=1 \
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten -DBUILD_SHARED_LIBS=OFF \
-DCMAKE_EXE_LINKER_FLAGS="-sTOTAL_MEMORY=33554432" ..\llvm-project\llvm
wasm-objdump
でセクションヘッダの内容を確認してみると、そもそも -g0
が効いてないっぽいな。。
oku@stripe /cygdrive/f/wasmlldb/wasm/tools/lldb/tools/lldb-vscode/CMakeFiles/lldb-vscode.dir
$ wasm-objdump -h VSCode.cpp.o
VSCode.cpp.o: file format wasm 0x1
Sections:
Type start=0x0000000e end=0x000000d9 (size=0x000000cb) count: 31
Import start=0x000000df end=0x000015a4 (size=0x000014c5) count: 119
Function start=0x000015aa end=0x000019e0 (size=0x00000436) count: 1076
Elem start=0x000019e6 end=0x00001a07 (size=0x00000021) count: 1
DataCount start=0x00001a0d end=0x00001a0e (size=0x00000001) count: 114
Code start=0x00001a14 end=0x00026fbe (size=0x000255aa) count: 1076
Data start=0x00026fc4 end=0x00027f22 (size=0x00000f5e) count: 114
Custom start=0x00027f28 end=0x00028072 (size=0x0000014a) ".debug_loc"
Custom start=0x00028078 end=0x00028d13 (size=0x00000c9b) ".debug_abbrev"
Custom start=0x00028d19 end=0x000553cc (size=0x0002c6b3) ".debug_info"
Custom start=0x000553d2 end=0x000575d0 (size=0x000021fe) ".debug_ranges"
Custom start=0x000575d6 end=0x000b119d (size=0x00059bc7) ".debug_str"
Custom start=0x000b11a3 end=0x000be0fb (size=0x0000cf58) ".debug_line"
Custom start=0x000be101 end=0x000f5112 (size=0x00037011) "linking"
Custom start=0x000f5118 end=0x000fbfb6 (size=0x00006e9e) "reloc.CODE"
Custom start=0x000fbfbc end=0x000fc014 (size=0x00000058) "reloc.DATA"
Custom start=0x000fc01a end=0x000fc069 (size=0x0000004f) "reloc..debug_loc"
Custom start=0x000fc06f end=0x0011664b (size=0x0001a5dc) "reloc..debug_info"
Custom start=0x00116651 end=0x00119b93 (size=0x00003542) "reloc..debug_ranges"
Custom start=0x00119b99 end=0x0011b7ca (size=0x00001c31) "reloc..debug_line"
Custom start=0x0011b7d0 end=0x0011b860 (size=0x00000090) "producers"
Custom start=0x0011b866 end=0x0011b8a8 (size=0x00000042) "target_features"
-g0
はリンカのコマンドラインに必要だった
-g0
はリンク時に指定しないとDWARFの後処理(これがメモリを超喰う)を省略できないようだ。。というわけで指定したらリンクまで進むようになった。
未実装が大量にあるが ptrace
とか wait
はネイティブデバッグでしか用が無いので実装する必要は無さそう。というわけで、
warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
これで勝負
emcmake cmake -GNinja "-DLLVM_TARGETS_TO_BUILD=WebAssembly;X86;ARM;AVR" ^
-DLLVM_ENABLE_PROJECTS="clang;lldb" -DCMAKE_C_FLAGS="-pthread -sUSE_PTHREADS" ^
-DCMAKE_CXX_FLAGS="-pthread -sUSE_PTHREADS" ^
-DLLVM_TABLEGEN=f:\wasmlldb\native\bin\llvm-tblgen.exe ^
-DCLANG_TABLEGEN=f:\wasmlldb\native\bin\clang-tblgen.exe ^
-DLLDB_ENABLE_PYTHON=0 -DCMAKE_CROSSCOMPILING=1 ^
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten -DBUILD_SHARED_LIBS=OFF ^
-DLLDB_TABLEGEN_EXE=f:\wasmlldb\native\bin\lldb-tblgen.exe ^
-DLLVM_PARALLEL_LINK_JOBS=1 ^
-DCMAKE_EXE_LINKER_FLAGS="-g0 -sTOTAL_MEMORY=33554432 -sPROXY_TO_PTHREAD -sPROXY_POSIX_SOCKETS -s ERROR_ON_UNDEFINED_SYMBOLS=0 -lwebsocket.js" ^
..\llvm-project\llvm
リンクできた
F:\wasmlldb\wasm>ninja -k0 bin/lldb.js
[2/2] Linking CXX executable bin\lldb.js
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux10InitializeEPFvRNS_8FileSpecEE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux12GetOSVersionEv (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux16GetOSBuildStringEv (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux18GetProgramFileSpecEv (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux26ComputeSupportExeDirectoryERNS_8FileSpecE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux27ComputeUserPluginsDirectoryERNS_8FileSpecE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux29ComputeSystemPluginsDirectoryERNS_8FileSpecE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux30ComputeHostArchitectureSupportERNS_8ArchSpecES2_ (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private13HostInfoLinux9TerminateEv (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private4Host14GetEnvironmentEv (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private4Host14GetProcessInfoEyRNS_19ProcessInstanceInfoE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private4Host17FindProcessesImplERKNS_24ProcessInstanceInfoMatchERNSt3__26vectorINS_19ProcessInstanceInfoENS4_9allocatorIS6_EEEE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: _ZN12lldb_private4Host20ShellExpandArgumentsERNS_17ProcessLaunchInfoE (referenced by top-level compiled C/C++ code)
warning: undefined symbol: ptrace (referenced by top-level compiled C/C++ code)
warning: undefined symbol: wait4 (referenced by top-level compiled C/C++ code)
やったぜ
でも実行できない
F:\wasmlldb\wasm\bin>F:/emscripten/emsdk/node/14.18.2_64bit/bin/node.exe --experimental-wasm-threads lldb.js
failed to asynchronously prepare wasm: CompileError: WebAssembly.instantiate(): Compiling function #278211 failed: local count too large @+69912775
Aborted(CompileError: WebAssembly.instantiate(): Compiling function #278211 failed: local count too large @+69912775)
F:\wasmlldb\wasm\bin\lldb.js:165
throw ex;
^
RuntimeError: Aborted(CompileError: WebAssembly.instantiate(): Compiling function #278211 failed: local count too large @+69912775)
at abort (F:\wasmlldb\wasm\bin\lldb.js:1583:11)
at F:\wasmlldb\wasm\bin\lldb.js:1749:7
だめじゃん。
constexpr size_t kV8MaxWasmFunctionLocals = 50000;
意外と少ねぇな。。DebugビルドをやめてReleaseにして、かつ、assertを抜いて改善するかだろうか。。
動いた
結局、 Release にしてwasm側を最適化させ、DWARFを捨てることでなんとか動作させることは可能そう。 ...そしてどうやって使うかどうかが難しいとこだな。。
emcmake cmake -GNinja "-DLLVM_TARGETS_TO_BUILD=WebAssembly;X86;ARM;AVR" ^
-DLLVM_ENABLE_PROJECTS="clang;lldb" ^
-DCMAKE_C_FLAGS="-Os -pthread -sUSE_PTHREADS" ^
-DCMAKE_CXX_FLAGS="-Os -pthread -sUSE_PTHREADS" ^
-DLLVM_TABLEGEN=f:\wasmlldb\native\bin\llvm-tblgen.exe ^
-DCLANG_TABLEGEN=f:\wasmlldb\native\bin\clang-tblgen.exe ^
-DLLDB_ENABLE_PYTHON=0 -DCMAKE_CROSSCOMPILING=1 ^
-DLLVM_HOST_TRIPLE=wasm32-unknown-emscripten -DBUILD_SHARED_LIBS=OFF ^
-DLLDB_TABLEGEN_EXE=f:\wasmlldb\native\bin\lldb-tblgen.exe ^
-DLLVM_PARALLEL_LINK_JOBS=1 ^
-DCMAKE_EXE_LINKER_FLAGS="-g0 -sTOTAL_MEMORY=33554432 -sPROXY_TO_PTHREAD -sPROXY_POSIX_SOCKETS -s ERROR_ON_UNDEFINED_SYMBOLS=0 -lwebsocket.js" ^
-DCMAKE_BUILD_TYPE=Release ..\llvm-project\llvm
リビルドしたら動かなくなった
F:\wasmlldb\wasm\bin>F:/emscripten/emsdk/node/14.18.2_64bit/bin/node.exe --experimental-wasm-threads lldb.js --help
missing function: sigaltstack
Aborted(-1)
worker.js onmessage() captured an uncaught exception: RuntimeError: Aborted(-1). Build with -s ASSERTIONS=1 for more info.
sigaltstack
なんてあるわけないだろ。。
-DHAVE_PPOLL=0 -DHAVE_SIGALTSTACK=0
かな。。
ビルドを通せることは判った
とりあえずLLDB自体の使い方をマスターしていく必要があるな。。
configure中にハングするのは -sEXIT_RUNTIME=1
で解消した。というかデフォルトではそもそも exit
が無いんだよな。。