kgdb in openbsd
連休で暇なんで、近くの露天風呂へ行ってきた。地元の人しか知らないような隠れ湯。 山の中なんで、まだ桜が咲いていて、その花びらが湯に落ちてきて、風情がありましたよ。
ゆったり日向ぼっこしてた老人と目が合ってしまったので、一期一会と思って話しかけて みたぞ。隣の村からひと山超えてやってきたとの事。よく来てるそうだ。
今の季節、山菜いいですねぇって始まった、山菜談義。山菜の王様はなんだ? こしあぶら? タラの芽?やまうど? 出るわ出るは、いろんな名前のやつが。やがて、蕎麦の話になり、 きのこの話に、とりとめもなく続く。
おかげで、すっかり日焼け。こんな山の中でも紫外線が強いので強力に焼けたよ。 こんな日焼け、若い頃の山スキー以来だな。この時期、山形の月山でずっとスキーしてた ものね。
たまにはいいね。見ず知らずの人とのんびり会話するのも。世間では、マストドンなんてのが 大盛り上がりみたいで、 Mastodon(マストドン)とか、 Mastodonを楽しく歩こう なんてのも始まったみたいだけど、やっぱりフェースツーフェスが一番だと思うぞ。 (こんな事を書くようになっちゃ、爺の証拠だわな)
で、まだ連休が続いていたので、CQ出版から出てる、インターフェースなんて雑誌を、 本当に久しぶりに買ってみた。
新科学計算ソフトウルトラ大集合、ですって。やっぱりPythonとRが鉄板だな。そして パソコンを使えない若者が好む、スマホ向けも、その手のやつが大分有るようだ。
手書きで数式を入力すると、その式を元にグラフを書いてくれるやつが有るそうだ。 無料なんで試して、若者気分を味わってみるかな。
どこもかしこも、pythonで、 Python 3の組み込み関数を速攻理解しようなんてのも続いている。
kgdb for qemu-kvm
前回の続きで、CentOSにqemu-kvmを突っ込み、ゲストOSとしてOpenBSDを入れて、 ごにょごにょやってる。OpenBSDのカーネル観光の土台作り。
DDBとKGDBは排他になってるので、DDBの方を殺して、KGDBが有効になったカーネルを作る。 下記は、その設定の抜粋。(includeしてるGENERICの方でDDB宣言を無効にしとく事)
makeoptions DEBUG="-g" #option DDB # in-kernel debugger #option DDB_SAFE_CONSOLE # allow break into ddb during boot option KGDB # Remote debugger support; exclusive of DDB option "KGDB_DEVNAME=\"com\"",KGDBADDR=0x2f8,KGDBRATE=9600
そして、起動時に十分にbootオプション(debuggerに落ちるなら、-d)を入力する時間を 与えるため、設定をする。
# cat /etc/boot.conf set timeout 120
それから、qemuにシリアルラインを生やすため、-serial ptyを追加した、起動コマンドを 用意しる。
[cent tmp]$ cat com /usr/libexec/qemu-kvm -m 256M -net nic -net user -s \ -redir tcp:2022::22 -serial pty disk & sleep 2 vncviewer localhost:5900
これで起動すると、下記のように、/dev/pts/4がそのシリアルだと教えてくれる。
[cent tmp]$ ./com char device redirected to /dev/pts/4 (label serial0) VNC server running on `::1:5900' :
やおら、gdbを起動して、シリアルで接続するも、無しのつぶて。
[cent DEBUG]$ gdb -q bsd.gdb Reading symbols from bsd.gdb...done. (gdb) set serial baud 9600 (gdb) target remote /dev/pts/4 Remote debugging using /dev/pts/4 Ignoring packet error, continuing... warning: unrecognized item "timeout" in "qSupported" response Ignoring packet error, continuing... Remote replied unexpectedly to 'vMustReplyEmpty': timeout
ネットを彷徨うと、こんなのもあったけど、やはりkgdbとは接続出来ず。 kgdb waiting ... と、OpenBSD側にメッセージが出たままになる。
(gdb) set architecture i386:x86-64:intel (gdb) target remote | exec /usr/libexec/qemu-kvm -gdb stdio
で、ふと、dmesgを見てたら、カーネルのkgdb受付用ポートと、ハード?側に用意された ポートのアドレスが違う事に気付いてしまった。
$ dmesg com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo
これはもう、kgdbのポートを変更する鹿。変更後のdmesgでは、com0がkgdb用に割り当てられたって確認出来た。
com0 at isa0 port 0x3f8/8 irq 4: ns16550a, 16 byte fifo com0: kgdb
でも、相変わらず
[cent DEBUG]$ gdb -q bsd.gdb Reading symbols from bsd.gdb...done. (gdb) target remote /dev/pts/4 Remote debugging using /dev/pts/4 Ignoring packet error, continuing... warning: unrecognized item "timeout" in "qSupported" response Ignoring packet error, continuing... Remote replied unexpectedly to 'vMustReplyEmpty': timeout
となってしまって、意志疎通が出来ない状態。CentOS側のgdbを起動しておいて、OpenBSD側からちょっかいを出しても、その逆でも同様。
こちらの方も、同様なお悩みがあるようですよ。
text data bss dec hex 9632556 245784 671744 10550084 a0fb44 mv bsd bsd.gdb strip -S -o bsd bsd.gdb 2m00.90s real 1m19.50s user 0m27.67s system
この間、何度コンパイルしたやら。コンパイルするたびにデバイスを減らしていったら、大分スピードアップが図れたな。
alias ddb='sysctl ddb.trigger=1'
qemu-kvmな環境ではkgdbは使えないという結論を下さざるを得ない。諦めて、ddbを使う 環境に戻した。何時でもddbに突入出来るように、上のようなエイリアスを書いておいたよ。
それから、不思議な事に、ddbを生かした環境でも、Cent側でgdbを起動して、target remote :1234 すると、普通にgdbでtarget側のOpenBSDを観察出来る事。どういう仕組みで動いて いるのかな?
本物のOpenBSD 6.0 上で確認する
で、しょうがないので、生粋のOpenBSD 6.0 環境でやってみる。qemu-system-x86_64の中で 動いているやつが対象です。
text data bss dec hex 9417580 224104 651264 10292948 9d0ed4 mv bsd bsd.gdb strip -S -o bsd bsd.gdb real 1m47.274s user 0m48.520s sys 0m51.920s
この差は、qemu-kvmのオーバーヘッドかな? まだ削れそうな所が有るから、暇に任せて やってみるかな。それより、kgdbが動くかの確認が先。
結論を書いてしまえば、CentOSと同じ症状になり失敗しました。何か見落としている所が 有るのだろうか? これ以上はソース嫁の世界かな。
VBOXにOpenBSD 6.1を入れる
気分を変えて、VBOXの方へFULLのOpenBSDを入れた。
何か新しいportsが来ていないか調べてみたら、hugs98が無くなっていた。古いので 誰も見向きもしなくなったんだろうね。ちょいと使うのには軽くていいんだけどな。 素のソースを取ってきて入れようとしたら、途中でエラー発生。
諦めて、6.0の時のportsをコピペ(こういうのをレシピの盗用と言います)してきて、 コンパイルしたら、無事に入った。果たしていつまで盗用が出来るやら?
で、気分を変えて、 chibi-scheme なんてのを試している。作者は、あのscheme-complate.elを書いた、Alex Shinnさん。
chibiって日本語だよな。彼はgaucheのshiroさんと一緒にやってたんで、日本語に感化 されて、名前を決めたに違いない。
Snow Package Managerというのも用意されてて、そのリポジトリぃーには、shiroさんの名前もうかがえる。 切磋琢磨してるんだな。
VBOX, VMWare間で、kgdb
失敗続きのkgdb、最後の悪あがきとして、VBOXとVMWareのコラボレーションでやってみる。 すでにVBOXの方へはOpenBSD6.1を入れたので、VMWare側にも入れる。VBOX側ではgdbを 起動して、VMWare側のOpenBSDを観測しよう。
Serial connectionを 思い出して、VMWare側はクライアント設定。VBOX側がサーバー側。tty00を一般ユーザーが 使うには、dialerに属している必要が有る。
(gdb) target remote /dev/tty00 Remote debugging using /dev/tty00 Ignoring packet error, continuing... breakpoint () at cpufunc.h:343 343 cpufunc.h: No such file or directory. in cpufunc.h
VMWare側で、起動時に、-dしたら、上記のようになった。一応繋がっているみたい。 続いて、プロセスが生まれる所にBPを張る。
(gdb) b fork1 Breakpoint 2 at 0xffffffff8111be6f: file /usr/src/sys/kern/kern_fork.c, line 323. (gdb) c Continuing. Can't send signals to this remote system. SIGEMT not sent. Program received signal SIGEMT, Emulation trap. 0xffffffff8111030a in main (framep=0xe) at /usr/src/sys/kern/init_main.c:189 189 { (gdb) c Continuing. Can't send signals to this remote system. SIGEMT not sent. Program received signal SIGEMT, Emulation trap. breakpoint () at cpufunc.h:343 343 cpufunc.h: No such file or directory.
fork1は、437行目に有るんだけど、上では、mainの入り口を指しているな。それから、cpufunc.hが 見つからないと言ってきてるけど、arch/amd64/include/cpufunc.hに有るぞ。
/* Break into DDB/KGDB. */ static __inline void breakpoint(void) { __asm volatile("int $3"); }
asm命令が書いてあるんで、gdbはいかんともしがたいから、無いって嘘をついているのかな。 で、続きをやろうとしたら、クライアント側がハングした。
クライアント側を立ち上げた後、サーバー側から接続に行くと、
vmx| I125: serial0: Overrun
VMWare側はパニ喰った。これ、VMWare側のログね。これから後に続くログを添えて、サポセンに連絡とか出てきた。遊びで使っているので、封印しておこう。
kgdb 諦めた
ddbが有効なやつでも、systemcallぐらいは、gdbでソースから追えるんで良しとしよう。 本当にddbで追及するのは、mainの中だけに限られるからね。
そんな訳で、コンパイルを繰り返していたqemu配下のdiskは、随分と肥大化してたんで、 インストールのやり直し。(都合、4回も6.1をインストールしたんで、もう慣れたものです)
Cent側にある、ソースをOpenBSD内に取り込むの、今まではrsycが定番だったけど、どうせ 一回しか出番がないので、scpを使ったよ。
$ scp -r cent:ob61/sys .
考えながら転送してるんで、少々時間がかかったぞ。
記念に出来たカーネルの状況。デフォルトのカーネルは、色々なハードに対応するため 太っているけど、関係ないのをそぎ落とすと、スリムになるな。
# ls -lh bsd obsd -rw-r--r-- 1 root wheel 6.5M May 4 14:39 bsd -rw-r--r-- 1 root wheel 10.2M May 4 14:39 obsd
そして、そのカーネルを逆Asmして、使われている命令を列挙してみた。ダントツでmovが 多いって事は、データをあちこちに移動させるのがカーネルの仕事ですって事だな。 次に多いのは、add。きっと、1を足し算する、小学生並みの事しかやってないんでしょね。 次は、何かの下請けを呼び出す事か。大体10命令に1回の割合で、下請けをこき使うとな。 カーネルは偉い人なんだな。
[cent tmp]$ objdump -D bsd >LOG [cent tmp]$ wc LOG 1662656 11019966 104634892 LOG [cent tmp]$ cat LOG | cut -f3 | cut -d' ' -f1 | sort | uniq -c | sort -nr 690527 mov 98632 add 74767 callq 49340 je 39628 and 38567 cmp 31862 test 31210 movl 29593 jne 27210 push 26283 sub 24467 movzbl 23448 jmp 22882 lea 20415 jmpq 19731 movzwl 19617 cmpl 17348 xor 15148 retq 14794 leaveq 13063 or 11198 shl 10885 movq 10060 imul 9876 int3 9409 movslq :
インテルの糞石は、可変命令長なやつ。逆Asmした時、命令語の長さが不規則。それでも 頑張って、綺麗に並べるために、TABが使われている。
今回はそのTABを目印にフィールドを分解してみた。cutのフィールドセパレータは、 デフォでTABになってるのね。知らなかったぞ。
ああ、調子に乗って、OpenBSDのスリム化をやっていたら、とうとうやせ細って、立ち上がれ なくなったぞ。ちょいと悔しいな。