今年の夏は記録的な暑さで、
人間さまは9月に入っても続く猛暑でバテバテですが、
互換性を重視したバージョンアップの際に特に気を使うのが共有ライブラリ
WindowsやMacOSのような、
今回は、
共有ライブラリの基礎知識
実際のトラブル例を紹介するまえに、
Linuxの場合、
共有ライブラリは
これらライブラリは/libディレクトリや/usr/
たとえば、
% ls /usr/lib/libz.* /usr/lib/libz.a* /usr/lib/libz.so@ /usr/lib/libz.so.1@ /usr/lib/libz.so.1.2.3*
上記のうち、
静的ライブラリは、
% ar t /usr/lib/libz.a adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o zutil.o inflate.o infback.o inftrees.o inffast.o
それぞれのオブジェクトファイルが提供する機能はnmコマンドで調べることができます。
% nm -A /usr/lib/libz.a /usr/lib/libz.a:adler32.o:00000000 T adler32 /usr/lib/libz.a:adler32.o:00000270 T adler32_combine /usr/lib/libz.a:compress.o:000000b0 T compress /usr/lib/libz.a:compress.o:00000000 T compress2 /usr/lib/libz.a:compress.o:00000160 T compressBound /usr/lib/libz.a:compress.o: U deflate /usr/lib/libz.a:compress.o: U deflateEnd /usr/lib/libz.a:compress.o: U deflateInit_ /usr/lib/libz.a:crc32.o:00000010 T crc32 /usr/lib/libz.a:crc32.o:000002a0 T crc32_combine /usr/lib/libz.a:crc32.o:00000000 r crc_table ...
静的ライブラリは、
上記リストで00000000や00000270と表示されているのは、
静的ライブラリが参照されるのはソースコードのコンパイル時であるのに対して、
共有ライブラリでは、
% nm -A /usr/lib/libz.so.1.2.3 /usr/lib/libz.so.1.2.3:000098a5 t .L147 /usr/lib/libz.so.1.2.3:00009929 t .L155 /usr/lib/libz.so.1.2.3:0000bb96 t .L156 ... /usr/lib/libz.so.1.2.3:000017a0 T adler32 /usr/lib/libz.so.1.2.3:00001a30 T adler32_combine /usr/lib/libz.so.1.2.3:0000ff20 r base_dist /usr/lib/libz.so.1.2.3:00010020 r base_length ...
共有ライブラリを利用する場合、
このように作成されたバイナリファイルは、
言葉だけで説明するのはわかりにくいと思うので、
libz が提供するcrc32()という機能を使う、
#include <zlib.h>
int main() {
crc32(0,0,0);
return 0;
}
このコードを静的ライブラリを使うようにコンパイルするには、
% gcc -static sample.c -lz
この結果、
% ls -l a.out -rwxr-xr-x 1 kojima users 671,785 9月 7日 20:11 a.out*
作成されたバイナリファイルには、
% nm a.out 080a581c t .L100 080a179e t .L101 080a5809 t .L101 ... 0806a470 t compute_offset 080506f0 W connect 080c8840 b connected 08048270 T crc32 08048500 T crc32_combine 080a6820 r crc_table 080689d0 t critical_factorization ....
それぞれの機能に付いている8ケタの数字はそれぞれの機能を呼び出す際のアドレスで、
一方、
% gcc sample.c -lz % ls -l a.out -rwxr-xr-x 1 kojima users 4,447 9月 7日 20:16 a.out*
この実行可能バイナリには、
% nm a.out
08049554 d _DYNAMIC
08049628 d _GLOBAL_OFFSET_TABLE_
08048538 R _IO_stdin_used
w _Jv_RegisterClasses
08049544 d __CTOR_END__
...
08049648 b completed.5744
U crc32
08049640 W data_start
0804964c b dtor_idx.5746
08048420 t frame_dummy
08048448 T main
一方、
% ldd a.out
linux-gate.so.1 => (0xffffe000)
libz.so.1 => /usr/lib/libz.so.1 (0xb76f1000)
libc.so.6 => /lib/libc.so.6 (0xb75ae000)
/lib/ld-linux.so.2 (0xb7737000)
このように、
例に示したように、
ライブラリに何らかの問題が見つかって修正版が公開された場合、
このようなメリットのため、
先に紹介したように、
このような問題を防ぐために、
そのルールは、
共有ライブラリがこのバージョン付けのルールに従う限り、
Linuxの共有ライブラリでは、
先に紹介したlibzの場合、
この共有ライブラリに対して/usr/
libz.
共有ライブラリのこのバージョン付けルールは、
Heimdalパッケージの共有ライブラリ問題
Heimdalは、
Plamo Linuxでは、
ところが、
先に解説したように、
先に紹介したように、
test.
int main() {
return 0;
}
このソースコードをビルドする際に、
% ldd /usr/lib/libsmbclient.so.0
....
libgssapi.so.2 => /usr/heimdal/lib/libgssapi.so.2 (0xb75f1000)
libheimntlm.so.0 => /usr/heimdal/lib/libheimntlm.so.0 (0xb75ec000)
libkrb5.so.25 => /usr/heimdal/lib/libkrb5.so.25 (0xb753f000)
libhx509.so.3 => /usr/heimdal/lib/libhx509.so.3 (0xb7509000)
....
一方、
% ls -l /usr/heimdal/lib/libkrb5* -rw-r--r-- 1 root root 578,998 6月 17日 16:00 /usr/heimdal/lib/libkrb5.a -rwxr-xr-x 1 root root 1,155 6月 17日 16:00 /usr/heimdal/lib/libkrb5.la* lrwxrwxrwx 1 root root 17 9月 7日 23:04 /usr/heimdal/lib/libkrb5.so -> libkrb5.so.26.0.0* lrwxrwxrwx 1 root root 17 9月 7日 23:04 /usr/heimdal/lib/libkrb5.so.25 -> libkrb5.so.25.0.0* -rwxr-xr-x 1 root root 860,213 3月 22日 20:10 /usr/heimdal/lib/libkrb5.so.25.0.0* lrwxrwxrwx 1 root root 17 9月 7日 23:04 /usr/heimdal/lib/libkrb5.so.26 -> libkrb5.so.26.0.0* -rwxr-xr-x 1 root root 481,470 6月 17日 16:00 /usr/heimdal/lib/libkrb5.so.26.0.0*
ところが、
% gcc test.c -lsmbclient /usr/heimdal/lib/libkrb5.so.25: undefined reference to `bswap16' /usr/heimdal/lib/libkrb5.so.25: undefined reference to `socket_get_port' /usr/heimdal/lib/libkrb5.so.25: undefined reference to `strlcat' /usr/heimdal/lib/libkrb5.so.25: undefined reference to `bswap32' ... collect2: ld はステータス 1 で終了しました
あれれ、
% nm /usr/heimdal/lib/libkrb5.so.25 | grep -C3 bswap16
00071200 t bindText
00049700 t bind_principal
00070650 t blobReadWrite
U bswap16
U bswap32
000678b0 t btreeNext
00067a10 t btreePrevious
libkrb5.
% ldd /usr/heimdal/lib/libkrb5.so.25
linux-gate.so.1 => (0xffffe000)
libhx509.so.4 => /usr/heimdal/lib/libhx509.so.4 (0xb778f000)
libwind.so.0 => /usr/heimdal/lib/libwind.so.0 (0xb7767000)
libcrypto.so.0.9.8 => /usr/lib/libcrypto.so.0.9.8 (0xb7632000)
libasn1.so.8 => /usr/heimdal/lib/libasn1.so.8 (0xb75b9000)
libcom_err.so.2 => /lib/libcom_err.so.2 (0xb75b5000)
libroken.so.18 => /usr/heimdal/lib/libroken.so.18 (0xb75a3000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0xb7572000)
libdl.so.2 => /lib/libdl.so.2 (0xb756e000)
libresolv.so.2 => /lib/libresolv.so.2 (0xb755a000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb7541000)
libc.so.6 => /lib/libc.so.6 (0xb73fd000)
libcom_err.so.1 => /usr/heimdal/lib/libcom_err.so.1 (0xb73f9000)
/lib/ld-linux.so.2 (0xb78ad000)
これらの共有ライブラリそれぞれについて、
% nm /usr/heimdal/lib/libroken.so.18.1.0 | grep -C3 bswap16
U readdir64@@GLIBC_2.2
U realloc@@GLIBC_2.0
0000b290 T rk_asnprintf
000040c0 T rk_bswap16
00004090 T rk_bswap32
0000e970 T rk_cgetent
0000df30 T rk_cgetstr
あれれ、
% nm usr/heimdal/lib/libroken.so.18.1.0 | grep -C3 bswap16
00003b80 T base64_decode
00003cd0 T base64_encode
U bind@@GLIBC_2.0
00003e40 T bswap16
00003e10 T bswap32
000103e0 d bytes_short_units
00010400 d bytes_units
おかしいなぁ、
Linuxの共有ライブラリの仕組みでは、
このままでは、
当初は、
さてどうしたものか…、
% ldd /usr/heimdal/lib/libkrb5.so.25
....
libhx509.so.4 => /usr/heimdal/lib/libhx509.so.4 (0xb7638000)
libroken.so.17 => /usr/heimdal/lib/libroken.so.17 (0xb744b000)
....
% ldd /usr/heimdal/lib/libkrb5.so.26
....
libhx509.so.5 => /usr/heimdal/lib/libhx509.so.5 (0xb77fd000)
libroken.so.18 => /usr/heimdal/lib/libroken.so.18 (0xb75ad000)
....
この環境ならば、
% gcc test.c -lsmbclient
% ldd a.out
linux-gate.so.1 => (0xffffe000)
libsmbclient.so.0 => /usr/lib/libsmbclient.so.0 (0xb760c000)
...
libkrb5.so.25 => /usr/heimdal/lib/libkrb5.so.25 (0xb7383000)
libroken.so.17 => /usr/heimdal/lib/libroken.so.17 (0xb6fb6000)
....
一方、
GCCのリンカオプション問題
Plamo-4.
これはGCCのリンカの仕様の問題で、
この動作はオプションで変更可能で、
GCCの場合、
先の test.
% gcc -Wl,--as-needed test.c -lsmbclient
% ldd a.out
linux-gate.so.1 => (0xffffe000)
libc.so.6 => /lib/libc.so.6 (0xb7701000)
/lib/ld-linux.so.2 (0xb7877000)
smbclientライブラリをリンクするように指示されたものの、
libc.
このオプションを指定するとリンカの仕事が多少増えますが、
本来、
