2 インストール

この章の目次へ

2.1 背景

ここに示す移行手順の目的は、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)の項を見てく ださい。

2.2 始める前に --- 注意と警告

2.3 必要なものは、、、

以下のパッケージは、 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 という名前になっています。以下に示してい るバージョンよりも新しいバージョンを入手した場合、必ずリリースノートに 目を通してください。それら新しいバージョンではインストールの方法が変っ ているかも知れません。

2.4 ファイルシステムの再構成

えーっと、あらかじめ注意しておきますが、以下で私が `削除する' と言った ら、自動的に `バックアップしてから削除する' と読みかえてください :-)な お、これらの指示は ELF で苦しんだことの無い人々向けのものです。すでに 苦しんだことのある人は、適当に読み換えるに充分な知性を備えていることで しょうから。さあ始めましょう。

  1. HDD を / パーティションと /usr パーティションに分け ている場合、多少の注意が必要です。起動時に /usr がマウントさ れる以前に動くプログラムを全てチェックするか /usr が読み出せ なくなったらどうなるか試してみてください。そして、それらのプログラムが 必要とするライブラリは /lib-aout に置きます。 実はそれほど難しい話ではありません。単に、
    $ ldd /sbin/* /bin/* /etc/* >/tmp/list.txt
    
    とやって、/tmp/list.txt を調べ、実行可能プログラムではないファ イルについてのエラーは無視し、どのライブラリが使われているかメモしてお きます。それらのライブラリがルートパーティションに必要となるライブラリ です。このリストは保存しておきましょう。
  2. a.out 関係のファイルを移すための新しいディレクトリを作ります。

    mkdir -p /usr/i486-linuxaout/bin
    mkdir -p /usr/i486-linuxaout/include
    mkdir -p /usr/i486-linuxaout/lib
    mkdir /lib-aout
    

  3. ソースコードを置いているディレクトリで、動的リンカ ld.so-1.7.3 パッ ケージを展開して、展開された直後の ld.so-1.7.3/instldso.sh ス クリプトを読んでみましょう。もし、本当に標準的なシステムを使っているな ら、sh instldso.sh を実行するだけでインストールすることもでき ますが、もし何か標準的でないものを使っているなら、手動でインストールす る必要があります。`何か標準的でないもの'とは、、
    • シェルとして zsh を使っている(zsh のあるバージョンでは $VERSION という変数を定義しており、それが instldso.sh を混乱させます)
    • /lib/elf から /lib へシンボリックリンクを張っている (こうすべき理由はないのですが、もし ELF の開発を追いかけていたなら、こ うしているかも知れません)
    などです。 /etc/ld.so.conf を修正して、/usr/i486-linuxaout/lib を加え(必要ならば /lib-aout も加え)、/sbin/ldconfig -v を再実行して、新しいディレクトリを探しているかチェックします。
  4. libc と libm 以外のすべての a.out 形式のライブラリを探し出し、 /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 は全てのプログラムを動かすためにまだ必要です。
  5. もし /usr/lib/ldscripts ディレクトリがあれば削除します。
  6. /usr/bin にある(ld86as86 以外の)全ての ldas のコピーを削除します。
  7. あるバージョンの GNU tar はシンボリックリンクされたファイルを扱う際に 問題が生じることが知られています。そのため、libc のイメージファイルを インストールする前に、/usr/include へ行っていくつかのファイルを削除す る必要があるかも知れません。 これは面倒くさい仕事ですが、/usr/include にのみインストールさ れ、対応する C ライブラリがないパッケージ(例えば ncurses) も いくつかあるので仕方ありません。まず /usr/include 以下をバックアップし て、tar tzf して、あらかじめどういうファイルが入っているか確 認しましょう。実際にファイルが書きこまれるディレクトリを削除した上で、 libc-5.0.9.bin.tar.gz をルートディレクトリから展開します。
  8. 以上で、ELF の実行形式を動かすために必要なファイルを全てインス トールできました。医学の専門家によると、VDU ワーカーは定期的に休憩を取っ てスクリーンの前から離れるべきだそうです。ちょうどいいタイミングですか ら、ここで一休みしましょう。
  9. さぁ、いよいよ ELF プログラムをインストールします。まず binutuils パッケージをインストールします。 tar -xvzf binutils-2.5.2l.17.bin.tar.gz -C / とするのが最善の方法の一つです。
  10. /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

2.5 よくあるエラー

この節では、皆さんから寄せられた問題を集めようと思っています。あらかじ め連絡していただければ、お名前は公表しません :-)

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 を使いましょう。

次の章へ , 前の章へ

この章の目次へ, この文書の目次へ

この文書の最初へ , この章の最初へ