NetBSD dtrace格闘記その2
(NetBSD6.0でdtrace環境を手っ取り早く整えたい方は、末尾のほうにある「まとめ」を読んでくださいな。)
前回の日記では
*NetBSD6.0ではdtraceが導入された。公式のWiki(http://wiki.netbsd.org/how_to_enable_and_run_dtrace/)に導入方法が書いてあった。
* しかし、modloadしようとするとsolarisモジュール以外のモジュールがいないといわれる。
* build.shでdistributionしてできたオブジェクト群の中にはモジュールが存在している。ということはインストールができていないだけ。
*build.shにはinstallmodulesというOperationが存在するが、そのときに指定するディレクトリがよくわからない。
*modloadのソースをシステムコール含め読んでみると、どうやらmodloadは/stand/i386/6.0/modulesディレクトリの下を見に行っていることがわかった。
*よって、installmodulesに指定するディレクトリは/stand/i386/6.0/modulesを指定すればいいんじゃね?という仮説が立った。
ということを書いた。
そこで、今日はbuild.shでinstallmodulesを試す。
./build.sh -a i386 -O ../obj -T ../tools installmodules=/stand/i386/6.0/modules
途中までうまくいくが、sys/modules/xldscriptsのところでエラーが発生する。
install ===> sys/modules/xldscripts # install /stand/i386/6.0/modules/usr/libdata/ldscripts/kmodule /usr/src/../tools/bin/i486--netbsdelf-install -N /usr/src/etc -c -r -o root -g wheel -m 444 kmodule /stand/i386/6.0/modules/usr/libdata/ldscripts/kmodule i486--netbsdelf-install: /stand/i386/6.0/modules/usr/libdata/ldscripts: mkstemp: No such file or directory *** Failed target: /stand/i386/6.0/modules/usr/libdata/ldscripts/kmodule *** Failed command: /usr/src/../tools/bin/i486--netbsdelf-install -N /usr/src/etc -c -r -o root -g wheel -m 444 kmodule /stand/i386/6.0/modules/usr/libdata/ldscripts/kmodule *** Error code 1
ログによると、/stand/i386/6.0/modules/usr/libdata/ldscripts/kmoduleが存在しないと言われているようだ。
けど、/stand/i386/6.0/modules/の下のさらに/usr/libdata/ldscripts/kmoduleを探しにいくのはおかしい。
他のモジュールのインストールログを見ると「/stand/i386/6.0/modules/stand/i386/6.0/modules」なんてディレクトリ構成になっている・・・。
どうやら指定したディレクトリに/stand/i386/6.0/modulesディレクトリを作成し、そこにモジュールをインストールしていると推定。
今回モジュールをインストールしたいのは/stand/i386/6.0/modulesなので、installmodulesで「/」を指定することにした。
./build.sh -a i386 -O ../obj -T ../tools installmodules=/
installmodulesは成功した。しかし、再度modloadを試みてもやはりsolaris以外のモジュールがロードできないし、/stand/i386/6.0/modulesの下に該当モジュールがいない。
よって、「インストールすべきモジュール群はどのようにして決まっているのか」を追うことにする。
まず、ソースファイルが置かれたルートディレクトリ(build.shがあるディレクトリ)にあるMakefileを見る。build.shがinstallmodules時に叩いているMakefileだ。
installmodulesターゲットでは、諸々のチェックをしたあと、以下の3行を実行する。
${MAKEDIRTARGET} sys/modules install DESTDIR=${INSTALLMODULESDIR:U/} @echo "make ${.TARGET} started at: ${START_TIME}" @printf "make ${.TARGET} finished at: " && date
${MAKEDIRTARGET}とは何でこれは何処にいるのか?
grepをかけて調べると、share/mk/bsd.own.mkにいることがわかる。
bsd.own.mkの説明書きによると
# # MAKEDIRTARGET dir target [extra make(1) params] # run "cd $${dir} && ${MAKEDIRTARGETENV} ${MAKE} [params] $${target}", with a pretty message #
とのことである。このことからcd sys/modulesしてmakeをしていることが伺える。
そこで、sys/modulesの下のMakefileを見る。すると以下の記述が存在する。
.if (${MKDTRACE} != "no") SUBDIR+= dtrace .endif # we need solaris for the dtrace and zfs modules .if (${MKDTRACE} != "no" || ${MKZFS} != "no") SUBDIR+= solaris .endif
これによるとdtraceはMKDTRACEというビルド変数が"no"以外でないとmakeの対象にしてもらえないらしい。
ここで、solarisモジュールはインストールできている。
その理由はshare/mk/bsd.own.mkの中で以下のように定義されているためである。
# # We want to build zfs only for i386 and amd64 by default for now. # .if ${MACHINE} == "amd64" || ${MACHINE} == "i386" MKZFS?= yes .endif
しかし、MKDTRACEはどこの時点でnoにされているのか。grepをかけてみた。
ヒットしたファイルの一つであるshare/mk/bsd.own.mkを確認すると、以下の記述があった。
# # MK* options which default to "no". Note that MKZFS has a different # default for some platforms, see above. # _MKVARS.no= \ MKBSDGREP MKBSDTAR \ MKCATPAGES MKCRYPTO_RC5 MKDEBUG \ MKDEBUGLIB MKDTRACE MKEXTSRC \ MKMANZ MKOBJDIRS \ MKLLVM MKPCC \ MKPIGZGZIP \ MKREPRO \ MKSOFTFLOAT MKSTRIPIDENT \ MKUNPRIVED MKUPDATE MKX11 MKZFS .for var in ${_MKVARS.no} ${var}?=no .endfor
ああ、列挙されているビルド変数を"no"にしているのね。ここまでのところで、installmodulesしてもモジュールがインストールできないのはビルド変数MKDTRACEが"no"だったからということがわかる。
ということで再度build.shをかけてみる。
./build.sh -a i386 -O ../obj -T ../tools -V MKDTRACE=yes installmodules=/
これまで失敗していた「modload dtrace」を実行してみると、今度は成功した。
「modload sdt」も「modload fbt」も同様に成功した。
公式ブログで述べられているデバイスファイル作成も成功。
mkdir /dev/dtrace mknod /dev/dtrace/dtrace c dtrace 0
プルーブの一覧を表示するために「dtrace -l」を実行したが、これが失敗する。(dtrace: Command not found.)
build.shでdistributionしてからinstallをしていなかった事に気づく。よって、以下のコマンドを実行する。
./build.sh -a i386 -O ../obj -T ../tools -V MKDTRACE=yes install=/
実行後、rehashし、再度dtraceコマンドを実行する。今度は無事にprobeの情報を出力することができた。
まとめ
NetBSD6.0でdtraceの環境を作るためには以下の手順が必要。
(ソースが/usr/src以下に、objディレクトリは/usr/objに、ツールチェインが/usr/toolsにあるという前提で記載する。)
(1)ツールチェインを作成する。
./build.sh -a i386 -O ../obj -T ../tools tools
(2)カーネルをビルドする。ビルドする際、カーネルコンフィグファイルに以下の3記述があることを確認する。(コメントアウトされていないか要確認。なければ追加)
options INSECURE options KDTRACE_HOOKS options MODULAR
(3)distributionをビルドする。
./build.sh -a i386 -O ../obj -T ../tools -V MKMODULAR=yes -V MKDTRACE=yes distribution
(4)(3)でビルドしたブツをインストールする。
./build.sh -a i386 -O ../obj -T ../tools -V MKDTRACE=yes install=/
(5)(3)でビルドされたモジュールをインストールする。
./build.sh -a i386 -O ../obj -T ../tools -V MKDTRACE=yes installmodules=/
(6)モジュールをロードする。
modload solaris modload dtrace modload sdt modload fbt
(7)デバイスファイルの作成を行う。
mkdir /dev/dtrace mknod /dev/dtrace/dtrace c dtrace 0
これでdtrace -lしてプルーブの一覧が表示されれば成功です。
公式ブログでは端折っている箇所があり、苦労しましたが、いろいろと勉強になりました。