2007-11-26

cf.sourceforge.jp続き (dylibの謎)

10.5だから動かないというわけではなく、

DYLD_LIBRARY_PATH=/opt/local/lib

って環境変数を設定してたのが原因でした。なんか作業中に設定してしまった模様。

同じ名前で中身が違うshared libraryがDYLD_LIBRARY_PATHで先に読まれてしまったのが原因。今回の場合はDYLD_FALLBACK_LIBRARY_PATHで足らなかったら読むようにすれば解決。


だけだと面白くないですね。追ってみます。

syscallをおっかけられるktraceで見てみると

...

いやさ10.5ならktraceじゃなくてdtrace!

sudo dtrace -n syscall::open"*":entry'/execname == "Vim"/{printf("%s", copyinstr(arg0))}'

こんなんでopen syscallの第一引数を逐次表示。よくわからんスクリプトだなぁと思ってましたが、awkと思えばスッキリ。


DYLD_LIBRARY_PATH=/opt/local/lib を指定してると

CPU ID FUNCTION:NAME
1 17600 open:entry /opt/local/lib/libncurses.5.dylib
1 17600 open:entry /opt/local/lib/libiconv.2.dylib
1 17600 open:entry /opt/local/lib/libintl.8.dylib
1 17600 open:entry /opt/local/lib/libmigemo.1.dylib
1 17600 open:entry /System/Library/Frameworks/Python.framework/Versions/2.3/Python
1 17600 open:entry /opt/local/lib/libruby.dylib
1 17600 open:entry /opt/local/lib/libz.1.dylib
1 17600 open:entry /opt/local/lib/libxslt.1.dylib
1 17600 open:entry /opt/local/lib/libPng.dylib


DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib を指定していると

0 17600 open:entry /opt/local/lib/libncurses.5.dylib
0 17600 open:entry /opt/local/lib/libiconv.2.dylib
0 17600 open:entry /opt/local/lib/libintl.8.dylib
0 17600 open:entry /opt/local/lib/libmigemo.1.dylib
0 17600 open:entry /System/Library/Frameworks/Python.framework/Versions/2.3/Python
0 17600 open:entry /opt/local/lib/libruby.dylib


ほらこの通り。って、なんか全然足らないですね。carbonげなdylibとかまったく読まれてない。DYLD_PRINT_LIBRARIES= も付けて実行すると読み込まれたすべてのdylibが表示されるので、dtraceでもここまで表示されて欲しい。

syscall::"*":entryで見てみるとstatで/usr/lib/libobjc.A.dylibとか触ってる。システム系のshared libraryはsystem callで読まれないのかなぁ、とか一瞬思ってしまいましたが、こりゃcacheですね。man dyldで発見。

DYLD_SHARED_REGION=avoid DYLD_FALLBACK_LIBRARY_PATH=/opt/local/lib なら

0 17600 open:entry /opt/local/lib/libncurses.5.dylib
0 17600 open:entry /opt/local/lib/libiconv.2.dylib
0 17600 open:entry /opt/local/lib/libintl.8.dylib
0 17600 open:entry /opt/local/lib/libmigemo.1.dylib
0 17600 open:entry /System/Library/Frameworks/Python.framework/Versions/2.3/Python
0 17600 open:entry /opt/local/lib/libruby.dylib
0 17600 open:entry /usr/lib/libobjc.A.dylib
0 17600 open:entry /usr/lib/libSystem.B.dylib
0 17600 open:entry /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CarbonSound.framework/Versions/A/CarbonSound
0 17600 open:entry /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/CommonPanels.framework/Versions/A/CommonPanels
...


解決! でも/opt/local/lib/libncurses.5.dylibとか使ってる状態で、さらにこれやってもopenで読まれるのはなんでだろう。何かcacheされる条件があるんかな。

ということでdtraceは面白いという話でした。awkみたいなスクリプト以外にrubyとかで書けたら便利かも。あとhookして挙動いじれたり。openしたつもりが別のファイルをopenしてたりとか。system callの中身をrubyで書いたりとか。jailな感じ。