Open5
WasmLinux: initcallへの対応
WebAssemblyのリンカはリンカスクリプトに対応していないので、通常のELFなLinuxがやっているような、特定のセクションに関数ポインタを集めておいて配列に変換する というテクニックは使えない。
先駆者
先駆者はマップファイルから関数名を取り出してハードコードにしている。
これでも動くが、できれば2passでビルドするのは避けたい。。(マップファイルはリンク後にできるものなので、一度はリンクする必要がある)
抽出
定義されたinitcall類は llvm-nm
で抽出できる。
$ llvm-nm --defined-only --format=just-symbols vmlinux.a | grep __initcall__
__initcall__kmod_nommu__257_1855_init_admin_reserve4
__initcall__kmod_page_alloc__419_8863_init_per_zone_wmark_min2
__initcall__kmod_slub__278_6058_slab_sysfs_init6
...
例えば __initcall__kmod_clocksource__186_1439_init_clocksource_sysfs6
のような名称は、 __initcall_id
とか __initcall_stub
マクロで生成されている。
このシンボルの末尾には 1
とか rootfs
といったソート順を表わす文字(列)が入る。
あとは、これらのシンボルへのポインタが詰まった配列を生成してやり、 __initcall0_start
みたいな名前で生成すれば良い。
ただし、 このロジックは配列が単一であり、 _start
シンボルがそれぞれのレベルの始端を指す ことを前提としている。
static const int arr[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9
};
const int* const ptr_0 = &arr[0];
const int* const ptr_5 = &arr[5];
こういう感じで数を数えて出すくらいしか思いつかないな。。とりあえずコレで。。
undefinedが増えた
wasm-ld: error: ../vmlinux.a(kernel/params.o): undefined symbol: __start___modver
wasm-ld: error: ../vmlinux.a(kernel/params.o): undefined symbol: __start___modver
wasm-ld: error: ../vmlinux.a(kernel/params.o): undefined symbol: __stop___modver
wasm-ld: error: ../vmlinux.a(kernel/params.o): undefined symbol: __stop___modver
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_early
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_early
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_header
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_header
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_final
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_final
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_enable
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_enable
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_resume
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_resume
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_resume_early
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_resume_early
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_suspend
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_suspend
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __end_pci_fixups_suspend_late
wasm-ld: error: ../vmlinux.a(drivers/pci/quirks.o): undefined symbol: __start_pci_fixups_suspend_late
wasm-ldってdead code stripしてんの。。!? EDIT: そもそもLinuxは標準でO2だった。
とりあえず表を作成
Wasmの時だけ static
を外すワークアラウンドを追加で入れている。あんまりクールじゃないな。。
ポインタで受けるのは間違いだったので修正
グローバル変数を並べて、それらが連続することを祈る方式に変更。。