WASMで様々なリソースにアクセス

tomo
tomo in nttlabs
May 30 · 7 min read

こんにちは、NTTの藤田です。

前回の記事で、 WebAssembly(WASM)をウェブブラウザ以外の環境で実行する仕様であるWASIは、ファイルぐらいしかアクセスできず、コンテナ技術を捨てるどころじゃない、と書きましたが、多くの皆さんから「コンテナ技術を今すぐ捨てたい!」という熱い思いが伝わってきた気がしました。WASMが、オペレーティングシステムの様々なリソースにアクセスする方法を調べてみました。

Lucetの概要

lucetc-wasiコマンドがWASI対応のWASMバイナリをネイティブコードにコンパイルし、 lucet-wasiコマンドがネイティブコードを実行します。Linuxの場合、lucetc-wasiコマンドが生成するのはELFのオブジェクトファイルで、lucet-wasiコマンドは、C言語の dlopen APIを使って、オブジェクトファイルをロードし、実行します。

LucetがWASMを実行するまで
$ lucetc-wasi -o hello_world.so hello_world.wasm
$ lucet-wasi hello_world.so
Hello, world!

コンパイラ

テキスト表現のWASM(一部)

文字を表示するだけなのに、多くのWASI関数が使われている、などと細かいことが気になる方は、_start関数を探しましょう。ランタイムが最初に実行する_start関数は、WASI関数を使って、環境変数、ファイルディスクリプター、コマンドライン引数を取得し、main関数を呼び出します。

MozillaとFastlyが開発しているCraneliftが、WASMからネイティブコードを生成します。生成されたオブジェクトファイルを解析するためには、バイナリをそのまま解読できるという特殊な人以外は、readelfコマンドがお勧めです。出力で、一番右が関数などのシンボル名ですが、その左にUNDと表記されているのが、このオブジェクトファイル以外で定義されているシンボルですので、WASI関数やlucetの独自関数が、実行時にリンクされることがわかります。

オブジェクトファイルの動的シンボル

lucetc-wasiコマンドは、ネイティブコードの他に、ランタイムが必要とする情報もオブジェクトファイルに埋め込みます。

ランタイム

1つのプロセスが複数のWASMインスタンスを実行

インスタンスが呼び出すWASI関数やlucet独自の関数は、lucet-wasiコマンドに含まれています。lucet-wasiコマンドは、C言語のdlopen APIを使って、指定されたオブジェクトファイルをロードし、リンクを完了させます。次に、WASMインスタンスが使うスタックやヒープなどのコンテキストが割り当てられ、CPUレジスタを入れ替えることでインスタンスのコンテキストに切り替えて、オブジェクトファイルに含まれる_start関数が実行されます。

独自のWASI関数を追加してみる

独自関数を参照するWASMファイル

2行目は、外部のfd_hoge関数を$__wasi_fd_hogeという名前で使うこと、その関数の型を宣言しています。

3行目からは、_start関数を定義しており、fd_hoge関数の4つの引数をスタックに積み、__wasi_fd_hoge関数を呼び出します。最初の3つの引数は、C言語のwritev関数に類似で、ファイルディスクリプタ、__wasi_ciovecのアドレス、iovecの数となり、4つ目が返り値を保存するアドレスとなります。

11行目は、ciovecの中身の文字列のアドレスとその長さ、実際の文字列をメモリに保存します。

下記のjsonファイルを引数に渡し、コンパイラを呼び出します。

コンパイラに渡すバインディング情報

30行目で、fd_hoge関数を__wasi_fd_hogeというシンボルで参照することをコンパイラに指示しています。

$ lucetc --bindings bindings.json hello.wat -o hello.so

readelfコマンドで、生成されたオブジェクトファイルが__wasi_fd_hoge関数を参照していることを確認できました。

オブジェクトファイルの動的シンボル

デバッグメッセージを表示する以外は__wasi_fd_write関数と同じ中身の__wasi_fd_hoge関数をランタイムに追加するパッチを当て、lucet-wasiコマンドをコンパイルしたら、試してみましょう。

$ lucet-wasi hello.so
wasi_fd_hoge function is called!
Hello, world!

おわりに

nttlabs

NTT Open Source

tomo

Written by

tomo

Janitor at the 34th floor of NTT Tamachi office, had worked on Linux kernel, founded GoBGP, TGT, Ryu, etc.

nttlabs

nttlabs

NTT Open Source