The Linux ELF HOWTO

Daniel Barlow <daniel.barlow@linux.org>

1996/07/14

こじまみつひろ <isle@st.rim.or.jp> (11/4)


この文書はあなたの Linux システムで ELF バイナリ形式のプログラムをコン パイルして動かすための方法をまとめたものです。この文書は大きく、(1)ELF とは何か、なぜ移行しなければならないか、(2)どうすれば ELF 形式が使える ようになるのか、(3)ELF にすれば何ができるのか、という 3 つの部分に分か れています。 私が研究にいそしんでいるフリをしている間、この文書は放ったらかしになっ ていましたが、最近 Linux 2.0 の情報を追加して全体をオーバーホールしま した。

注意: この文書はかなり以前に書かれたものなので、 いまどきの Linux 環境にはあてはまらない箇所があります。 (JF Project)

1. ELF とは何か? 簡単な紹介

2. インストール

3. プログラムの構築

4. ELF 用パッチとELF 化済みのプログラム

5. より詳しい情報

6. その他


1. ELF とは何か? 簡単な紹介

ELF(Executable and Linking Format)は元々 USL(Unix System Laboratories) で開発されたバイナリ形式で、現在は Solaris や System V Release 4 が採 用しています。 Linux がかって使っていた a.out 形式に比べて、ELF 形式は 柔軟性に富むので、GCC と C ライブラリの開発者たちは Linux の標準的なバ イナリ形式を ELF にしようと決定しました。

「柔軟性に富む」というのは、標準的なアプリケーションプログラマに 2 つ の利点を与えます。

このような利点に対して、ELF を使うと多少遅くなる、という反論もあります。 1% から 5% くらい遅くなるというのが通説ですが、実際のテストが示す結果 を見ると、その差は同時に起っているさまざまなノイズに隠されてしまう程度 のもののようです。TeX や Postscript のビューワ/プリンタを持っていれば、 SunSite などから speed.comp-1.0.tar.gz という ELF と a.out の 速度を比較した論文を入手して読むのもいいでしょう。

ELF 形式が遅くなるのは ELF のライブラリコードがポジションインデペンデ ントでなければならないことに由来します(コンパイル時の -fPIC オプションが意味することです)。ポジションインデペンデントであるため、 一つのレジスタをオフセット保持用に使わなけれなばならなくなります。その ため、変数を保存するのに使えるレジスタが一つ減ってしまいます。特に 80x86 CPU では一般的に使えるレジスタが元々不足しています。速度に差が出 るのは共有ライブラリのコードに限られていることに注意してください。アプ リケーションやカーネルでは a.out と ELF の間で速度差はありません。

1.1 ELF は何ではないか?

ELF 化すれば何ができるかについて、多くの誤解が広まっています。

SVR4 や Solaris のプログラムを動かすためのものではありません

