OpenBSD観光
『日本人は知らない中国セレブ消費』なんて言う本を読んだ。帯に、なぜ角部屋を彼らは嫌う? と言うキャッチが踊っていたから、ついつい手にした次第。著者は、上海生まれの方。日本に留学して、就職して、日本を体験した。その後、上海に戻って、日本の体験を生かして、セレブをターゲットにした雑誌を発行してるとか。
帯の答え、オイラーの予想は、角部屋では日光で家具が傷むだろうってもんだ。そんなの西洋の思想って軽くいなされたよ。風水ですよ。
角部屋と言うと、マンションでもホテルでも、大体が廊下の突き当りにある。邪気も廊下を伝わってきて角部屋に入り込む。中国人は、そんな邪気が漂う部屋には入りたくないぞと思うんだとか。
ホテルとかで、そんな部屋を割り当てられたら、まずは普通の部屋に部屋替えを依頼するらしい。だめなら、入室の時、大きな声を出して邪気を追い払うそうな。
著者は日本で旅行業界に居たんで、その経験を生かして旅行雑誌を発行してるんだけど、中国人の 思想を縦横に語っている。
日本は中国に無い文化と正直な国民性が評価され、何度も訪れたい国になってる。上海からだと九州へ来る方が北京に行くよりずっと近い。
豪華な刺身が大好き。生の魚を切っただけの料理なんで、誤魔化し様が無いから。そして、インスタ映えが、面子大好きな彼らにはぴったりだそうだ。
その他、色々と中国人をお得意様にする方法が紹介されてた。
詳しくしようは、失敗
前回qemuにOpenBSDを入れて、gdbから操れるようにした。こういうのは、みなさんやってる遊びなんですなあ。
Memo: How to build OpenBSD from source code and add system call on QEMU
こちらの方も、システムコールを追加する遊びまでやっておられて、良い道標になりますよ。
それはそうと、gdbから操れるって言っても、問題が無いとは言えない。関数の引数や、内部で 使われている変数をprintしようとすると、それはoptimizeされてるんで表示出来ないのよと言われるんだ。気分が落ち込みますなあ。
コンパイルする時に、最適化無しを指定すると、エラーになってしまい、カーネルが完成しなかったんだ。先を急ぐんで、涙をのんだわけ。でも、惜しいな。
man clang して、最適化を見ると、-O0 の他に、-Og てのも載ってたけど、これは将来のお楽しみらしい。
真面目にエラーと向き合う事にしたよ。で、最初に表われたエラーは、pf_iostat だったかの 関数に関するエラー。フレームサイズが一定以上になってると、それっておかしいんじゃねぇと 目を付けられるんだ。最適化しないんで、余計なものがフレームに残るんでしょうな。
何処かに、リミット値が書かれているはずだと思って調べたら、下記のMakefileに指定してあった。AMDのagp関数も通過出来るように、非常に大きな値にしてる。
cat i386/conf/Makefile.i386 : -Wframe-larger-than=6047 ## org is 2047 COPTS="-O0" make 又は COPTS="-Og" make
そして、上記のオプションでコンパイルしたが、エラーですよ。
ld -T ld.script -X --warn-common -nopie -o bsd ${SYSTEM_HEAD} vers.o ${OBJS} aic79xx.o: In function `ahd_handle_seqint': /usr/src/sys/dev/ic/aic79xx.c:1131: undefined reference to `ahd_assert_atn' /usr/src/sys/dev/ic/aic79xx.c:1177: undefined reference to `ahd_assert_atn' : pipex.o: In function `pipex_mppe_output': /usr/src/sys/net/pipex.c:2534: undefined reference to `pipex_mppe_setkey' /usr/src/sys/net/pipex.c:2559: undefined reference to `pipex_mppe_crypt' : wskbdutil.o: In function `wskbd_compose_value': /usr/src/sys/dev/wscons/wskbdutil.c:209: undefined reference to `compose_tab_cmp' i915_gem_gtt.o: In function `i915_gem_setup_global_gtt': /usr/src/sys/dev/pci/drm/i915/i915_gem_gtt.c:2712: undefined reference to `intel_vgt_balloon' : ahd_pci.o: In function `ahd_find_pci_device': /usr/src/sys/dev/pci/ahd_pci.c:305: undefined reference to `ahd_compose_id' *** Error 1 in /usr/src/sys/arch/i386/compile/DEBUG (Makefile:992 'bsd': @echo ld -T ld.script -X --warn-common -nopie -o bsd '${SYSTEM_HEAD...)
エラーを手掛かりに、ググル先生に聞いてみたけど、まだ誰も報告を上げていない。はて、どうしたものか? メーリングリストに加わって聞いてみたいけど、流量が多そうで躊躇してる。
ob6$ cc -v OpenBSD clang version 5.0.1 (tags/RELEASE_501/final) (based on LLVM 5.0.1) Target: amd64-unknown-openbsd6.3 Thread model: posix InstalledDir: /usr/bin ob6$ gcc -v Reading specs from /usr/lib/gcc-lib/amd64-unknown-openbsd6.3/4.2.1/specs Target: amd64-unknown-openbsd6.3 Configured with: OpenBSD/amd64 system compiler Thread model: posix gcc version 4.2.1 20070719
もしものためにgccも残してあるけど、これでコンパイル出来るのかなあ。上であげたMaMakefile.i386が元締めっぽいんで、これを変更して試してみるかな。
for kernel debug
上でgccに思いが至ったのは、オイラーの知らないオプションが出て来たから。clangの説明にも 載ってなかったんだ。こういう時は先輩のgccに尋ねてみるのがセオリー。脊髄反射で、man gccとしてたのさ。そしたら、ちゃんと説明が出て来た。だったら、 本体も居るんじゃねぇ? 何もかもググル先生に聞くのは止しましょう。
んでもって、お試しに
ob6# config SS ob6# cd ../compile/SS ob6# vi obj/Makefile ob6# CC=gcc make
Makefileで変更したのは、下記部分
COPTS?= -O0
configすると、ヘッダーファイル類とMakefileがobjの下に作られる。このMakefileは、config時に、Makefile.i386がコピーされるっぽい。だから、このMakefileはいじり倒してもOK。それから、このMakefileを見てて気が付いたんだけど、amd64な環境でも、ちゃんとi386用にコンパイルしてくれるのね。そんな事は知らんかったわい。
で、コンパイルすると、Intel i915の所で失敗する。どうせ、qemuで実行するんだから、X関係者なんていらないでしょ。それからついでに、ATI Radeon DRM driver の部分もコメントアウトしておいたよ。(これ不完全、後述のkernel for debugを試せ)
kernel startup 観光旅行
気分を変えるって事で、旅にでる事にした。
カーネルが起動して、ログインメッセージが出て来るまでを、ドキュメント風に追ってみる。定番の観光コースですな。
コンソールには、com0を設定。
ss63$ cat /etc/boot.conf set tty com0
ああ、これは、qemu配下のターゲットOpenBSD側ね。
そして、
qemu-system-i386 -m 256 -S -s \ -serial pty \ -net nic -net user,hostfwd=tcp::2022-:22 disk &
こんな設定で、qemuをスタート。すかさず、シリアルラインにcuで接続しておく。
QEMUの画面は、guest has not initialized the display (yet). で待ち受けです。
Reading symbols from bsd.gdb...done. 0x0000fff0 in ?? () (gdb) b main Breakpoint 1 at 0xd08c2720: file /usr/src/sys/kern/init_main.c, line 192. (gdb) c Continuing. Breakpoint 1, main (framep=<error reading variable: Cannot access memory at add\ ress 0x8>) at /usr/src/sys/kern/init_main.c:192 192 { (gdb)
進み具合の優先権はgdbにあるので、mainにBPを置いてcontinueする。(FreeBSDはmainなんてのは無かったような気がしたぞ。OpenBSDは優しい作りだな。)
Booting from Hard Disk... Using derive 0, partition 3. Loading....... probing: pc0 com apm pci mem[639K 254M a20=on] disk: fd0 hd0+ >> OpenBSD/i386 BOOT 3.31 switching console to com0
この時、QEMUのコンソールには、こんな案内が出て来る。
cu -l /dev/ttyp4 Connected to /dev/ttyp4 (speed 9600) >> OpenBSD/i386 BOOT 3.31 boot> booting hd0a:/bsd: 8119572+2216964+164616+0+1089536 [662718+82+492608+504331]=0xca5524 entry point at 0x2000d4 [ using 1660196 bytes of bsd ELF symbol table ]
シリアルライン側の表示。mainで止まった時は、カーネルがローディングされた状態。
(gdb) 230 cpu_startup(); (gdb) 232 random_start(); /* Start the flow */
gdbのnextを実行した。
Copyright (c) 1982, 1986, 1989, 1991, 1993 The Regents of the University of California. All rights reserved. Copyright (c) 1995-2018 OpenBSD. All rights reserved. https://www.OpenBSD.org OpenBSD 6.3 (DEBUG) #5: Tue Jun 5 14:20:13 JST 2018 sakae@ob.happy.net:/usr/src/sys/arch/i386/compile/DEBUG cpu0: QEMU Virtual CPU version 2.5+ ("GenuineIntel" 686-class) 2.41 GHz cpu0: FPU,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,PGE,CMOV,MMX,FXSR,SSE,SSE2,SSE3,HV real mem = 267796480 (255MB) avail mem = 248979456 (237MB)
見慣れたバナーが出て来たな。
366 config_rootfound("mpath", NULL); (gdb) 370 cpu_configure();
少し先まで進める。
mpath0 at root scsibus0 at mpath0: 256 targets
マザーボードのバスの検出でしょうか?
369 /* Configure the devices */ 370 cpu_configure();
ちょっとgdbの魚拓を取り忘れてしまったけど、370行目が実行されると、ドドーンと デバイスの認識が行われる。
: pckbc0 at isa0 port 0x60/5 irq 1 irq 12 pckbd0 at pckbc0 (kbd slot) wskbd0 at pckbd0: console keyboard, using wsdisplay0 pms0 at pckbc0 (aux slot) wsmouse0 at pms0 mux 0 pcppi0 at isa0 port 0x61 spkr0 at pcppi0 lpt0 at isa0 port 0x378/4 irq 7 npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16
そして、この行が(dmsgにも出てるだろうけど)表示された所で、ステップをしても 粛々と内部のソフト的な準備が進むようである。
570 start_periodic_resettodr(); (gdb) 576 tsleep(&proc0, PVM, "scheduler", 0); (gdb)
そして、遂に変化が表れて。ここからはinitさんが、/etc/rcを解釈実行してくんだな。
Automatic boot in progress: starting file system checks. /dev/wd0a (0496db44f78111d2.a): file system is clean; not checking setting tty flags pf enabled starting network em0: bound to 10.0.2.15 from 10.0.2.2 (52:55:0a:00:02:02) fd0 at fdc0 drive 1: density unknown starting early daemons: syslogd. starting RPC daemons:. savecore: /dev/wd0b: Device not configured checking quotas: done. clearing /tmp kern.securelevel: 0 -> 1 creating runtime link editor directory cache. preserving editor files. starting network daemons: sshd. starting local daemons:. Sat Jun 9 15:35:39 JST 2018
ここで、initさんの初期仕事はおしまい。後は、監視役になるのか。
575 while (1) (gdb) n 576 tsleep(&proc0, PVM, "scheduler", 0);
で、何度かこのルーチンを回ると
OpenBSD/i386 (ss63.my.domain) (tty00) login:
gettyだかが起動してくるんだな。やっと、見慣れた所に到達した。 同様なログインメッセージは、QEMUのコンソールにも出て来たぞ。
ss63$ dmesg | tail lpt0 at isa0 port 0x378/4 irq 7 npx0 at isa0 port 0xf0/16: reported by CPUID; using exception 16 nvram: invalid checksum vscsi0 at root scsibus2 at vscsi0: 256 targets softraid0 at root scsibus3 at softraid0: 256 targets root on wd0a (0496db44f78111d2.a) swap on wd0b dump on wd0b clock: unknown CMOS layout fd0 at fdc0 drive 1: density unknown
改めて確認すると、ここまでがカーネルさんのお仕事なんだな。
kernel for debug
amd64のマシンで、最適化しないkernelを作ってみた。ログインすると
login: sakae Password: Last login: Sat Jun 9 07:00:05 on tty00 OpenBSD 6.3 (SS) #0: Sat Jun 9 14:20:47 JST 2018 NO LOGINS: System going down at 9:00
なんだか、意味不なメッセージが出て来たぞ。なんじゃらほい? そして致命的な出来事が。。。隣の端末からsshでログインしようとしたら、
ss63$ uvm_fault(0xd0c7ce80, 0x0, 0, 1) -> e kernel: page fault trap, code=0 Stopped at pf_set_protostate+0x3d: movzbl 0x27(%eax),%eax ddb> ddb> trace pf_set_protostate(d170bb60,0,2,d081158f,d168c480) at pf_set_protostate+0x3d pf_create_state(f36eeec0,d194979c,0,0,f36eee38) at pf_create_state+0x497 pf_test_rule(f36eeec0,f36eefa8,f36eefa4,f36eefac,f36eefa0) at pf_test_rule+0xbca pf_test(2,1,d176b030,f36ef054,f36ef058) at pf_test+0x94a ip_input_if(f36ef054,f36ef064,4,0,d176b030) at ip_input_if+0x32c ipv4_input(d176b030,d178e800,6,d08a18e0,800) at ipv4_input+0x4c ether_input(d176b030,d178e800,0,d0939192,0) at ether_input+0x2bc if_input_process(d176b030,f36ef118,f36ef12c,d090f446,d171d054) at if_input_process+0x81 ifiq_process(d176b27c,f36ef158,d0731665,0,0) at ifiq_process+0x79 taskq_thread(d171d040) at taskq_thread+0x5c
この通り、ddb君がお出まししました。これじゃ、危なくておちおち観光旅行出来ないな。 無理して、amd64なコンパイラーで、i386用のカーネルを作るという、細い道を通ったから、地雷を踏んじゃったかしらん。
幸いバックアップとして、virtualboxにi386な環境を作ってあるんで(ポータブルOpenBSDを作る積りでインストールしたんだけど)、そこで製造したカーネルを持ってこよう。
どうせなら、多用されているマクロを展開・確認出来るようにしておくか。そんな訳で、Makefileに次のような変更を加えておいた。
DEBUG=-g3 COPTS?= -O0 -gdwarf-2
これでコンパイルすると、最後の最後で、リンカーにg3なんてオプションは無いぞと文句を 言われる。Makefileのg3をgにしてから、コンパイル再開。無事にカーネルが出来た。bsd.gdbが通常サイズの40M前後から、260Mに膨れ上がってしまったぞ。
走らせてみると、やはりsshとかscpは、中から外、外から中とも、ddbに落ちてしまう挙動。 でも、マクロの展開が出来るようになったんで、これで佳しとするか。こちらの方が絶対的に便利ですから。
(gdb) info macro ENXIO Defined at /usr/src/sys/sys/errno.h:47 included at /usr/src/sys/sys/param.h:75 included at /usr/src/sys/dev/audio.c:17 #define ENXIO 6
単純な確認
(gdb) macro expand FILE_SET_MATURE(fp,p) expands to: do { (fp)->f_iflags &= ~0x02; (--(fp)->f_count == 0 ? fdrop(fp, p) \ : 0); } while (0)
Lispで言うなら、マクロエキスパンドだな。
このカーネルだと、観光には便利なんだけど、何かをネット越しに転送する事が出来ない。 従来のカーネルも入れておいて、必要に応じて切り替えて使えばいいな。
例えば、ssh出来るカーネル(clangで普通にコンパイルした奴)を、/bsdSSH っていう名前で登録しとく。起動してbootプロンプトが出てきたら素早くスペースを叩く。後は落ち着いて
boot> boot hd0a:/bsdSSH
bsdSSHを指定する。これで、ワンショットでSSH出来るカーネルが上がってくる。何も指定 しなければ、5秒後に、bsd(gdbでマクロが見られるやつ)が、普通に立ち上がる。
リピーターの観光
一回旅行をすると、OpenBSDのフレンドリィーさが身に染みて分かってくる。そうすると、何度も訪れたくなるのは、チャイナの人と一緒。お上りさんじゃなくて、目的を持って旅をしたい。 で、選んだのは、オーディオなボードを検出して、それがカーネルに組み込まれる現場の確認。
カーネル屋さんなら、そりゃドライバーの組み込みでしょって言うはず。組み込むボードは、追加でac97をqemuの起動部分に追加した。(フィジカルには、オーディオボードの2枚刺しだ)
-soundhw ac97,es1370
組み込みなんで、アタッチかな。
(gdb) b audio_attach Breakpoint 1 at 0xd04348da: file /usr/src/sys/dev/audio.c, line 993. (gdb) c Continuing. Breakpoint 1, audio_attach (parent=0xd17dca00, self=0xd17dcc00, aux=0xd0ea8b18) at /usr/src/sys/dev/audio.c:993 993 {
予想は当たって、BPが当たったよ。以下は、長い長いルートを通って、やっと許可された図(ファイル名を閲覧し易いように、関数の引数は削除した)
(gdb) bt #0 audio_attach (..) at /usr/src/sys/dev/audio.c:993 #1 0xd075f6b9 in config_attach (..) at /usr/src/sys/kern/subr_autoconf.c:401 #2 0xd075f341 in config_found_sm (..) at /usr/src/sys/kern/subr_autoconf.c:311 #3 0xd0434e5c in audio_attach_mi (..) at /usr/src/sys/dev/audio.c:1185 #4 0xd08b8940 in auich_attach (..) at /usr/src/sys/dev/pci/auich.c:524 #5 0xd075f6b9 in config_attach (..) at /usr/src/sys/kern/subr_autoconf.c:401 #6 0xd075f341 in config_found_sm (..) at /usr/src/sys/kern/subr_autoconf.c:311 #7 0xd06153fb in pci_probe_device (..) at /usr/src/sys/dev/pci/pci.c:557 #8 0xd0615b15 in pci_enumerate_bus (..) at /usr/src/sys/dev/pci/pci.c:784 #9 0xd0614573 in pciattach (..) at /usr/src/sys/dev/pci/pci.c:197 #10 0xd075f6b9 in config_attach (..) at /usr/src/sys/kern/subr_autoconf.c:401 #11 0xd075f341 in config_found_sm (..) at /usr/src/sys/kern/subr_autoconf.c:311 #12 0xd058cc95 in mainbus_attach (..) at /usr/src/sys/arch/i386/i386/mainbus.c:250 #13 0xd075f6b9 in config_attach (..) at /usr/src/sys/kern/subr_autoconf.c:401 #14 0xd075f3cf in config_rootfound (..) at /usr/src/sys/kern/subr_autoconf.c:326 #15 0xd0912cb4 in cpu_configure () at /usr/src/sys/arch/i386/i386/autoconf.c:160 #16 0xd0696d9e in main (framep=0x0) at /usr/src/sys/kern/init_main.c:370 (gdb)
そして、こちらは、dmsgに出てきた記録。
auich0 at pci0 dev 4 function 0 "Intel 82801AA AC97" rev 0x01: apic 0 int 11, ICH ac97: codec id 0x83847600 (SigmaTel STAC9700) audio0 at auich0
後は、これを手掛かりに、思い出に浸るのが定番。ゆっくりグラスでも傾けながらね。