@ledsun blog

無味の味は佳境に入らざればすなわち知れず

wasmバイナリを読む

お題

WebAssembly text formatからwasmバイナリをつくる環境を整える - @ledsun blogで、watからwasmが作れるようになりました。 すこし複雑な例をつかってwasmバイナリを生成して読んでみましょう。 WebAssembly テキスト形式の理解 - WebAssembly | MDNにwatのサンプルがあります。 今回は最初のサンプルを使います。

(module (memory 1) (func))

手法

これをwat2wasmでwasmバイナリに変換します。

~/wabt/bin/wat2wasm example_one.wat -o example_one.wasm  

バイナリを読む

出力されたバイナリを見てみます。

►hexdump -C example_one.wasm
00000000  00 61 73 6d 01 00 00 00  01 04 01 60 00 00 03 02  |.asm.......`....|
00000010  01 00 05 03 01 00 01 0a  04 01 02 00 0b           |.............|
0000001d

00 61 73 6d 01 00 00 00がプリアンブルです。 01 04 01以降がセクションです。

ふたつの違和感

ここで違和感があります。 セクションは1バイトのidに続いて4バイトのサイズがあると思っています。 4バイトのサイズというのは04 01 60 00のことです。 これはいくら何でも大きすぎます。

次に(memory 1)コンパイルしたので、memoryセクションのid 05があるはずです*105 03 01 00 01 0a 04 01 02 00 0bのあたりがmemoryセクションのようです。 これも値1を表すには長すぎます。

セクションの並び順

そういえばwat上ではmemoryセクションが前にあったのに、wasmでは後ろにずれています。 これはwasmのセクションはid順に並ぶためのようです。 そう思ってみると、01と05の間に03セクションがあるように思えます。

01(typeセクション) は 01 04 01 60 00 00ではないでしょうか? そう考えるとスッキリします。

  • 01 : id
  • 04 : size
  • 01 60 00 00 : cont

と読むと良さそうです。

サイズは1バイト

sizeは4バイトだと思ってましたが、1バイトでした。 *2

そうやって見るとこのバイナリには次のセクションが含まれていることがわかります。

  • 01 04 01 60 00 00 : type
  • 03 02 01 00 : function
  • 05 03 01 00 01 : memory
  • 0a 04 01 02 00 0b : code

なにやら、それっぽいです。 wasmバイナリが読めるようになった気がしてきました。

*1:セクションのIDの意味はModules — WebAssembly 2.0 (Draft 2023-09-06)のテーブルを見るとわかります。

*2:wasmバイナリのカスタムセクションを書いてみる - @ledsun blog でsizeを4ではダメで、7にするとよい理由がわかりました。