ELF は SVR4 システムと同じ形式のバイナリの`容器'ですが、だからと言って、 ELF にすれば SVR4 用のプログラムが突然 Linux でも使えるわけではありま せん。この関係はディスクフォーマットと似ているでしょう -- Linux のプロ グラムを MSDOS や Minix のフォーマットのディスクに保存したり、その逆も 可能ですが、だからといってそれぞれのシステムが互いのプログラムを実行で きるわけではありません。

(そのプログラム自身に依存しますが)他の x86 Unix 用のプログラムを Linux で動かすことも可能かも知れませんが、この HOWTO では、そのための説明は 致しません。まず(tsx-11.mit.edu などにある)iBCS カー ネルモジュールについて調べることから始めましょう。

プログラムが小さくなるわけでも、速くなるわけでもありません。

ずっと簡単に共有ライブラリが作れるようになったので、複数のプログラム間 で共通しているコードをライブラリ化すれば、結果としてより小さなプログラ ムを作成すことも可能かも知れませんが、一般的に言って、同じコンパイラオ プションを指定してバイナリが a.out よりも小さくなったなら、たまたま運 が良かったか、コンパイラのバージョンが違うためでしょう。もし「速く」なっ たら、ちょっとびっくりです。共有ライブラリを活用してプログラムが小さく なったため、スワップが減ったり、より多くのメモリを利用できるようになっ たならば、速くなることもありえますが。

全てのバイナリを置き替える必要はありません

この文書の手順に従えば、ELF と a.out の双方をコンパイルして動かすシス テムを構築できます。新しいプログラムはデフォルトでは ELF 形式にコンパ イルされますが、これはコマンドラインスイッチで変更できます。ELFと a.out を同時に動かした場合、両方の C ライブラリを読みこまなければなら なくなるなど、多少メモリの使用効率は悪くなります。もっとも、この差は メモリを 6Mb 積んだマシンではほとんど気づかない程度だそうですので(8Mb のマシンではもっと気づきませんでした)、あまり気にすることも無いでしょ う。何しろ、Emacs や静的リンクされた Mosaic/Netscape といったメモリを 大食いするプログラムを毎日のように 使っているでしょ? :-)

トールキンとは関係ありません

少なくともこの文脈においては。

1.2 なぜ ELF へ移行すべきか

ELF を使えるようにシステムをアップグレードするのには、主に 2 つの 理由があります:まず第一に、上述したようにプログラムがずっと柔軟にでき ること。第二に、第一とも関連しますが、だれもがそうしようとしている(あ るいは既にそうした)から。将来の C ライブラリや GCC は ELF 用のみがリリー スされますし、それ以外のプログラムの開発者たちも ELF の方へ進むはずで す。

ELF の安定性に不安を感じている人々もいます(愉快な話ではありませんが、 当然のことです)。Linux の世界で ELF は 1994 年の夏から存在していました。 その後 1995 年の 5 月か 6 月ごろ一般に公開されました。現在では、致命的 な問題は存在しないでしょう。大きなバージョンアップをする時にしばしば起 きるように、きちんと動いているシステムを壊しかねないと感じている人もい るかも知れません。でも、このバージョンアップはもはや最先端の技術ではあ りません。開発用のシステムや他の人がコンパイルしたバイナリを動かしたい 場合では、ELF は必須のものになりつつあります。カーネルを v2.0 にバージョ ンアップする際に ELF へスイッチすることを考えてください。

1.3 ELF への移行の仕方

この HOWTO が最初に書かれた時には ELF へ移行する方法は、ここに述べ た方法一つしかありませんでした。今日では、高品質で簡単に新しいバージョ ンをインストールできるようなディストリビューションも存在します。あなた のマシンをお好みの設定にチューニングすることにかかる時間を考えると、以 下に述べるライブラリやコンパイラをごちゃごちゃにしてしまうよりは必要な データを全てバックアップして最新の Red Hat や Debian をインストールし てしまった方がいいかも知れません。

強調しておきますが、以下に述べるインストール方法はそれ自身としては簡単 な仕事です(新しいソフトウェアをダウンロードする時間を除けば一時間もあ れば十分でしょう)が、システムが再起動できなくなるような失敗の可能性も あちこちにあります。共有ライブラリをバージョンアップしたくなかったり、 ldconfigldd といったコマンドを御存知なかったり、 ソースコードから必要なプログラムを作成するのが面倒だったりするならば、 「より簡単な方法」を選ぶ方がいいでしょう。それも嫌な場合、とにかくこう いう風に考えてみてください -- 「完全な ELF システム」のためには、 誰かが 全てのバイナリをその上でコンパイルし直さなければならないの です。

それでもやりますか?

2. インストール

2.1 バックグラウンド

ここに示す移行手順の目的は、a.out と ELF の双方をコンパイルして動 かすことのできるシステムを構築することです。そのためには双方のプログラ ムが適切な共有ライブラリを見つけられなければなりません。このためには、 他のいくつかのシステムがやっているように、単純に `/lib/usr/lib そしてコンパイル時に指定されたディレクトリを全て探す' という方法よりも多少なりとも賢い方法が必要です。

