Open12

LLDBをEmscriptenでビルドしたい

okuokuokuoku

これはマジで辛い(でかいので)

ClangとかLLVM自体は他に例があった気がするけど、LLDBを直接的にブラウザで提供している例は見当たらなかった。

okuokuokuoku

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 で良いね。

okuokuokuoku

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 を設定してしまうので実行自体を避けられない。

okuokuokuoku

LLDB_TABLEGEN_EXE を指定しないと Native 版をビルドしようとする

無意味だから止めてくれ〜

-DLLDB_TABLEGEN_EXE=f:\wasmlldb\native\bin\lldb-tblgen.exe

のような感じで、同じコンフィギュレーションで事前にビルドしておいたネイティブ版のビルドディレクトリ bin/ 以下のファイルを指定すれば良い。

okuokuokuoku

メモリ不足になり怪奇現象が多発する

LLVMをNinjaでビルドするときは LLVM_PARALLEL_LINK_JOBS でリンクの並列度を調整できる。

-DLLVM_PARALLEL_LINK_JOBS=1 

あと、 wasm-emscripten-finalize もバカみてぇにメモリを喰うので一旦 -g0 をコンパイラオプションに指定してみる。

okuokuokuoku

何故かビルドに 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_SCRIPT0 に設定する。

... これはそもそもLLVMはEmscriptenに移植されていない可能性が濃厚な気がするな。。

okuokuokuoku

BSD socketエミュレーションライブラリ内に in6addr_loopback in6addr_any が無い

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;
};
okuokuokuoku

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"
okuokuokuoku

-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を抜いて改善するかだろうか。。

okuokuokuoku

動いた

https://github.com/okuoku/llvm-project/commit/71b521ea73b7aa2d2ed04549a3d8db7d07f95908

結局、 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
okuokuokuoku

リビルドしたら動かなくなった

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

かな。。

okuokuokuoku

ビルドを通せることは判った

https://twitter.com/okuoku/status/1513867359152635908

とりあえずLLDB自体の使い方をマスターしていく必要があるな。。

configure中にハングするのは -sEXIT_RUNTIME=1 で解消した。というかデフォルトではそもそも exit が無いんだよな。。