Open3
WasmLinux: syscallの発行を目指す会
とりあえず空の init
の動作まで進んだので、前のLKL内で直接syscallを発行する手法の再現を目指す。
実用的なLinuxシステムを目指すなら、
- シングルプロセス、NOMMUでカーネルとメモリ空間共有(
mmap
とかは使えない ) - マルチプロセス --
clone
を呼んでpidを分ける - Wasmモジュールを分離
- libc(たぶんMUSL)を移植
- hard-mmuで
mmap
を再現 -- ホストシステム(Win32とかLinux)のmmapを流用 ← ここまでwasm2c専用 - Wasmのバイナリトランスレータを書いてsoft-mmu化、他のWasmランタイムやブラウザで実行
のようなステップだろうか。。
Clang16はまだrelocatableなWasmを出力できない
ダメじゃん。。 手元でツールチェインをビルドする必要がある。(Clang17はまだFedoraのパッケージにも来てないので) いやSnapshotがあった。。
(この手順に加えて、 dnf update
しておく必要がある。)
RelocatableなExecutableの生成
基本的には https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md に従ったバイナリが出力される。
int the_global = 1234;
int
main(int ac, char** av){
the_global = ac;
return (int)&the_global;
}
を、
cc --verbose -nostdlib -Wl,-pie -Wl,--no-entry -fPIC -Wl,--export=main -Wl,--Map=out.map -o out.wasm check.c
のようにコンパイルして wasm2c
すると、
struct w2c_env;
extern u32* w2c_env_0x5F_memory_base(struct w2c_env*);
extern u32* w2c_env_0x5F_stack_pointer(struct w2c_env*);
extern u32* w2c_env_0x5F_table_base(struct w2c_env*);
typedef struct w2c_0x24out0x2Ewasm {
/* import: 'env' '__memory_base' */
u32 *w2c_env_0x5F_memory_base;
/* import: 'env' '__stack_pointer' */
u32 *w2c_env_0x5F_stack_pointer;
/* import: 'env' '__table_base' */
u32 *w2c_env_0x5F_table_base;
wasm_rt_memory_t w2c_memory;
} w2c_0x24out0x2Ewasm;
void wasm2c_0x24out0x2Ewasm_instantiate(w2c_0x24out0x2Ewasm*, struct w2c_env*);
void wasm2c_0x24out0x2Ewasm_free(w2c_0x24out0x2Ewasm*);
wasm_rt_func_type_t wasm2c_0x24out0x2Ewasm_get_func_type(uint32_t param_count, uint32_t result_count, ...);
/* export: 'memory' */
wasm_rt_memory_t* w2c_0x24out0x2Ewasm_memory(w2c_0x24out0x2Ewasm* instance);
/* export: '__wasm_apply_data_relocs' */
void w2c_0x24out0x2Ewasm_0x5F_wasm_apply_data_relocs(w2c_0x24out0x2Ewasm*);
/* export: 'main' */
u32 w2c_0x24out0x2Ewasm_main(w2c_0x24out0x2Ewasm*, u32, u32);
のようなインターフェース入りで出力される。
アプリ側は、 w2c_env_0x5F_memory_base
といったリロケーション情報提供用の関数を用意した上でモジュールをinstanciateすると、使用メモリをオフセットした形でモジュールを使用できるが、 新しくメモリを確保してしまう のでこの辺は今のところwasm2cの出力を使うのではなく自前で実装する必要がある。
必要になるメモリサイズは、 wasm-objdump
で調べられる:
$ wasm-objdump -x -j dylink.0 out.wasm
out.wasm: file format wasm 0x1
module name: <out.wasm>
Section Details:
Custom:
- name: "dylink.0"
- mem_size : 4
- mem_p2align : 2
- table_size : 0
- table_p2align: 0