賢い方法の中心に位置するのがシステムの上に一つ、あるいは二つ、存在する 動的ローダです。a.out のプログラム用には /lib/ld.so、 ELF のプログラム用には /lib/ld-linux.so.1 がそれぞれ動的ロー ダになっています。コンパイラやリンカは出力するプログラムにライブラリへ の絶対パスを埋めこむことはしません。その代りに、ライブラリ名と適切な動 的ローダへの絶対パスを埋めこみます。そして、実行時に、(動的ローダが)適 切なライブラリに結びつけるわけです。ここに重要な秘密があります -- すな わち、あるプログラムが使っているライブラリが別のディレクトリに動かされ ても、プログラムを再コンパイルする必要はなくld.so (あるいはld-linux.so.1) に新しいディレクトリを探しに行くように 指示するだけで済みます。これが以下に述べるディレクトリを入れ替える操作 の骨子です。

上記から導かれる結論として、ld.so を削除したり移動させたりす れば、動的リンクを使っているプログラムは全て機能しなくなる、 ということがわかります。これは良くないことである、と一般に考えられてい ます。

ですから、基本的な計画としては、ELF 用の開発環境(コンパイラ、インクルー ドファイル、ライブラリ)を、今は a.out 用のものがある /usr/{bin,lib,include}に置き、a.out 関連のファイルは /usr/i486-linuxaout/{bin, lib, include} へ移すことにします。 /etc/ld.so.conf はライブラリが見つかるであろう場所全てのリス トになっており、ldconfig は ELF と a.out を見わける能力を持っ ています。

ライブラリの場所には多くの例外があります。

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

プログラムは常にソースからコンパイルするという人でも、以下に示すプログ ラムはバイナリ版を入手してお使いになることを強くお勧めします。これらの プログラムのほとんどは a.out 版のシステムで ELF 形式を生成するようには 設定されておらず、a.out の環境でコンパイルしようとしても無駄です。

絶対に必要なもの

その他

上記以外にも、必須ではありませんが入手しておいた方がいいライブラリ やファイルがいくつかあります。以下に示すものは ELF で使うためにバージョ ンアップしなければならない類いのプログラムです。この文書の後半では、そ のままでも使えるものの、ELF 形式でコンパイルするには修正やバージョンアッ プが必要なプログラムを紹介します。ネットとの接続が遅い場合(例えばフロッ ピーの箱を抱えて 5 分間歩いているくらい時間のかかるような)、以下のファ イルは飛ばして、設定を終える前にこの文書の後半部にあるそれぞれのプログ ラムについての記述と合せてチェックしてください。

2.4 ファイルシステムの再調整

え〜っと、私が以下で「削除する」と言った場合、「バックアップを取っ てから削除する」と読みかえてください :-) まず、深呼吸して、、

