printf アクション実装の特定
VM 内部コードの解析で、printf() 系の処理がおそらくユーザ空間で実施されているだろうことは見当が付いたけど、本当にユーザ空間で処理されているか確認をしてみる。
dtrace コマンドのソースが usr/src/cmd/dtrace/dtrace.c にあることはすぐに見当が付くけど、どうもこれだけでは実装が足りない気が。
御多分に漏れず、処理の大半が共有ライブラリに追い出されているんだろう、という思惑を元に、共有ライブラリの参照状態を確認してみることに。
AMD64 環境で確認してみたところ:
$ ldd `which dtrace` libc.so.1 => /lib/libc.so.1 libm.so.2 => /lib/libm.so.2
あれ?これだけ?では SPRAC 環境も見てみるか……
$ ldd /usr/sbin/dtrace libc.so.1 => /lib/libc.so.1 libm.so.2 => /lib/libm.so.2 /platform/SUNW,Sun-Fire-V210/lib/libc_psr.so.1
あら、こちらもだ。うーむ、どういうことだ?
こうなったら truss 先生にお願いしてみよう。AMD64 環境だと:
execve("/usr/sbin/amd64/dtrace", 0x0804701C, 0x08047034)
32bit x86 環境だと:
execve("/usr/sbin/i86/dtrace", 0x08047C68, 0x08047C74)
なるほど、そういうことか。じゃ、SPARC 環境も:
execve("/usr/sbin/sparcv9/dtrace", 0xFFBFFCA4, 0xFFBFFCBC)
了解了解。つまり、最初に起動されるコマンドは ISA(instruction set architecture)情報に応じて実処理を行なうコマンドの切り替えだけをやっているので、共有ライブラリが不要、という按配なのね。
で、実処理を行なうコマンドを確認すると、libdtrace.so を必要としている模様。このライブラリのソースは usr/src/lib/libdtrace 配下に(メインは common 配下)。あぁ、この分量なら納得だ。
表示系の処理をやっているのは usr/src/lib/libdtrace/common/dt_printf.c あたりか。
ちなみに、dtrace コマンドの Makefile を構成する usr/src/cmd/dtrace/Makefile.com を見ると:
LDLIBS += -ldtrace -lproc -lctf -lelf
libdtrace.so を使っていることがすぐ分かりました ..... orz