今天這篇進度比較差,但是也就只能這樣繼續努力debug。
首先先簡介一下原本的進度,是要將initramfs => true rootfs這條路打通,正常來說,Alpine的initramfs希望作的事情是:
(1) 將 apkovl
的overlay透過overlayfs蓋上userspace
(2) 然後使用apk-static將基礎套件裝到rw layer
(3) 緊接著如果有permanant stage的rootdev,才在最後蓋上來。
但是對我們的usecase來說,這太複雜了。而且按照Alpine Init的邏輯,他的root
會跟kernel parameter衝突,其實這也代表它的預期流程是被kernel直接包套吃走的;為了避免每次都要重包kernel、且反正initramfs我們可以改,不如這樣辦吧:
直接hack掉permanent rootdev的detection,並且塞一個loopback file進去initramfs當作我們的real rootdev。
可是這樣改時,會非常尷尬地遇上一個問題:
那就是Alpine Init是用swtich_root在作iniramfs => rootfs的交棒,而switch_root期待新舊皆為ramfs/tmpfs。
出於無奈,我們再次進行改動 — —
將原本的
exec /bin/busybox pivot_root $sysroot $chart_init "$KOPT_init" $KOPT_init_args
更改為
cd /sysroot
pivot_root . .
exec chroot . /sbin/openrc
然而此時,我們撞到了bus error:
[ 165.477801] openrc[82]: unhandled signal 7 code 0x2 at 0x95ad11ac in ld-musl-riscv32-sf.so.1[95ad4000+c7000]
[ 165.478835] CPU: 0 PID: 82 Comm: openrc Not tainted 5.10.7 #2
[ 165.479261] epc: 95b473dc ra : 95b556e0 sp : 9da494f0
[ 165.479607] gp : 95ad4000 tp : 95b9df28 t0 : 00000002
[ 165.479960] t1 : 0000d1d3 t2 : 00000007 s0 : 9da499a8
[ 165.480307] s1 : 0000d000 a0 : 95ad11ac a1 : 00000000
[ 165.480654] a2 : 00000e54 a3 : 00000fff a4 : fffff000
[ 165.481006] a5 : 00000000 a6 : 00000000 a7 : 000000de
[ 165.481355] s2 : 95ac5000 s3 : 00000000 s4 : 95ac5000
[ 165.481695] s5 : 000000a0 s6 : 00000000 s7 : 00000003
[ 165.482210] s8 : 00000004 s9 : 95b9ca6c s10: 0000d000
[ 165.482496] s11: 9da4955c t3 : 95b9c288 t4 : 00000000
[ 165.482757] t5 : 00000000 t6 : 00000020
[ 165.482968] status: 00004020 badaddr: 95ad11ac cause: 0000000f
Bus error
若單純照字面解讀, cause 0xf
代表著(AMO) store error,所以kernel判定是bus error。
但是此時我們還在QEMU上做事,這比較有可能發生的情形是、出於某些原因PC飛到了data segment去,而非真正的bus error。
而initramfs半殘的狀態下,我們還是先回shell來找找有沒有比較小的測試可以看。
在亂try亂看的路上,我們發現了一組有趣的對照:apk-static
可以正常運作,但是apk
不行,這個警訊整個讓人警鈴大響 — — dynamically linked 出bug了。
然而此時遇到了一個我還在想辦法workaround掉的debug難點:seperated debug symbol。
在現代化的distro、為了方便distribute套件,會採用「先開啟debug build、再objcopy出 debug symbol的elf stub、爾後strip target program」的手法,一般人安裝時都是strip過的、爾後需要debug時去安裝*-dbg
的套件。
想做實驗的話,可以這樣玩:
riscv32-linux-gcc -g3 -static ./hello_world.c -o hello_world
riscv32-linux-objcopy --only-keep-debug ./hello_world ./hello_world.debug
riscv32-linux-strip --strip-debug --strip-unneeded ./hello_world
qemu-riscv32 -g 1234 ./hello_world &
riscv32-linux-gdb -ex 'target remote localhost:1234' -ex 'symbol-file ./hello_world.debug'
But,就是這個but,目前我從我bootstrap的musl-dbg套件中撈出來的seperated debug file,是壞的Orz
下篇會來繼續debug這個慘況QQ