エッセンス --- バイナリ・インストール

  1. a.out バイナリを移動するためのディレクトリを作成
    mkdir -p /usr/i486-linuxaout/bin
    mkdir -p /usr/i486-linuxaout/include
    mkdir -p /usr/i486-linuxaout/lib
    mkdir /lib-aout
    
  2. 動的リンカのパッケージ ld.so-1.7.14 をいつものソースコー ドを置いている場所で展開し、取り出された ld.so-1.7.14/instldso.sh スクリプトを読んでください。本当に標 準的なシステムをお使いなら、sh instldso.sh を実行してインストー ルすることができますが、何か非標準的なものを組みこんでいる場合、手動で インストールすることになります。「何か非標準的なもの」とは、
  3. /etc/ld.so.conf を修正して、 /usr/i486-linuxaout/lib を加え(必要ならば /lib-aout も加え)、/sbin/ldconfig -v を再実行して、新しいディレクトリ を探しにいくかチェックします。
  4. /usr/*/lib にある全ての a.out 形式の「ライブラリ」を /usr/i486-linuxaout/lib に移します。移すものは lib*.so*lib*.sa*lib*.a などの「ライブ ラリ」であって、その他のファイルを移す必要はありません。 /usr/lib/gcc-lib などもまだ動かしてはいけません。
  5. 次に /lib をチェックします。libc.so*libm.so*libdl.so* はそのままにしておきます。X のラ イブラリ(libX*.so.3*へのシンボリックリンクもそのままにしてお きましょう --- XView 等のプログラムがそれらのライブラリを使っ ているかも知れません。ld.so*ld-linux.so* など ld で始まっているファイルもそのままにしておきます。残りのライ ブラリについては(もしあれば): ルートパーティションに /usr が あれば、そこにあるファイルは /usr/i486-linuxaout/lib に移しま す。/usr が別パーティションにマウントされていれば、 /lib-aout に移します。これで ldconfig -v してみてく ださい。
  6. binutils をインストールする準備として、もし /usr/lib/ldscripts ディレクトリがあれば削除します(binutils が このディレクトリを新たに作ります)
  7. /usr/bin にある(ld86as86 以外の)全ての ldas のコピーを削除します。
  8. /usr/include 以下のディレクトリを削除します。標準的な システムでは、ここにあるファイルのいくつかはシステムの「核」となる機能 を担っており、libc と共に配布されています。それ以外にも、あなた自身が インストールしたり、使っているディストリビューションの作成者がインストー ルしたファイルもあるはずです。これらを整理するために、0 から作り直すこ とをお勧めします。まず既存の/usr/include/usr/include.oldに変更し、libc-5.2.18.bin.tar.gzをルー トディレクトリで展開します。
  9. binutils パッケージをインストールします。このためには tar - xvzf binutils-2.6.0.12.bin.tar.gz -C / がお勧めの方法です。
  10. gcc パッケージはルートディレクトリで展開する必要があります。gcc パッケージはいくつかのファイルを /usr/bin に、残りの多くのファ イルを /usr/lib/gcc-lib/i486-linux/2.7.2/usr/lib/gcc-lib/i486-linuxaout/2.7.2 にインストールします。 gcc をインストールするには、まず
    $ tar ztf gcc-2.7.2.bin.tar.gz
    
    として、何が入っているかをチェックしてください。残しておきたいファイル に上書きするようであれば(例えば Gnu ADA をインストールしていれば /usr/bin/gcc を残しておきたいでしょう)、まずそれらのファイル を安全な所に移します。その上で、
    # tar -zxf gcc-2.7.2.bin.tar.gz -C /
    
    とします。この時点で、gcc -v して gcc のバージョンを確かめた り、テスト用のプログラムをコンパイルして、きちんと動いているかチェック してください。
    $ gcc -v
    Reading specs from /usr/lib/gcc-lib/i486-linux/2.7.2/specs
    gcc version 2.7.2
    $ gcc -v -b i486-linuxaout
    Reading specs from /usr/lib/gcc-lib/i486-linuxaout/2.7.2/specs
    gcc version 2.7.2
    $ ld -V
    ld version 2.6 (with BFD 2.6.0.2)
      Supported emulations:
       elf_i386 
       i386linux 
       i386coff 
    
    次に伝統的な ``Hello, world'' プログラムを試してください。そのプログラ ムを gccgcc -b i486-linuxaout で、コンパイルし、 a.out と ELFのコンパイラが正しく設定されているか確認してみましょう。 終りましたかって?もう少し頑張って。まだいくつかのライブラリが残ってい ます。また、シンボリックリンクをごちゃごちゃ張らないといけません。頑張っ て、、

    シンボリックリンク

  11. いくつかのプログラム(特にいくつかの X 関連プログラム)は /lib/cpp を使います。/lib/cpp は Linux では /usr/lib/gcc-lib/i486-linuxversion/cppにあり ます。ここまでの段階で /lib の下にあるシンボリックリンクは全 て削除しているはずなので、リンクを張り直す必要があります。
    # cd /lib
    # ln -s /usr/lib/gcc-lib/i486-linux/2.7.2/cpp .
    
  12. /usr/include 以下を /usr/include.old 以下に移 すと、カーネルのソースコードへのシンボリックリンクが失なわれるので、
    # cd /usr/include
    # ln -s ../src/linux/include/linux .
    # ln -s ../src/linux/include/asm .
    
    としてリンクを張り直してください。 (ここではカーネルのソースコードは /usr/src/linux にあると仮定 しています。そうでない場合、適切な場所を指定してください)
  13. FSSTND の連中は、ここでも utmpwtmp ファイ ルを /var/adm から /var/run/var/log に それぞれ移すことにしました。必要に応じて /var/log/var/adm を作り、utmpwtmp の現在位置へ リンクを張るようにしてください。私は以下の ls -l に示すような 配置にしました。
    $ ls -ld /var/adm /var/log /var/run /var/log/*tmp /var/run/*tmp
    lrwxrwxrwx   1 root     root            3 May 24 05:53 /var/adm -> log/
    drwxr-xr-x   9 root     root         1024 Aug 13 23:17 /var/log/
    lrwxrwxrwx   1 root     root           11 Aug 13 23:17 /var/log/utmp -> ../run/utmp
    -rw-r--r--   1 root     root       451472 Aug 13 23:00 /var/log/wtmp
    drwxr-xr-x   2 root     root         1024 Aug 13 23:17 /var/run/
    -rw-r--r--   1 root     root          448 Aug 13 23:00 /var/run/utmp
    
    FSSTND の全体については sunsite にあ る LDP のアーカイブなどにある文書をご覧ください。

    おめでとう!

    ここまでで(多少なりとも)完全に機能する ELF の開発環境が完成したはずで す。一歩下って、しばらく静かに喜びをかみしめましょう。

    重要なソースコードのパッケージ

  14. ncurses のインストールはかなり時間のかかる仕事です。もっ とも、その大部分の時間はコンパイルしながらネットニュースを読むことに費 すことができますが。tar ファイルを展開したら INSTALL ファイル を、自分が「Linux 何たらシステム」のディストリビューションの作成/まと め役である、と思って読んでみましょう。すなわち、コンパイルの際には、多 分、以下のようなコマンドラインで設定する必要がある、ということです。
    $ ./configure --with-normal --with-shared --disable-termcap --enable-overwrite --prefix=/usr
    
    デフォルトになっているターミナルの種類にも注意しましょう。1.3 と 2.0 のカーネルでは、起動時のデフォルトのターミナルは linux になっ ています。場合によっては /etc/inittab を修正して consolegetty にしなければならないかも知れません。 ルートパーティションのあるハードディスクに /usr/lib/terminfo が無い場合、ncurses の `fallback' 機能でごまかす必要があるでしょう。こ の機能は上述の INSTALL ファイルに説明してあり、単純ですが、退 屈な仕事になります(ライブラリを 2 度作成する必要があります)。fallback として linuxvt100 を使えばいい場合、幸いなことに 既存の fallback.cに置き替え可能な fallback.cftp.uk.linux.org に用意されています。 ncurses をインストールした後、/usr/lib 以下で多少面倒な仕事を する必要があります。これは不定形な作業なので、手でやるのが最も簡単です。 バージョン番号が多少不一致になっていることに注意してください。これは醜 いですが、健康に害があるわけではありません。
    1. /usr/lib/libncurses.so.1.9.9e/lib に移し、 シングルユーザーモードでも curses プログラムが動けるようにします。ルー トパーティション に /usr/lib がある場合、特にこの作業は不要で すが、やっておいても害はありません。
    2. /lib ディレクトリで libncurses.so.1.9.9e から /libncurses.so.3.0 へリンクを張ります。
    3. その他、/lib/libncurses.so.3.0 から /usr/lib/libncurses.so/usr/lib/libcurses.so/usr/lib/libtermcap.so へのリンクも必要かも知れません。
    考えるのがメンドウな人向けに簡単に言うと、以下のような作業になります。
    # cd /lib
    # mv /usr/lib/libncurses.so.1.9.9e .
    # ln -s libncurses.so.1.9.9e libncurses.so.3.0 
    # cd /usr/lib
    # ln -s /lib/libncurses.so.3.0 libncurses.so
    # ln -s /lib/libncurses.so.3.0 libcurses.so
    # ln -s /lib/libncurses.so.3.0 libtermcap.so
    
  15. gdbm のインストール。ソースコード用のディレクトリでソー スコードを展開し、gdbm.patch をあて、READMEINSTALL ファイルに目を通します。 構築の手順は以下のようなものになるはずです。
    $ tar zxf gdbm-1.7.3.tar.gz
    $ patch -p0 < gdbm.patch
    $ cd gdbm-1.7.3
    $ ./configure --prefix=/usr
    $ make 
    $ make progs
    $ su
    # make install
    # make install-compat
    # cd /usr/lib
    # ln -s libgdbm.so.1 libgdbm.so
    # ln -s libgdbm.so.1 libgdbm.so.2
    # ldconfig
    
    最後の 2 つは古いバージョンとの互換性を保つためです。最近のディスト リビューションでは libgdbm.so.2 というバージョンになっていま すが、これは libdgbm.so.1 と全く同じコードで、バージョン番号 だけが歴史的な理由から間違えて付けられているものです。

    オプションのソースコードパッケージ

    一般に、それぞれのパッケージに付属の指示にしたがってインストールすれば 大丈夫なので、ここで繰り返すことはしません。ただし、例外が 2 つあり、

  16. GNU 風の termcap が必要な場合(厳密に言うと必須ではあり ませんが、実際には XFree86 のバイナリが必要とするので、ほぼ必須でしょ う)、ソースコードから構築する必要がありますが、必要な作業は以下に示す 程度です。
    $ tar zxf termcap-2.0.8.tar.gz
    $ cd termcap-2.0.8
    $ make
    $ su
    # cp libtermcap.so.2.0.8 /usr/lib
    # ldconfig
    
    決して make install は実行しないように。make install すると ncurses のプログラムを一部上書きしてしまいます。こ のライブラリを使うようにコンパイルされた既存のバイナリを使うのではなく、 新たにこのライブラリを使ってプログラムをコンパイルする場合、ヘッダーファ イルとスタティック・ライブラリをどこか別の場所に用意して -I-L フラグを使ってコンパイル時にその場所を明示するようにし てください。この部分は他の部分に比べて記述が曖昧だと思われるかも知れま せんが、それには理由があります。すなわち、よほどの理由がないかぎり、 termcap を使い続けることはお勧めできないからです。
  17. libdb は以下のように作成します。
    $ tar zxf db.1.85.tar.gz
    $ patch -p0 <db.patch
    $ cd db.1.85/PORT/linux
    $ make
    $ su
    # mkdir /usr/include/db
    # ldconfig
    # cp libdb.so.1.85.3 /usr/lib ; ( cd /usr/lib && ln -s libdb.so.1 libdb.so )
    # cp ../../include/*.h /usr/include/db
    
    注意点としては

2.5 どういう風になるのか(ディレクトリ構成のアウトライン)

以下に示すものは今までにインストールしてきたファイルのかなりおおま かな概観です。トラブルシューティングや削除すべきものを決める際にご利用 ください。

/lib

/usr/lib

/usr/lib/ldscripts

/usr/i486-linux/bin

/usr/i486-linuxaout/bin

/usr/i486-linux/lib

/usr/i486-linuxaout/lib

/usr/lib/gcc-lib/i486-linux/2.7.2

/usr/lib/gcc-lib/i486-linuxaout/2.7.2

2.6 よくあるエラー ——— あわてないで!

(以下の内容の大部分は親切なメールでいただいたものです)

何か間違ったものを動かして、何も動かなくなってしまった!

その場合でも shell は動いているはずなので、多少工夫すれば shell の組み こみ機能だけでかなりの仕事をこなすことが可能です。echo *ls の代わりに使え、echo >>filename はファイル に書き足すのに使えます。ldconfig も静的にリンクされていること をお忘れなく。例えば、libc.so.4 を間違って lib-aout ディレクトリに移してしまった場合、echo "/lib-aout" >>/etc/ld.so.conf ; ldconfig -vすれば、復旧します。 /lib/ld.so を動かしてしまった場合、 静的にリンクされた ln が あれば、sln /sillyplace/ld.so /lib/ld.soすることで、多分復旧 するでしょう。

bad address

ELF 形式のプログラムを動かそうとすると、いつもbad address エ ラーになる場合、多分、カーネルの 1.3.xx <3 の バージョンをお使いなのでしょうが、そのバージョンを使ってはいけません。 それらは多分、最悪のバージョンの一つです。2.0 へバージョンアップするか 1.2.13 にバージョンを落しましょう。似たような環境でカーネルパニックが 発生すると報告している人たちもいますが、私は詳しく調べていません。なぜ なら、開発版のバージョンを使いたいとも思わないし、使う必要があるとも感 じないので、最新版の追っかけはしていないからです。

gcc: installation problem, cannot exec something: No such file or directory

a.out 形式でコンパイルしようとして(something の部分はたいてい の場合 cppcc1 のはずです)、このエラーが生じる場 合、実際に cppcc1 に問題があるか、

$ gcc -b -i486-linuxaout

のように入力したのでしょう。実際には

$ gcc -b i486-linuxaout

と入力しなければなりません。`i486'の部分はダッシュではじまらないことに 注意してください。

make: *** No targets specified and no makefile found. Stop.

このエラーが出る場合、make にパッチをあてて再コンパイルしてい ないか、古いバージョンの make がシステムのどこかに残っている のでしょう。

no such file or directory: /usr/bin/gcc

実際にそのファイルが存在するのにこういうエラーが出る(gcc 以外のプログ ラムでもこうなるかも知れません)。この場合、ELF の動的ローダー /lib/ld-linux.so.1 をインストールしていないか、何らかの理由で ローダーが読めない状態になっているのでしょう。先に述べたインストールス テップの 2 を読んで /lib/ld-linux.so.1 を正しくインストールし てください。

not a ZMAGIC file, skipping

このエラーは ldconfig が出しています。古いバージョンの ld.so のパッケージをお使いのようなので、新しいものを入手してください。もう一 度、インストールのステップ 2 を読んでください。

_setutent: Can't open utmp file

このメッセージは xterm を起動した時に 3 行ずつ出力されることがよくあり ます。インストール手順の最後のあたりにある FSSTND の長文の説明を読んで ください。

3. プログラムの構築

3.1 一般的なプログラム

プログラムを ELF 形式でコンパイルする場合、いつものように gcc を使います。a.out 形式でコンパイルする場合、gcc -b i486-linuxaout としてください。

$ 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

さて、そろそろ「a.out 形式のコンパイラが出力するバイナリのデフォルト名 が a.out なら、ELF コンパイラの出力するバイナリのデフォルト名 は何というの?」という質問に答えるべき時でしょう。答は、「やっぱり a.out」なんです。残念でしたか? :-)

3.2 ライブラリの作り方

libfoo.so を共有ライブラリとして構築したい場合、基本的な手順 は以下のようになります。

$ gcc -fPIC -c *.c
$ gcc -shared -Wl,-soname,libfoo.so.1 -o libfoo.so.1.0 *.o
$ ln -s libfoo.so.1.0 libfoo.so.1
$ ln -s libfoo.so.1 libfoo.so
$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH

これにより、libfoo.so.1.0 と呼ばれる共有ライブラリと ld 用の シンボリックリンク(libfoo.so)、動的リンカ用のシンボリックリン ク(libfoo.so.1)が作成されます。ライブラリのテストの際は、最後 に示したように、現在のディレクトリを LD_LIBRARY_PATH に加えて 試してみましょう。

ライブラリが正しく動くことが確認できれば、適切な場所、例えば /usr/local/lib に移し、リンクを張り直しましょう。 libfoo.so のリンクは libfoo.so.1 へ張られているので、 バージョン番号のマイナーチェンジがあってもリンクを張り直す必要はありま せん。libfoo.so.1.0 から libfoo.so.1 へのリンクは、 たいていのシステムでは ldconfig が起動時に更新します。

$ su
# cp libfoo.so.1.0 /usr/local/lib
# /sbin/ldconfig
# ( cd /usr/local/lib ; ln -s libfoo.so.1 libfoo.so )

3.3 a.out 形式の構築

ELF 環境の中でも古い a.out 形式のバイナリを作成しなければならない 場合があるかも知れません。「普通の」プログラムの場合、必要なことは gcc を起動する時に -b i486-linuxaoutフラグを使って a.out 用のコン パイラを起動し、(もし) ld を起動する場合は -m i386linux フラ グを使います。a.out 形式の DLL 共有ライブラリを未だに必要とする人は、、 可哀想に。私の知る限りでは、一言で言えば「動きません」。別の方法を御存 知ならばメールで私に教えてください。

4. ELF 用パッチとELF 化済みのプログラム

ここまでで、お好みならば終了することが可能です。ELF 形式のプログラ ムをコンパイルして動かすために必要な環境は全てインストールできました。

「美意識」的な観点やメモリ使用量を最小化するためには、お使いのプログラ ムを全て ELF 形式でコンパイルし直したくなるかも知れません。ELF 形式で の再コンパイルはほとんどのエンドユーザー用のアプリケーションではごく簡 単です。しかしながら、動作環境について何らかの前提のあるプログラムもい くつかあり、それらは以下のような理由でエラーになるかも知れません。

とにかく、以下に 2 つのリストを示します。最初のリストは既に ELF 形式の バージョンが作成されているもの(すなわち、ELF 形式でコンパイルするには 新しいバージョンを入手すればいいもの)で、2 つめのリストは第三者からの パッチが必要なプログラムです。

4.1 アップグレードすればいいもの:

4.2 パッチが公開されているもの

5. より詳しい情報

6. その他

6.1 フィードバックのお願い

Feedback は歓迎します。メールは daniel.barlow@linux.org へお願いします。秘密のメールを送る必要がある場合、私の web pages にある PGP の 公開鍵(ID 5F263625)を使ってください。

この文書に答があるべき問題で、答が見つからない場合も私にメールしてくだ さい。この文書の中で触れられるべきではない問題で、私が答を知っているか も知れない問題については、まず comp.os.linux.* ニュースグルー プに投稿してみてください。たいていメールの問い合わせにも答えていますが、 メールを無くすこともよくあるので。

私の名前がゴミメーリングリストに載っているのを見た人は削除してくださる ようにお願いします。

6.2 翻訳版

この文書の翻訳版を作りたい場合、積極的にやっていただいて構いません が、一言連絡してください。私が話せる言語に翻訳してもらえる可能性は(悲 しいことに)数百分の一でしょうが、それはさておき、私の出来ることはよろ こんでお手伝いします。

私が知っている翻訳版は:

6.3 法的な話題

All trademarks used in this document are acknowledged as being owned by their respective owners. Yow!

The right of Daniel Barlow to be identified as the author of this work has been asserted in accordance with sections 77 and 78 of the Copyright Designs and Patents Act 1988.

This document is copyright (C) 1996 Daniel Barlow <daniel.barlow@linux.org> It may be reproduced and distributed in whole or in part, in any medium physical or electronic, as long as this copyright notice is retained on all copies. Commercial redistribution is allowed and encouraged; however, the author would like to be notified of any such distributions.

All translations, derivative works, or aggregate works incorporating any Linux HOWTO documents must be covered under this copyright notice. That is, you may not produce a derivative work from a HOWTO and impose additional restrictions on its distribution. Exceptions to these rules may be granted under certain conditions; please contact the Linux HOWTO coordinator at the address given below.

In short, we wish to promote dissemination of this information through as many channels as possible. However, we do wish to retain copyright on the HOWTO documents, and would like to be notified of any plans to redistribute the HOWTOs.

If you have questions, please contact Greg Hankins, the Linux HOWTO coordinator, at gregh@sunsite.unc.edu.

この文書に現われたトレードマークは全てその所有者に帰属しています。

この文書の原著者である Daniel Barlow の権利は 1988 年に制定された ``COpyright Desings and Patents" 法の 77 条と 78 条に規定されています。

この文書は Daniel Barlow<daniel.barlow@linux.org> が著作権 を有しています。この著作権表示が示される限り、どのような物理的、電子的 媒体を用いて、この文書の全体でも一部だけでも、コピーして再配布すること が可能です。商的利用も許諾され、推奨されますが、そのような場合には著者 まで一言お知らせください。

翻訳やこの文書から派生した文書、あらゆる Linux HOWTO 文書との組みあわ せた文書集なども、この著作権表示によって保護されることになります。すな わち、Linux の HOWTO から派生した作品に対して、その配布を妨げるような 制限を課すことはできません。一定の条件のもとで例外を設けることも可能な ので、詳細については以下に示す Linux HOWTO のコーディネータに尋ねてく ださい。

簡単に言えば、私たちは可能なかぎりの方法でこの文書などの情報を広く知ら せようと考えています。しかしながら、私たちは HOWTO 文書に著作権を設定 し、HOWTO の再配布計画については知らせてもらいたいと思っています。

質問があれば、現在の Linux HOWTO のコーディネータ、Grep Hankins gregh@sunsite.unc.edu へ連絡してください。