libsmbclient + nss_wins の問題 (3)
謎は解けた。
と謎を追ってきたのですが,非 static
な関数があたかも static
定義な関数のように振る舞っていたのは,リンカのフラグに -Bsymbolic-functions
が指定されていた(on Ubuntu Hardy 8.04)ためでした。-Bsymbolic-functions
については ld 2.18 の -Bsymbolic オプションを使うと共有ライブラリ内でシンボルをローカルバインドできる - daily dayflower を参照してください。
一応背景
Samba の lib/debug.c
のコードの抜粋を再掲します。
/* source/lib/debug.c: */ /******* snip snip snip *******/ static int debug_all_class_hack = 1; int *DEBUGLEVEL_CLASS = &debug_all_class_hack; /******* snip snip snip *******/ int debug_add_class(const char *classname) { void *new_ptr; /******* snip snip snip *******/ new_ptr = DEBUGLEVEL_CLASS; if (DEBUGLEVEL_CLASS == &debug_all_class_hack) { /* Initial loading... */ new_ptr = NULL; } new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1); if (!new_ptr) return -1; DEBUGLEVEL_CLASS = (int *)new_ptr; /******* snip snip snip *******/ }
DEBUGLEVEL_CLASS
も debug_add_class()
も非 static
なシンボルです。
今回の状況は,libsmbclient.so と libnss_wins.so で各々このソースが読み込まれていることにあります。これまでは両者とも非 static
なので,共有ライブラリが読み込まれたときにごっそりといれかわっていました。
つまり(単純にいうと)-lsmbclient -lnss_wins
でビルドすると,両シンボルともに libsmbclient.so 由来のものになっていました。これなら問題ありません。
しかし,-Bsymbolic-functions
というオプションつきでビルドすると,libnss_wins.so 内から debug_add_class()
を呼び出した場合,libnss_wins.so 内の debug_add_class()
が呼び出されることになります。すると,変数 DEBUGLEVEL_CLASS
は libsmbclient.so 由来ですが static
変数の debug_all_class_hack
は libnss_wins.so 由来になってしまうので,実は初期化されていないのに,初期化済みとみなされ,不正な realloc()
をしてしまうのです。
まるでわからない説明だと思いますが,詳しくお知りになりたい方は上記にあげた3つの記事を読んでみてください。
なんで Samba が -Bsymbolic-functions
つきでビルドされたか
それは krb5-dev の krb5-config --libs
を実行すると -Wl,-Bsymbolic-functions
が出力されるからです。
なんで krb5-config
の LDFLAGS
が -Wl,-Bsymbolic-functions
になっているのか
それは dpkg-buildpackage
の LDFLAGS
のデフォルトが -Wl,-Bsymbolic-functions
だからです。
ということで
どうみても Ubuntu Hardy の dpkg
のバグです。ありがとうございます。
ちなみに Upstream な Debian の dpkg
では,Ubuntu のを参考にして LDFLAGS のデフォルトを設定したあとにやっぱそれまずいわと取り下げてます。やれやれ。
いちおう dpkg@Ubuntu の launchpad に報告をあげておきましたが,どうなることやら。