into the void

ソフトウェアに関する雑多な調査日記

Debian/UbuntuのMultiArch対応 〜/lib/x86_64-linux-gnuとか/lib64とか〜

gdbでlibcの中の関数までバックトレースしたかったり、valgrindでメモリリーク調査をしたかったりすると、libcのデバッグ版が必要になる。
PC Linuxなら、Debian系ならlibc6-debugをインストールしてやれば良いのだが、ARM上で組込み用のLinuxが動いているような環境では、パッケージでインストールされるファイルに相当するものを手で入れることになる。どのディレクトリにどんなファイルを入れれば良いのか把握していないといけないわけで、そこでMultiArch対応という仕組みの理解が求められる。

gdbやvalgrindはどうやってデバッグ版libcの場所を見つけるのか

libc6-debugをパッケージインストールすると、パッケージ内のファイルは/usr/lib/debug配下にコピーされる。
どうやら、gdbやvalgrindはデフォルトで/usr/lib/debugをデバッグ版ライブラリのサーチパスとして持っているらしい。
もちろんサーチパスの変更は可能で、gdbの場合は「set debug-file-directory」というコマンドでできる。valgrindの場合は、「--extra-debuginfo-path」オプションで設定できる。
https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
http://valgrind.org/docs/manual/manual-core.html

/usr/lib/debugの下に、オリジナルのライブラリと同じディレクトリ構成でライブラリファイルを置いてく必要がある。
例えば、/lib/x86_64-linux-gnu/libc-2.15.soの場合、/usr/lib/debug/lib/x86_64-linux-gnu/libc-2.15.soという感じ。
/usr/lib/debugの直下に/usr/lib/debug/libc-2.15.soという形で置いておいても認識してくれないので注意。

このlibの後ろのx86_64-linux-gnuってなんだというのがメインの話題。

MultiArch tuple

32bit互換の64bit CPUが出てから、同じシステム上で32bitアプリと64bitアプリの両方が動く環境が求められるようになった。
Linuxの場合、システムライブラリは/lib、/usr/libに配置される慣習なので、32bit版はこれまで通り/libに、64bit版は/lib64という形で配置されていた。
これはIntelの32bit、64bitを区別するぶんには機能するけるども、ABIの違いは表現できていないので将来ABIが変わった場合にはどうするんだとか、IA-64とかは64bitのライブラリだけど32bitじゃないから/libに配置されるわけでわかりづらいぞ、ARMとかMIPSとか別のCPUアーキテクチャでも32bitと64bitがあるけどどうするんだという、課題があって廃止になった。
で、代わりに使われるようになったのが/lib//というディレクトリ構成。の部分には、ABIを識別する文字列がはいる。x86_64-linux-gnuの場合、CPUがx86_64で、カーネルLinuxの環境用にGNUにて定められたABIという意味になる。x86_64-kfreebsd-gnuの場合は、カーネルFreeBSD用のABIという意味。arm-linux-gnueabiの場合は、ARM CPU用にGNUで定められたEABI。
もともとはGNUツールチェインなんかで使われてたtuple表現をそのまま使おうとしたらしいけども、ライブラリが対応するABIを表現するには曖昧だったり、不適切だったりする場合があって、一部はそのまま使って、一部は表現を変えているらしい。

tupleの一覧は下記にまとめられている。
https://wiki.debian.org/Multiarch/Tuples

その他の参考サイト。
https://wiki.ubuntu.com/MultiarchSpec

ローダとの関連

結局どのライブラリを使うかというのは、ローダが決めることなので、ABIごとにそれ用のローダがある。逆に言うとローダさえ決まっていれば使われるライブラリが決まる。どのローダを使うかは、コンパイル時に実行ファイルに埋め込まれる。glibcがサポートするABIごとのロードの一覧がここにまとめられている。
https://sourceware.org/glibc/wiki/ABIList
https://wiki.linaro.org/RikuVoipio/LdSoTable