借り初めのひみつきち

仮ブログです。

今週の MYOS

wasm-strip

MYOS のアプリケーションは WebAssembly 形式に対応していて、現在は Rust で開発する前提でライブラリの整備を進めています。 しかしどうやら Rust で WebAssembly を生成すると Release ビルドにも関わらずバイナリにデバッグ情報のようなものが付与されているようです。 現在のアプリは数KB程度のサンプルが多いですが、実際の内容の半分以上はデバッグ情報になっていることも多いです。 このデバッグセクションは仕様がよくわからず、自作 wasm ランタイムにとっては完全にゴミ情報なので削除してサイズ節約したいです。

そこで、デバッグ情報を削除できるユーティリティーを作りました。 内容は簡単で、 wasm ファイルを読み込んでセクションを順番にパースして通常のセクションはそのままデータとして残し、 Custom セクションは実行に直接関係ないデータなので削除し、最後に残ったデータだけを結合して出力します。 wasm ファイルの構造は複数のセクションが並んでいる構造で、各セクションの中身は直接パースせずただのバイナリとして扱う場合は結構簡単に加工できます。

なお、 Custom セクションのうち、 name セクションだけはデバッグ情報ほどサイズが大きくなく残した方が有益と判断したので、現在の MYOS の Makefile では name セクションを残すオプションを指定しています。

実際のファイル内容にはおそらくリンクのために冗長な LEB128 エンコードで表現されているデータも含まれているので、その辺をパースして圧縮すればもう少しファイルを小さくできそうですが、想定される作業量の割には削減できるデータ量がそこまでないので見送りになりました。

name セクション対応

前の節で触れたように、 WebAssembly には name というカスタムセクションが存在します。 WebAssembly は全ての関数はインデックスで扱い、 export されていない関数は番号でしか判別できません。 多くの場合は高級言語コンパイルして実行するので、関数名を番号で表示されてもどの関数のことかわかりません。

しかし、 name セクションがある場合は export していなくてもシンボルの名前がわかるようになります。 ということで、実行エラーが発生した時に関数名も表示できるように対応しました。

f:id:neriring16:20210724030921p:plain

実際のバイナリ上の関数名はほとんどの場合マングルされるのでソース上の関数名と比べるとよくわからない呪文が付属したよくわからない長い名前になってしまいますが、番号だけ表示されるよりは若干わかりやすくなった気がします。

その他の細かい改良

そのほかにも WebAssembly の細かい調整をしてパフォーマンスが向上した気がしますが、ベンチに使っている qemu が時々何の前触れもなくいきなり実行速度が2〜3倍になったり戻ったりするので実際の速度がよくわからなくなってしまいました・・・