Slide 1

Slide 1 text

入門 WebAssembly Binary Format Mitsuru Takigahira : @MysticDoll

Slide 2

Slide 2 text

発表者 • Mitsuru Takigahira @MysticDoll • 低レイヤは初心者です • 社会人2年目になり、住民税の責め苦を受けている • 会社ではRust書いたりSCMの運用する妖精とかやってる

Slide 3

Slide 3 text

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) • 安全でポータブルで低レベルなコードフォーマット 効率良い実行・小さい表現でデザインされているらしい

Slide 4

Slide 4 text

参考にした文献 • https://webassembly.github.io/spec/core/index.html • 発表2日前とかに仕様がW3Cの勧告候補になったらしくキレた • どうなるかわからんけどW3Cの方の仕様の方が見た目が綺麗 https://www.w3.org/TR/wasm-core-1/ • この発表ではBinary Formatがどうなっているかのみ扱います

Slide 5

Slide 5 text

じゃあ実際どうなっとんねん

Slide 6

Slide 6 text

WebAssembly Binary Magic • wasmバイナリの開始4バイトは固定で 0x00 0x61 0x73 0x6d • 次4バイトはwasmバイナリのバージョンを書く • 現在は 0x01 0x00 0x00 0x00 固定

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

Section Format • 各Sectionには対応するIDがある • Sectionは以下のように表現する • ≔ : , ≔ : 32 , ≔ (はSectionに依存)とすると の様に表現する • 書かれていないSectionは空のSectionとみなされる • Custom Sectionを除き、SectionはIDの若い順で記述する (Section間の依存関係の問題で)

Slide 9

Slide 9 text

基本的な数値表現 • 関数に利用可能な数値型はi32, i64, f32, f64の4種

Slide 10

Slide 10 text

整数の表現 • 仕様上は主にビット長Nに対しuN, iNが定義されている • 基本的にはsigned LEB128 • LEB128はDwarfなどで用いられている整数表現 • 数値が小さいほど短い表現で済む • LEB128を知らないと初見でなんで固定長じゃないの?となる • この会場にいる人は概ねそうではなさそう… • このスライドで数値が使われていたら → 実際はLEB128で表現してると思ってください

Slide 11

Slide 11 text

浮動小数点数の表現 • ビット長Nに対し fN が定義されている • 表現はIEEE754-2008 • たぶんこれはECMA262に合わせたんじゃないかと勝手に思っています

Slide 12

Slide 12 text

ベクトルの表現 • 構造体に対しベクトル()の表現は ℎ = ∶ u32とし て … ( ) • 結構読みやすい、素直に最初の数値を読んでその数繰り返し読むだけ • 仕様上vectorと書いてあるけどBによってはvectorじゃないよね

Slide 13

Slide 13 text

名称の表現 • UTF-8で書く • で表現する。 このとき長さはUTF-8で表現したときのバイト数 • otakuだったら 0x6f 0x74 0x61 0x6b 0x75 で5バイトなので 0x05 0x6f 0x74 0x61 0x6b 0x75 となる

Slide 14

Slide 14 text

ここまで • WebAssemblyには11のSectionがある • Section IDの小さい順で書く • 数値はLEB128, IEEE754-2008で表現 • Vectorは長さを先頭に、実物をその後ろに並べる • 名称は で表現

Slide 15

Slide 15 text

関数を定義する

Slide 16

Slide 16 text

関数の表現 • wasm上の関数の表現は以下の2つの部分から構成される 1. 関数のプロトタイプ宣言 (i32, i32) -> i32 的な 2. 実際の関数の命令列 • 関数に用いられる命令は基本1byteで表現される(今のところ) • 静的なオプションが必要な命令は1byte + option という風に表現 • 1がType SectionとFunction Section、2がCode Sectionに対応

Slide 17

Slide 17 text

• i32 := 0x7F • i64 := 0x7E • f32 := 0x7D • f64 := 0x7C • にそれぞれ対応、以下に用いられる • 関数のプロトタイプ定義 • global/local varの定義 • 関数内のブロックが返却する型の宣言

Slide 18

Slide 18 text

• 関数のシグネチャの表現 • 0x60 • 引数の型のvectorと返却する型のvectorを書く • vectorとなっているがまだwasmはタプルなどを返せないので お飾り

Slide 19

Slide 19 text

Type Section • Section ID 1 • Wasm内で利用される関数(importも含む)のシグネチャを書く • = として 1 () • 関数のシグネチャは定義した順にインデックスが振られる

Slide 20

Slide 20 text

