Open6

WasmLinux: LKLのリンクエラーをなんとかする

okuokuokuoku

とりあえず、 vmlinux.a としてLinuxソースをひととおりコンパイルできたようなのでなんとかリンクしたい。LKL自体はCOFFでもリンクできるようだが、基本的にLinuxはELF前提なので色々と難しい。。

okuokuokuoku

jiffies

とりあえず適当にリンカを実行すると:

$ ../_warp/bin/warp-cc -g -nostdlib -Wl,--no-entry -Wl,--export=init -Wl,--error-limit=0 -Wl,--verbose ../vmlinux.a hostwasm_main.c

大量のundefinedが出る。これらを解消していかないといけない。。

wasm-ld: error: ../vmlinux.a(mm/slub.o): undefined symbol: jiffies

jiffiesはリンカスクリプトでaliasされている。

https://github.com/lkl/linux/blob/31a835e54b32bc76cde50f41aab41285ab9053d9/arch/lkl/kernel/vmlinux.lds.S#L14

というわけでaliasする必要がある。 ...というかアドレスを計算で埋めてるものはソリューションが無くない。。?

diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 717fcb9fb14a..e33d1bfbbf41 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -59,6 +59,10 @@

 __visible u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;

+#ifdef __wasm__
+extern unsigned long volatile __cacheline_aligned_in_smp __jiffy_arch_data __attribute__((alias ("jiffies_64"))) jiffies;
+#endif
+
 EXPORT_SYMBOL(jiffies_64);

 /*
okuokuokuoku

_ctype

wasm-ld: error: ../vmlinux.a(lib/kstrtox.o): undefined symbol: _ctype

うーん。。ビルドはされている。

https://github.com/lkl/linux/blob/31a835e54b32bc76cde50f41aab41285ab9053d9/lib/ctype.c#L12

$ llvm-nm ./lib/ctype.o
00000000 d .debug_abbrev
00000000 d .debug_line
00000000 d .debug_str
00000000 D _ctype

... ./lib/lib.a ってのが別にあるのか。。これをリンクすればOKっぽい。

$ ../_warp/bin/warp-cc -g -nostdlib -Wl,--no-entry -Wl,--export=init -Wl,--error-limit=0 -Wl,--verbose -Wl,--Bstatic ../lib/lib.a ../vmlinux.a hostwasm_main.c
okuokuokuoku

init_thread_unioninit_stack

これはリンカスクリプト内で定義される。

https://github.com/lkl/linux/blob/31a835e54b32bc76cde50f41aab41285ab9053d9/include/asm-generic/vmlinux.lds.h#L399-L407

うーん。。とりあえず64KiB予約しとくか。。アドレスは同じでよいのでaliasで対応できる。

static char dummy_page[64*1024];
extern char* __attribute((alias ("dummy_page"))) init_thread_union;
extern char* __attribute((alias ("dummy_page"))) init_stack;
okuokuokuoku

残件

見たところ、コンストラクタ系とメモリ空間系に大別されるな。。

コンストラクタ系?

コンストラクタ系はセクションを収集して1箇所にあつめる必要がある。 ...というのはWasmでは不可能なので、これを行っているところは手を入れる必要がある。

(init/main.o): undefined symbol: __initcall0_start
(init/main.o): undefined symbol: __initcall1_start
(init/main.o): undefined symbol: __initcall2_start
(init/main.o): undefined symbol: __initcall3_start
(init/main.o): undefined symbol: __initcall4_start
(init/main.o): undefined symbol: __initcall5_start
(init/main.o): undefined symbol: __initcall6_start
(init/main.o): undefined symbol: __initcall7_start
(init/main.o): undefined symbol: __initcall_end
(init/main.o): undefined symbol: __initcall_start
(init/main.o): undefined symbol: __setup_end
(init/main.o): undefined symbol: __setup_start
(kernel/params.o): undefined symbol: __start___param
(kernel/params.o): undefined symbol: __stop___param
(kernel/printk/printk.o): undefined symbol: __con_initcall_end
(kernel/printk/printk.o): undefined symbol: __con_initcall_start
(kernel/sched/core.o): undefined symbol: __sched_class_highest
(kernel/sched/core.o): undefined symbol: __sched_class_lowest

メモリ空間系?

これらはstubしてしまって良いはず。つまり extable(exception table)はそもそもWasmではハンドルできないし、page関連もLKLでは使われない。

(kernel/extable.o): undefined symbol: __start___ex_table
(kernel/extable.o): undefined symbol: __stop___ex_table
(kernel/extable.o): undefined symbol: _etext
(kernel/kallsyms.o): undefined symbol: __init_begin
(kernel/kallsyms.o): undefined symbol: __init_end
(kernel/kallsyms.o): undefined symbol: _einittext
(kernel/kallsyms.o): undefined symbol: _end
(kernel/kallsyms.o): undefined symbol: _sinittext
(kernel/kallsyms.o): undefined symbol: _stext
(mm/page_alloc.o): undefined symbol: __bss_start
(mm/page_alloc.o): undefined symbol: __bss_stop
(mm/page_alloc.o): undefined symbol: _edata
(mm/page_alloc.o): undefined symbol: _sdata
(mm/util.o): undefined symbol: __end_rodata
(mm/util.o): undefined symbol: __start_rodata
(kernel/stacktrace.o): undefined symbol: __irqentry_text_end
(kernel/stacktrace.o): undefined symbol: __irqentry_text_start
(kernel/stacktrace.o): undefined symbol: __softirqentry_text_end
(kernel/stacktrace.o): undefined symbol: __softirqentry_text_start
okuokuokuoku

とりあえずリンクはできた

とりあえずリンカスクリプトで書いているものはゼロを埋めておいて、リンクだけ通しておいた。

$ ../_warp/bin/warp-cc -g -nostdlib -Wl,--no-entry -Wl,--export=init -Wl,--error-limit=0 \
-Wl,--verbose -Wl,--Map=out.map ../lib/lib.a ../vmlinux.a hostwasm_main.c