Upgrade to Pro — share decks privately, control downloads, hide ads and more …

入門WebAssemblyBinaryFormat.pdf

 入門WebAssemblyBinaryFormat.pdf

第15回 カーネル/VM探検隊 @東京

Mitsuru Takigahira

July 20, 2019
Tweet

More Decks by Mitsuru Takigahira

Other Decks in Technology

Transcript

  1. WebAssembly • ブラウザ上で高速に動くアセンブリではないコードフォーマット • WebAssembly (abbreviated Wasm [1]) is a

    safe, portable, low- level code format designed for efficient execution and compact representation. Its main goal is to enable high performance applications on the Web, but it does not make any Web-specific assumptions or provide Web-specific features, so it can be employed in other environments as well. (https://webassembly.github.io/spec/intro/introduction.html) • 安全でポータブルで低レベルなコードフォーマット 効率良い実行・小さい表現でデザインされているらしい
  2. WebAssembly Binary Magic • wasmバイナリの開始4バイトは固定で 0x00 0x61 0x73 0x6d •

    次4バイトはwasmバイナリのバージョンを書く • 現在は 0x01 0x00 0x00 0x00 固定
  3. Sections • WebAssemblyには以下11種のセクションがある • Custom Section • Type Section •

    Import Section • Function Section • Table Section • Memory Section • Global Section • Export Section • Element Section • Code Section • Data Section
  4. Section Format • 各Sectionには対応するIDがある • Sectionは以下のように表現する • ≔ : ,

    ≔ : 32 , ≔ (はSectionに依存)とすると の様に表現する • 書かれていないSectionは空のSectionとみなされる • Custom Sectionを除き、SectionはIDの若い順で記述する (Section間の依存関係の問題で)
  5. 整数の表現 • 仕様上は主にビット長Nに対しuN, iNが定義されている • 基本的にはsigned LEB128 • LEB128はDwarfなどで用いられている整数表現 •

    数値が小さいほど短い表現で済む • LEB128を知らないと初見でなんで固定長じゃないの?となる • この会場にいる人は概ねそうではなさそう… • このスライドで数値が使われていたら → 実際はLEB128で表現してると思ってください
  6. ベクトルの表現 • 構造体に対しベクトル()の表現は ℎ = ∶ u32とし て … (

    ) • 結構読みやすい、素直に最初の数値を読んでその数繰り返し読むだけ • 仕様上vectorと書いてあるけどBによってはvectorじゃないよね
  7. 関数の表現 • wasm上の関数の表現は以下の2つの部分から構成される 1. 関数のプロトタイプ宣言 (i32, i32) -> i32 的な

    2. 実際の関数の命令列 • 関数に用いられる命令は基本1byteで表現される(今のところ) • 静的なオプションが必要な命令は1byte + option という風に表現 • 1がType SectionとFunction Section、2がCode Sectionに対応
  8. • i32 := 0x7F • i64 := 0x7E • f32

    := 0x7D • f64 := 0x7C • にそれぞれ対応、以下に用いられる • 関数のプロトタイプ定義 • global/local varの定義 • 関数内のブロックが返却する型の宣言
  9. Type Section • Section ID 1 • Wasm内で利用される関数(importも含む)のシグネチャを書く • =

    として 1 () • 関数のシグネチャは定義した順にインデックスが振られる
  10. Function Section • 定義する関数がどのシグネチャなのかを宣言するSection • この時点では関数本体の定義は行わない • = として 3

    () • Code Sectionで書く関数本体それぞれのシグネチャと このvectorの要素が上から順に対応する
  11. Export Section • Export Sectionは以下のように記述する • 7 • ≔ •

    : = 000 001 002 003 • インデックスが0,1の関数をa,bとしてexportする場合 • 7 2 001 061 000 000 001 062 000 001
  12. Import Section • 2階層の名前空間で指定したインスタンスをimportできる • Export同様のインスタンスがexportできる • wasm全体の関数Indexはimportされた関数から振られる • memory,

    table, globalも同様にindexはimportの方が先 • といってもmemoryとtableは現状ユニークでなければならない • JSからimportするときは { hoge: {fuga: some_func } } みたいなオブジェクトを渡す
  13. Import Section(table) • ≔ • つまり ≔ 001 • は現在070(anyfunc)

    のみ可能 • ≔ ቊ 000 001 min • はtableの最小サイズと最大サイズを定義する • tableの中身は(現在は)関数のみ Element Sectionで関数indexを指定して突っ込む
  14. Import Section(memory) • ≔ • ≔ 003 • tableと似ていて、elementの種別を宣言せずlimitsだけ書く •

    memoryはpage size 64KiB • memoryはmemory.size命令で現在のサイズを得られ memory.grow命令で1ページ分サイズを増やす (返り値は増加前のサイズ)
  15. 線型メモリやテーブル • Memory SectionやTable Sectionでmemtype/tabletypeを宣言 • TableはElement Section, Memory は

    Data Sectionで初期化 • wasmのcompile時にexportした関数やテーブルやメモリなどは 再インポートして別wasmのcompileに利用できる • メモリ • コード中でtN.store/load で読み書き可能 • テーブル • call_indirectでtableから指定したindexの関数を呼び出せる
  16. Element Section • 9 • ≔ • はconstant expressionで以下の命令のみ可 •

    get_global m • *.const m • で評価された値がオフセットになり その位置に指定したインデックスの関数が追加される
  17. Data Section • Element Sectionと似ている • 11 • ≔ •

    Element Section同様オフセットを指定し、データを格納する • 格納するデータはバイト列となる