ここに示す移行手順の目的は、a.out と ELF の双方をコンパイルして動かす
ことのできるシステムを構築することです。そのためには双方のプログラムが
適切な共有ライブラリを見つけられなければなりません。このためには、他の
いくつかのシステムがやっているように、単純に `/lib
と
/usr/lib
そしてコンパイル時に指定されたディレクトリを全て探す'
という方法よりも多少なりともスマートな方法が必要です。
linux でライブラリを探すのに使われるプログラムは /lib/ld.so
です。コンパイラもリンカも出力するプログラムにはライブラリへの絶対パス
は埋めこみません。その代りに、必要なライブラリ名と ld.so
への
絶対パスを埋めこんでおき、実行時に ld.so
に適切なライブラリを
選択させるようにしています。これがきわめて重要な機能になります -- すな
わち、ld.so
にライブラリを探すべき新しいディレクトリを正しく
教えてやれば、プログラムをコンパイルしなおさなくても ライブラ
リを別のディレクトリへ移動させることが可能だ、ということです。この点が、
以下に示すディレクトリの入れかえ操作の鍵になります。
上記から導かれる結論として、ld.so
を削除したり移動させたりす
れば、動的リンクを使っているプログラムは全て機能しなくなる、
ということがわかります。これは良くないこと(Bad Thing)である、と一般に
考えられています。
ELF には ELF 用の動的ローダーが用意されています。これは
/lib/ld-linux.so.1
で、ELF プログラムに対して ld.so
とまっ
たく同じ機能を果します。ld-linux.so.1
も a.out 用の ld.so
と
同じ設定ファイルとプログラム(ldd
, ldconfig
,
/etc/ld.so.conf
)を利用します。
ですから、基本的な計画としては、ELF 用の開発環境(コンパイラ、インクルー
ドファイル、ライブラリ)を、今 a.out 用の環境がある
/usr/{bin,lib,include}
に置き、a.out 用の環境を
/usr/i486-linuxaout/{bin,lib,include}
に移す、ということにな
ります。/etc/ld.so.conf
にライブラリが見つかるはずの場所を全
て書いておけば、ldconfig
は ELF と a.out を自動的に区別します
ので、適切なライブラリを選択することができます。ライブラリを置くべき場
所には多くの例外があります;詳しくは次の警告(caveats)の項を見てく
ださい。
/usr
や /usr/lib
を /
パーティション
とは違うパーティションに取っている場合は特に注意してください。
そのような場合、/bin
と /sbin
にあるプログラムが使っ
ているライブラリをチェックして、それらをルートパーティションのどこか、
例えば /lib-aout
、に置いておく必要があります。この点に関して
は後に適切なところでもう一度触れることにします。
/lib/elf
に ELF
用のライブラリ(通常は libc.so.4 など)があるかも知れません。これらのラ
イブラリを使うアプリケーションは再コンパイルする必要があります。その上
でこのディレクトリは削除しましょう。もはや/lib/elf
ディレクト
リは不要です。このディレクトリは ELF の開発時のためのもので、Slackware
のインストール時の標準ディレクトリになるなんてことはないでしょう。
ld.so
を使っていません。ですか
ら、それらの使っているライブラリは移動することができません。この点は問
題になるかも知れないし、ならないかも知れません。ldd
を使って、ど
ういうライブラリを使っているのかチェックしてください。もし使っているの
が libc.so.4
と/あるいは libm.so.4
だけならば、これらのライ
ブラリは /lib
に残されるので問題はありません。もし X 関連のラ
イブラリで、shape や form についてのライブラリのみの場合も大丈夫です。
ld.so
を使わないくらい古いプログラムでは、ずいぶん古いバージョ
ンの X のライブラリを使うようにコンパイルされているはずなので、当時の
X のライブラリのメジャー番号もディレクトリの位置も今のものとは違ってい
ますから。
もし動かせない a.out ライブラリと ELF ライブラリが同じバージョン番号で、
同じ場所に必要な場合、ELF ライブラリをどこか別の場所に移して、そのディ
レクトリを /etc/ld.so.conf
に書いておきます。
もし使っているシステムがきわめて古くて、ファイル名に日付が入っているよ
うな共有ライブラリを使っているなら、あなたは明らかに Linux God(tm) の
一人であり、この点に関しては私に正しい方法を教えてくださいますようお
願いします :-) 回答は、この HOWTO のタイトルにあるアドレスまで。
/sbin/
何たら' を使うようになっているのに、自分のシ
ステムには /sbin
ディレクトリが無い場合、それらのプログラムは
/bin
か /etc
にあるはずです。
以下のパッケージは、 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ や ftp://sunsite.unc.edu/pub/Linux/GCC/ から入手可能です。両サイト とも多くの場所にミラーされていますので、可能なかぎり近くにあるミラーサ イト[日本ならば ftp://ftp.iij.ad.jp/pub/linux/sunsite/GCC/ や ftp://ftp.spin.ad.jp/pub/linux/sunsite.unc.edu/GCC/ など ] から探してください。その方があなたにとっても、みんなに取っても結局速 く入手できることになります。
以下に示すパッケージ(リストにあがっているバージョンかより新しいもの)が
必要です。これらをダウンロードして、それぞれに附属のリリースノートを読
んでみてください:リリースノートはたいてい
release.
packagename という名前になっています。以下に示してい
るバージョンよりも新しいバージョンを入手した場合、必ずリリースノートに
目を通してください。それら新しいバージョンではインストールの方法が変っ
ているかも知れません。
ld.so-1.7.3.tar.gz
--- 新しい動的リンカ
libc-5.0.9.bin.tar.gz
--- ELF 形式の共有ライブラリの実行イ
メージで、C 用のライブラリとその仲間たち(m(数学ライブラリ), termcap,
gdbm などなど)と対応する静的ライブラリ、これらを使ってプログラムをコン
パイルするのに必要なインクルードファイルなどが入っています。
gcc-2.7.0.bin.tar.gz
--- ELF 対応の C コンパイラ。新しいディ
レクトリ・レイアウトを理解する a.out 対応の C コンパイラも入っています。
binutils-2.5.2l.17.bin.tar.gz
--- Linux 用にパッチをあてた
GNU のバイナリ操作用プログラム。gas
, ld
, strings
などが
入っています。C コンパイラが機能するためには必須のプログラムです。
えーっと、あらかじめ注意しておきますが、以下で私が `削除する' と言った ら、自動的に `バックアップしてから削除する' と読みかえてください :-)な お、これらの指示は ELF で苦しんだことの無い人々向けのものです。すでに 苦しんだことのある人は、適当に読み換えるに充分な知性を備えていることで しょうから。さあ始めましょう。
/
パーティションと /usr
パーティションに分け
ている場合、多少の注意が必要です。起動時に /usr
がマウントさ
れる以前に動くプログラムを全てチェックするか /usr
が読み出せ
なくなったらどうなるか試してみてください。そして、それらのプログラムが
必要とするライブラリは /lib-aout
に置きます。
実はそれほど難しい話ではありません。単に、
$ ldd /sbin/* /bin/* /etc/* >/tmp/list.txt
とやって、/tmp/list.txt
を調べ、実行可能プログラムではないファ
イルについてのエラーは無視し、どのライブラリが使われているかメモしてお
きます。それらのライブラリがルートパーティションに必要となるライブラリ
です。このリストは保存しておきましょう。
mkdir -p /usr/i486-linuxaout/bin
mkdir -p /usr/i486-linuxaout/include
mkdir -p /usr/i486-linuxaout/lib
mkdir /lib-aout
ld.so-1.7.3
パッ
ケージを展開して、展開された直後の ld.so-1.7.3/instldso.sh
ス
クリプトを読んでみましょう。もし、本当に標準的なシステムを使っているな
ら、sh instldso.sh
を実行するだけでインストールすることもでき
ますが、もし何か標準的でないものを使っているなら、手動でインストールす
る必要があります。`何か標準的でないもの'とは、、
$VERSION
という変数を定義しており、それが instldso.sh
を混乱させます)
/lib/elf
から /lib
へシンボリックリンクを張っている
(こうすべき理由はないのですが、もし ELF の開発を追いかけていたなら、こ
うしているかも知れません)
/etc/ld.so.conf
を修正して、/usr/i486-linuxaout/lib
を加え(必要ならば /lib-aout
も加え)、/sbin/ldconfig -v
を再実行して、新しいディレクトリを探しているかチェックします。
/usr/*/lib
から /usr/i486-linuxaout/lib
か
/lib-aout
へ移します。/lib/ld.so
は動かしたり、削除
したり、その他一切いじってはいけません!
一つのパーティションしか切っていない人なら、以下のコマンドで必要な作業
の大部分がまかなえるはずです。
[訳注:以下の mv [ lib*.so* except for libc.so* and libm.so*
] /usr/i486-linuxaout/lib の部分は libc.so* と libm.so* 以外の
lib*.so* を移動させる、という意味です。zsh だと似たような構文で実行で
きるそうですが、(t)csh, bash では手動で移動させる必要があると思います
]
cd /lib
mv *.o *.a *.sa /usr/i486-linuxaout/lib
mv [ lib*.so* except for libc.so* and libm.so* ] /usr/i486-linuxaout/lib
cd /usr/lib
mv *.o *.a *.so* *.sa /usr/i486-linuxaout/lib
cd /usr/X11R6/lib
mv *.o *.a *.so* *.sa /usr/i486-linuxaout/lib
cd /usr/local/lib
mv *.o *.a *.so* *.sa /usr/i486-linuxaout/lib
/lib
にある libc.so*
と libm.so*
、ld.so
以
外の、上記の各ディレクトリにある全てのライブラリファイルとオブジェクト
ファイル(*.o
) を移動させるまで、次に進んではいけません。
libc.so*
と libm.so*
は古いプログラムを動かすのに必要で
ld.so
は全てのプログラムを動かすためにまだ必要です。
/usr/lib/ldscripts
ディレクトリがあれば削除します。
/usr/bin
にある(ld86
と as86
以外の)全ての
ld
と as
のコピーを削除します。
/usr/include
にのみインストールさ
れ、対応する C ライブラリがないパッケージ(例えば ncurses) も
いくつかあるので仕方ありません。まず /usr/include 以下をバックアップし
て、tar tzf
して、あらかじめどういうファイルが入っているか確
認しましょう。実際にファイルが書きこまれるディレクトリを削除した上で、
libc-5.0.9.bin.tar.gz をルートディレクトリから展開します。
tar -xvzf
binutils-2.5.2l.17.bin.tar.gz -C /
とするのが最善の方法の一つです。
/usr/lib/gcc-lib/{i486-linux, i486-linuxelf,
i486-linuxaout}/
以下にあるファイルをバックアップした上で削除しま
す。そして、gcc-2.7.0.tar.gz をルートディレクトリから展開します。
これでお終い! 以下に簡単なテスト法を示します。
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-linux/2.7.0/specs
gcc version 2.7.0
$ gcc -v -b i486-linuxaout
Reading specs from /usr/lib/gcc-lib/i486-linuxaout/2.7.0/specs
gcc version 2.7.0
$ ld -V
ld version cygnus/linux-2.5.2l.14 (with BFD cygnus/linux-2.5.2l.11)
Supported emulations:
elf_i386
i386linux
i386coff
次は、伝統的な ``Hello, world'' プログラムを試してみましょう。オプショ ン無しの gcc だけでコンパイルしたり -b i486-linuxaout オプションを付け てコンパイルしたりして、a.out と ELF の両コンパイラが正しく設定されて いるかチェックしてください。
$ cat >hello.c
main() { printf("hello, world\n"); }
^D
$ gcc -o hello hello.c
$ file hello
hello: ELF 32-bit LSB executable i386 (386 and up) Version 1
$ ./hello
hello, world
$ gcc -o hello -b i486-linuxaout hello.c
$ file hello
hello: Linux/i386 demand-paged executable (QMAGIC) not stripped
$ ./hello
hello, world
この節では、皆さんから寄せられた問題を集めようと思っています。あらかじ め連絡していただければ、お名前は公表しません :-)
no such file or directory: /usr/bin/gcc
/usr/bin/gcc
はちゃんとありますよね?その場合、ELF 用の動的ロー
ダーである /lib/ld-linux.so.1
がインストールされていないか、
何らかの理由で読み出せなくなっています。インストールするか、前節の
step 3 のあたりをチェックしてください。
not a ZMAGIC file, skipping
このエラーメッセージは ldconfig
からのものです。古いバージョ
ンの ld.so を使っているようなので、新しいものを入手してください。前節
の step 3 をもういちど見てください。
bad address
ELF フォーマットのプログラムが全てこのエラーになるときは 1.3.0 から 1.3.3 までのカーネルを使っているはずです。1.3.3 以上にアップグレードす るか 1.2.x を使いましょう。