Function Section • 定義する関数がどのシグネチャなのかを宣言するSection • この時点では関数本体の定義は行わない • = として 3 () • Code Sectionで書く関数本体それぞれのシグネチャと このvectorの要素が上から順に対応する

Slide 21

Slide 21 text

Code Section • 関数そのものの定義を書く • = として10 () • ≔ : 32 : • が関数の実体

Slide 22

Slide 22 text

• 関数本体 • 終端を00とした命令列を • 個数と型()の組をとして • f ≔ • ()は32 32 64 64とかなら2 2 07 2 07

Slide 23

Slide 23 text

実際のwasmを書く

Slide 24

Slide 24 text

Type Sectionまで

Slide 25

Slide 25 text

Type Sectionまで

Slide 26

Slide 26 text

Function Sectionまで

Slide 27

Slide 27 text

Code Sectionまで

Slide 28

Slide 28 text

wasmで関数の定義、できた

Slide 29

Slide 29 text

Export Section • お察しの通りExport SectionがないとJS側にwasm関数をexport できない • wasmでexportできるのはfunc memory table globalsの4つ • globalsはimmutableでないとexportできない

Slide 30

Slide 30 text

Export Section • Export Sectionは以下のように記述する • 7 • ≔ • : = 000 001 002 003 • インデックスが0,1の関数をa,bとしてexportする場合 • 7 2 001 061 000 000 001 062 000 001

Slide 31

Slide 31 text

じゃあさっきの関数もexportする

Slide 32

Slide 32 text

JSや他のwasmから関数を使いたい • →Import Sectionがあるじゃろ

Slide 33

Slide 33 text

Import Section • 2階層の名前空間で指定したインスタンスをimportできる • Export同様のインスタンスがexportできる • wasm全体の関数Indexはimportされた関数から振られる • memory, table, globalも同様にindexはimportの方が先 • といってもmemoryとtableは現状ユニークでなければならない • JSからimportするときは { hoge: {fuga: some_func } } みたいなオブジェクトを渡す

Slide 34

Slide 34 text

Import Section • 2 • ≔ • はimportする種別と開始1バイトが対応し 続く部分がそれぞれ異なる • ≔ 000 001 002 003

Slide 35

Slide 35 text

Import Section (import functions) • 関数をimportする場合は ≔ 000 • importする関数のシグネチャのインデックスを指定する

Slide 36

Slide 36 text

Import Section(table) • ≔ • つまり ≔ 001 • は現在070(anyfunc) のみ可能 • ≔ ቊ 000 001 min • はtableの最小サイズと最大サイズを定義する • tableの中身は(現在は)関数のみ Element Sectionで関数indexを指定して突っ込む

Slide 37

Slide 37 text

Import Section(memory) • ≔ • ≔ 003 • tableと似ていて、elementの種別を宣言せずlimitsだけ書く • memoryはpage size 64KiB • memoryはmemory.size命令で現在のサイズを得られ memory.grow命令で1ページ分サイズを増やす (返り値は増加前のサイズ)

Slide 38

Slide 38 text

Import Section (globals) • グローバル変数のimport • ≔ • は真偽値で、mutableなら1 • (mut i32) なら 07 1とか

Slide 39

Slide 39 text

じゃあとりあえずimportしてみる • console.logとかimportしてみる

Slide 40

Slide 40 text

した

Slide 41

Slide 41 text

ここまで • 関数のシグネチャ・本体・Exportした • Importもした • もうこれでバイナリエディタで簡単なwasmが書けるはず

Slide 42

Slide 42 text

線型メモリやテーブル • Memory SectionやTable Sectionでmemtype/tabletypeを宣言 • TableはElement Section, Memory は Data Sectionで初期化 • wasmのcompile時にexportした関数やテーブルやメモリなどは 再インポートして別wasmのcompileに利用できる • メモリ • コード中でtN.store/load で読み書き可能 • テーブル • call_indirectでtableから指定したindexの関数を呼び出せる

Slide 43

Slide 43 text

Memory Section/ Table Section • Table Section 4 () • Memory Section 5

Slide 44

Slide 44 text

Element Section • 9 • ≔ • はconstant expressionで以下の命令のみ可 • get_global m • *.const m • で評価された値がオフセットになり その位置に指定したインデックスの関数が追加される

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

Text Formatにするとこんなん

Slide 48

Slide 48 text

いかがでしたか • コンパクトというのは本当っぽい • バイナリフォーマットとしては結構簡単な方に見える • wasmのinstructionについては触れなかったが、 どこまで何ができるのか知る一助になれば嬉しいです