The Linux ELF HOWTO <author>Daniel Barlow <tt><daniel.barlow@linux.org></tt> <date>1996/07/14 <trans> こじまみつひろ <tt><isle@st.rim.or.jp></tt> (11/4) <abstract> この文書はあなたの Linux システムで ELF バイナリ形式のプログラムをコン パイルして動かすための方法をまとめたものです。この文書は大きく、(1)ELF とは何か、なぜ移行しなければならないか、(2)どうすれば ELF 形式が使える ようになるのか、(3)ELF にすれば何ができるのか、という 3 つの部分に分か れています。 私が研究にいそしんでいるフリをしている間、この文書は放ったらかしになっ ていましたが、最近 Linux 2.0 の情報を追加して全体をオーバーホールしま した。 </abstract> <p> <bf>注意: この文書はかなり以前に書かれたものなので、 いまどきの Linux 環境にはあてはまらない箇所があります。 (JF Project)</bf> </p> <sect>ELF とは何か? 簡単な紹介 <p> ELF(Executable and Linking Format)は元々 USL(Unix System Laboratories) で開発されたバイナリ形式で、現在は Solaris や System V Release 4 が採 用しています。 Linux がかって使っていた a.out 形式に比べて、ELF 形式は 柔軟性に富むので、GCC と C ライブラリの開発者たちは Linux の標準的なバ イナリ形式を ELF にしようと決定しました。 「柔軟性に富む」というのは、標準的なアプリケーションプログラマに 2 つ の利点を与えます。 <itemize> <item> ELF 形式を使えば共有ライブラリがずっと簡単に作成できます。通常、 <tt>-fPIC</tt>オプションを付けてコンパイルしたオブジェクトファイルを、 <tscreen><verb> gcc -shared -Wl,-soname,libfoo.so.y -o libfoo.so.y.x *.o </verb></tscreen> というコマンドラインでリンクするだけです。 これが複雑に見えるようならば、多分 a.out 形式で同じような共有ライブラ リを作る方法を御存知ないのでしょう。a.out 形式で共有ライブラリを作るた めには、ライブラリを 2 度コンパイルして、ライブラリが将来使うであろう 全てのデータのための空間をあらかじめ予約し、予約されたアドレス空間は全 ての開発者間で登録しておかねばなりません(詳しくは <url url= "ftp://tsx-11.mit.edu/pub/linux/packages/GCC/src/tools-2.17.tar.gz"> にある 20ページを超える文書をご覧ください)。 <item>動的ローディング(動作中のプログラムがモジュールをロードできる機 能)をずっと単純に実現できる。この機能は Perl 5 や Python, Java などで 使われています(さまざまな種類のインタープリタの起動に使われます)。動的 ローディング機能のもう一つの使い道は super-fast MUD です。この場合、プ ログラムを停止して再起動することなく、新しいプログラムをコンパイルして 動いているプログラムに組みこむことが可能になります。 </itemize> <p> このような利点に対して、ELF を使うと多少遅くなる、という反論もあります。 1% から 5% くらい遅くなるというのが通説ですが、実際のテストが示す結果 を見ると、その差は同時に起っているさまざまなノイズに隠されてしまう程度 のもののようです。TeX や Postscript のビューワ/プリンタを持っていれば、 SunSite などから <tt>speed.comp-1.0.tar.gz</tt> という ELF と a.out の 速度を比較した論文を入手して読むのもいいでしょう。 ELF 形式が遅くなるのは ELF のライブラリコードがポジションインデペンデ ントでなければならないことに由来します(コンパイル時の <tt>-fPIC</tt> オプションが意味することです)。ポジションインデペンデントであるため、 一つのレジスタをオフセット保持用に使わなけれなばならなくなります。その ため、変数を保存するのに使えるレジスタが一つ減ってしまいます。特に 80x86 CPU では一般的に使えるレジスタが元々不足しています。速度に差が出 るのは共有ライブラリのコードに限られていることに注意してください。アプ リケーションやカーネルでは a.out と ELF の間で速度差はありません。 <sect1> ELF は何ではないか? <p> ELF 化すれば何ができるかについて、多くの誤解が広まっています。 <descrip> <tag/SVR4 や Solaris のプログラムを動かすためのものではありません/ ELF は SVR4 システムと同じ形式のバイナリの`容器'ですが、だからと言って、 ELF にすれば SVR4 用のプログラムが突然 Linux でも使えるわけではありま せん。この関係はディスクフォーマットと似ているでしょう -- Linux のプロ グラムを MSDOS や Minix のフォーマットのディスクに保存したり、その逆も 可能ですが、だからといってそれぞれのシステムが互いのプログラムを実行で きるわけではありません。 (そのプログラム自身に依存しますが)他の x86 Unix 用のプログラムを Linux で動かすことも可能かも知れませんが、この HOWTO では、そのための説明は <bf>致しません</bf>。まず(<tt>tsx-11.mit.edu</tt> などにある)iBCS カー ネルモジュールについて調べることから始めましょう。 <tag/プログラムが小さくなるわけでも、速くなるわけでもありません。/ ずっと簡単に共有ライブラリが作れるようになったので、複数のプログラム間 で共通しているコードをライブラリ化すれば、結果としてより小さなプログラ ムを作成すことも可能かも知れませんが、一般的に言って、同じコンパイラオ プションを指定してバイナリが a.out よりも小さくなったなら、たまたま運 が良かったか、コンパイラのバージョンが違うためでしょう。もし「速く」なっ たら、ちょっとびっくりです。共有ライブラリを活用してプログラムが小さく なったため、スワップが減ったり、より多くのメモリを利用できるようになっ たならば、速くなることもありえますが。 <tag/全てのバイナリを置き替える必要はありません/ この文書の手順に従えば、ELF と a.out の双方をコンパイルして動かすシス テムを構築できます。新しいプログラムはデフォルトでは ELF 形式にコンパ イルされますが、これはコマンドラインスイッチで変更できます。ELFと a.out を同時に動かした場合、両方の C ライブラリを読みこまなければなら なくなるなど、多少メモリの使用効率は悪くなります。もっとも、この差は メモリを 6Mb 積んだマシンではほとんど気づかない程度だそうですので(8Mb のマシンではもっと気づきませんでした)、あまり気にすることも無いでしょ う。何しろ、Emacs や静的リンクされた Mosaic/Netscape といったメモリを 大食いするプログラムを毎日のように 使っているでしょ? :-) <tag/トールキンとは関係ありません/ 少なくともこの文脈においては。 </descrip> <sect1> なぜ ELF へ移行すべきか <p> ELF を使えるようにシステムをアップグレードするのには、主に 2 つの 理由があります:まず第一に、上述したようにプログラムがずっと柔軟にでき ること。第二に、第一とも関連しますが、だれもがそうしようとしている(あ るいは既にそうした)から。将来の C ライブラリや GCC は ELF 用のみがリリー スされますし、それ以外のプログラムの開発者たちも ELF の方へ進むはずで す。 ELF の安定性に不安を感じている人々もいます(愉快な話ではありませんが、 当然のことです)。Linux の世界で ELF は 1994 年の夏から存在していました。 その後 1995 年の 5 月か 6 月ごろ一般に公開されました。現在では、致命的 な問題は存在しないでしょう。大きなバージョンアップをする時にしばしば起 きるように、きちんと動いているシステムを壊しかねないと感じている人もい るかも知れません。でも、このバージョンアップはもはや最先端の技術ではあ りません。開発用のシステムや他の人がコンパイルしたバイナリを動かしたい 場合では、ELF は必須のものになりつつあります。カーネルを v2.0 にバージョ ンアップする際に ELF へスイッチすることを考えてください。 <sect1> ELF への移行の仕方 <p> この HOWTO が最初に書かれた時には ELF へ移行する方法は、ここに述べ た方法一つしかありませんでした。今日では、高品質で簡単に新しいバージョ ンをインストールできるようなディストリビューションも存在します。あなた のマシンをお好みの設定にチューニングすることにかかる時間を考えると、以 下に述べるライブラリやコンパイラをごちゃごちゃにしてしまうよりは必要な データを全てバックアップして最新の Red Hat や Debian をインストールし てしまった方がいいかも知れません。 強調しておきますが、以下に述べるインストール方法はそれ自身としては簡単 な仕事です(新しいソフトウェアをダウンロードする時間を除けば一時間もあ れば十分でしょう)が、システムが再起動できなくなるような失敗の可能性も あちこちにあります。共有ライブラリをバージョンアップしたくなかったり、 <tt>ldconfig</tt> や <tt>ldd</tt> といったコマンドを御存知なかったり、 ソースコードから必要なプログラムを作成するのが面倒だったりするならば、 「より簡単な方法」を選ぶ方がいいでしょう。それも嫌な場合、とにかくこう いう風に考えてみてください -- 「完全な ELF システム」のためには、 <bf>誰か</bf>が 全てのバイナリをその上でコンパイルし直さなければならないの です。 それでもやりますか? <sect> インストール <sect1> バックグラウンド <p> ここに示す移行手順の目的は、a.out と ELF の双方をコンパイルして動 かすことのできるシステムを構築することです。そのためには双方のプログラ ムが適切な共有ライブラリを見つけられなければなりません。このためには、 他のいくつかのシステムがやっているように、単純に `<tt>/lib</tt> と <tt>/usr/lib</tt> そしてコンパイル時に指定されたディレクトリを全て探す' という方法よりも多少なりとも賢い方法が必要です。 賢い方法の中心に位置するのがシステムの上に一つ、あるいは二つ、存在する <bf>動的ローダ</bf>です。a.out のプログラム用には <tt>/lib/ld.so</tt>、 ELF のプログラム用には <tt>/lib/ld-linux.so.1</tt> がそれぞれ動的ロー ダになっています。コンパイラやリンカは出力するプログラムにライブラリへ の絶対パスを埋めこむことはしません。その代りに、ライブラリ名と適切な動 的ローダへの絶対パスを埋めこみます。そして、実行時に、(動的ローダが)適 切なライブラリに結びつけるわけです。ここに重要な秘密があります -- すな わち、あるプログラムが使っているライブラリが別のディレクトリに動かされ ても、<bf>プログラムを再コンパイルする必要はなく</bf>、<tt>ld.so</tt> (あるいは<tt>ld-linux.so.1</tt>) に新しいディレクトリを探しに行くように 指示するだけで済みます。これが以下に述べるディレクトリを入れ替える操作 の骨子です。 上記から導かれる結論として、<tt>ld.so</tt> を削除したり移動させたりす れば、<em>動的リンクを使っているプログラムは全て機能しなくなる</em>、 ということがわかります。これは良くないことである、と一般に考えられてい ます。 ですから、基本的な計画としては、ELF 用の開発環境(コンパイラ、インクルー ドファイル、ライブラリ)を、今は a.out 用のものがある <tt>/usr/{bin,lib,include}</tt>に置き、a.out 関連のファイルは <tt>/usr/i486-linuxaout/{bin, lib, include}</tt> へ移すことにします。 <tt>/etc/ld.so.conf</tt> はライブラリが見つかるであろう場所全てのリス トになっており、<tt>ldconfig</tt> は ELF と a.out を見わける能力を持っ ています。 ライブラリの場所には多くの例外があります。 <itemize> <item> 古いプログラムのいくつかは <tt>ld.so</tt> を使わずに作られてい ます。これらのプログラムはライブラリが別の場所に移動すれば動かなくなり ます。ですから、もしそのようなプログラムを使っているならば、 <tt>libc.so*</tt> や <tt>libm.so</tt> は<tt>/lib</tt> にそのまま残して おかねばなりません。ELF 用のライブラリは主バージョン番号が異なっている ので、a.out と同じディレクトリに置いても上書きしてしまうことはありませ ん。古い X 関連のライブラリ(version 6 以前)もそのままの場所に残してお くのがいいでしょう。一方、新しいバージョン(<tt>libX*so.6</tt> は別の場 所に置かねばなりません。古いライブラリを動かすと、xview 関連のプログラ ムが動かなくなり、新しいライブラリを別の場所に置くようにしないと ELF 用の X ライブラリをインストールした際に古いものに上書きしてしまいます。 上記以外のライブラリを必要とする ld.so を使っていないプログラムをお持 ちなら(どのプログラムが該当するか分っていれば、<bf>前もって</bf>それら のプログラムを <tt>ldd</tt> で調べて、必要なライブラリをチェックしてお きましょう)、2 つの方法があります。一つは、ELF ライブラリを仮のディレ クトリに展開して、必要なライブラリに上書きされるかどうかを確認すること です。もし上書きされるようならば、ELF 版のライブラリは <tt>/lib</tt> とは違う場所、例えば <tt>/usr/i486-linux-lib</tt> へ置くようにします。 そして <tt>ldconfig</tt> してそのディレクトリが参照されるようにします。 もう一つの方法は問題のプログラムの新しいバージョンを入手してコンパイル し直してしまうことです。これはソースコードが入手可能ならば、そう悪いア イデアではありません。 <item> <tt>/usr</tt> と <tt>/</tt> が別のパーティションになっている場 合、<tt>/lib</tt> から動かすライブラリは、<tt>/usr</tt> のあるパーティ ションではなく、ルートパーティションのあるディスク上に置く必要がありま す。以下の例では <tt>/lib-aout</tt> に置くようにしています。 </itemize> <sect1> 始める前に --- 注意すべきポイント <p> <itemize> <item> <bf>ELF フォーマットのバイナリを動かすことのできる 1.1.52 以降 のカーネル</bf>を使っていることを確認してください。1.2.13 でも大丈夫で す。ほとんどの 1.3.x 同様、2.0.0(この文書を書いているいる時点での最新 版)でも動きますが、2.0 がリリースされた今となっては、古い「実験版」の カーネル(1.3.x) を使う必要はないでしょう。 <item> Slackware の救急(rescue)デイスクのような boot/root ディスクを用 意しておきましょう。多分必要になることはありませんが、必要になった時に 手元に無いと散々な目に遭います。同様に、mv や ln 等のファイル操作用の コマンド(実際のところ、shell の内蔵コマンドで必要な作業はほぼ可能だと 思いますが)を静的リンクで作っておくことも「治療よりも予防」的な準備と して役立つかも知れません。 <item> もし、ELF の開発を追いかけていたなら、<tt>/lib/elf</tt> に ELF 用のライブラリ(通常は <tt>libc.so.4</tt> など)があるかも知れません。これらのラ イブラリを使うアプリケーションは再コンパイルする必要があります。その上 でこのディレクトリは削除しましょう。<tt>/lib/elf</tt> ディレクトリは不 要です。 <item> 最近の Linux では `FSSTND(ファイルシステムスタンダード)' に従っ て、標準的なファイルシステムは配置されるようになってきましたが、そうでな いシステムもまだまだあることでしょう。もし以下の説明で `<tt>/sbin/</tt><em>何たら</em>' を使うようになっているのに、自分のシ ステムには <tt>/sbin</tt> ディレクトリが無い場合、それらのプログラムは <tt>/bin</tt> か <tt>/etc</tt> にあるはずです。新しいプログラムをイン ストールする場合、特にこの問題には注意してください。コマンドを検索する パスリストで <tt>/etc</tt> が <tt>/sbin</tt> よりも前になっていれば、 知らないうちに(<tt>/etc/にある</tt>)古いバージョンのコマンドを起動して しまい、妙なエラーを起す場合があります。 <item> ELF へ移行する際には誰もコンピュータを使っていない時間を選ぶか シングル・ユーザーモードで行いましょう。間違いを起さないように、フロッ ピーからブートして作業するのもいいアイデアでしょう。でも、私個人として は<bf>多少の</bf>の面白い要素も残しておきたいと思っています :-) </itemize> <sect1> 必要なものは、、、 <p> 必要なパッケージは、<url url="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/"> や <url url="ftp://sunsite.unc.edu/pub/Linux/GCC/"> から入手可能です。両サイト とも多くの場所にミラーされていますので、可能なかぎり近くにあるミラーサ イト[訳注:日本ならば<url url="ftp://ftp.iij.ad.jp/pub/linux/sunsite/GCC/"> や <url url="ftp://ftp.spin.ad.jp/pub/linux/sunsite.unc.edu/GCC/"> など ] から探してください。その方があなたにとっても、みんなにとっても、結局速く 入手できることになります。 以下に示すパッケージ(リストにあがっているバージョンかより新しいもの)が 必要です。これらをダウンロードして、それぞれに付属している文書を読んで みてください:必要な文書はたいてい <tt/release./<em/packagename/ とい う名前になっています。以下に示しているバージョンよりも新しいバージョン を入手した場合、必ずリリースノートに目を通してください。それら新しいバー ジョンではインストールの方法が変っているかも知れません。 プログラムは常にソースからコンパイルするという人でも、以下に示すプログ ラムはバイナリ版を入手してお使いになることを強くお勧めします。これらの プログラムのほとんどは a.out 版のシステムで ELF 形式を生成するようには 設定されておらず、a.out の環境でコンパイルしようとしても無駄です。 <sect2> 絶対に必要なもの <p> <itemize> <item> <tt>ld.so-1.7.14.tar.gz</tt> --- 新しい動的リンカ。ソースとバイ ナリが 入っています。これ以降のバージョンでは a.out バイナリを使う場合 でもカーネルに ELF サポート機能を組みこんでおく必要があります。もし 1.8.1 やそれよりも新しいバージョンをお持ちの場合はインストールする<bf> 前に </bf>カーネルに ELF サポート機能が組みこまれているかを確認してください。 <item> <tt>libc-5.3.12.bin.tar.gz</tt> --- ELF 形式の共有ライブラリで C と数学ライブラリ、その他関連する静的ライブラリやそれらを使ってプログ ラムをコンパイルするのに必要なインクルードファイルが入っています。必要 でしたらソースコードも入手できますが、コンパイルするには時間がかかりま すし、ELF システムを持っていないとコンパイルすることは不可能でしょう。 <item> <tt/gcc-2.7.2.bin.tar.gz/ --- ELF 対応の C コンパイラ。新しいディ レクトリ・レイアウトを理解する a.out 対応の C コンパイラも入っています。 gcc を自分でコンパイルしたい場合(やるとしても ELF 環境に移行してからの 方が簡単だと気づくでしょう)、GNU のオリジナルのソースコードに <tt>gcc-2.7.2-linux.diff.gz</tt> パッチをあてた方がいいでしょう。 <item> <tt>/binutils-2.6.0.12.bin.tar.gz</tt> --- Linux 用にパッチ をあてた GNU バイナリユーティリティです。このパッケージには <tt>gas</tt> や <tt>ld</tt>、<tt>strings</tt> などのプログラムが含まれ ており、C コンパイラを使うには必須になっています。素のままの GNU binutilities (例えば <tt>prep.ai.mit.edu</tt> にあるような)では代りに ならないことごに御注意ください。どうしても自分でコンパイルしたい場合は GNU のものではなく、Linux 用にパッチを当てた <tt>binutils-2.6.0.12.tar.gz</tt> を使ってください。 <item> <tt>ncurses-1.9.9e.tar.gz</tt> --- SVR4 互換の curses ライブラ リで、これからの Linux 用「標準 curses ライブラリ」であると考えられて います。ソースコードは <url url="ftp://prep.ai.mit.edu/gnu/"> のような GNU のサイト、あるいは <url url="ftp://ftp.netcom.com/pub/zm/zmbenhal"> から入手でき、 <tt>tsx-11</tt> にはバイナリパッケージも用意されています。このパッケー ジをインストールする時には既に完全に ELF 化された開発環境に移行してい るはずなので、マシンパワーがある場合はソースコードを入手した方がいいで しょう。 <item> <tt>gdbm-1.7.3.tar.gz</tt> --- Unix の標準となっている dbm や ndbm ルーチンと互換の、拡張ハッシュ機能を持ったデータベースルーチンです。ソー スコードは <url url="ftp://prep.ai.mit.edu/gnu/"> から入手できます。共 有ライブラリ版を作るには <url url="ftp://ftp.uk.linux.org/pub/Linux/libc/non-core/gdbm.patch"> を当 ててください。このパッチはその他いくつかのバグを修正しています (Makefile にある一文字の typo や間違った種類のファイルロッキングを使う 傾向など)。 </itemize> <sect2> その他 <p> 上記以外にも、必須ではありませんが入手しておいた方がいいライブラリ やファイルがいくつかあります。以下に示すものは ELF で使うためにバージョ ンアップしなければならない類いのプログラムです。この文書の後半では、そ のままでも使えるものの、ELF 形式でコンパイルするには修正やバージョンアッ プが必要なプログラムを紹介します。ネットとの接続が遅い場合(例えばフロッ ピーの箱を抱えて 5 分間歩いているくらい時間のかかるような)、以下のファ イルは飛ばして、設定を終える前にこの文書の後半部にあるそれぞれのプログ ラムについての記述と合せてチェックしてください。 <itemize> <item> <bf>a.out 互換</bf>ライブラリパッケージ、<tt>libc.so-4.7.6</tt>。 このパッケージが「オプション」になっているのは、手元にある既存のバイナ リを動かすことのできる a.out ライブラリがあれば、それはそのまま使える からです。このライブラリは何らかの理由で今後も a.out 形式のプログラム を開発せねばならない時に必要になります。 <item><bf>BSD curses</bf> <tt>libcurses.so.1</tt> を必要とするバイナリがあれば、これが古い BSD curses ライブラリです。このライブラリのソースコードは今のところ見つかっ ていないのですが、このライブラリでしか動かないプログラムはごく稀なはず です。その種のプログラムがあれば、ncurses を使うようにコンパイルし直し た方がいいでしょう。そうできない場合は <tt>libcurses.so</tt> が <tt>tsx-11</tt> とそのミラーサイトにある <tt>libc-5.0.9.bin.tar.gz</tt>に含まれています。 <item> <bf>Berkeley db</bf> 新しい 4.4 BSD 用 <tt>libdb</tt> データベースルーチンです。ソースコー ドは <url url="ftp://ftp.cs.berekeley.edu/ucb/4bsd/db.1.85.tar.gz/"> で、Linux の共有ライブラリ用のパッチは <url url="ftp://ftp.uk.linux.org/pub/Linux/libc/non-core/db.patch"> にあり ます。 <item> <bf>C++ 用のプログラム</bf> <tt>gcc</tt> パッケージは <tt>g++</tt> と共に配布されていますが、有用 な C++ ソフトウェアをコンパイルするには <tt>libg++-2.7.1.4.bin.tar.gz </tt> が必要です。私自身は C++ を使っていませんが、聞くところによると、 このライブラリをソースコードからコンパイルするのは結構大変だそうです。 ですから、バイナリ版をお勧めします。 <item> <bf>GNU 互換の termcap</bf> ncurses への移行は ELF への移行と同時に起ったわけではありません。他の 人が作ったプログラムや使い続けたいアプリケーションの中にはこのライブラ リを使っているものがあるかも知れません。<tt>gdb</tt> がそのいい例です。 共有ライブラリをデバッグしたいけれど、gdb が自分自身へリンクしているラ イブラリを前にして混乱するような場合、静的にリンクしたバイナリを使うべ きでしょう。その場合、本当の termcap は ncurses に含まれている termcap 互換のルーチンに比べてずっと小さいことに気づくでしょう。 <tt>termcap-2.0.8.tar.gz</tt> は <tt>tsx-11</tt> から入手できます。こ れは GNU Termcap とは<bf>異なり</bf>ますが、完全に互換です(違いはエラー チェックの部分だけです)。これはソースコードのパッケージになっています。 <item> <bf>MAKEDEV</bf> ある状態で起動すると、MAKEDEV は既存のデバイス ファイルを削除した上で再度作成することがあります。<tt>/dev/zero</tt> を削除してしまえば、いくつかのバージョンの <tt>ld-linux.so.1</tt> が動 かなくなります。新しいバージョンの MAKEDEV は <url url="ftp://sunsite.unc.edu/pub/Linux/system/Admin/MAKEDEV-C-1.5.tar.gz"> か <url url="ftp://sunsite.unc.edu/pub/Linux/system/Admin/MAKEDEV-2.2.tar.gz">. にあります。 <item> <tt>modules-2.0.0</tt> モジュールを使っている場合、binutils をバージョンアップすれば 1.3.69 以前のモジュール・ユーティリティは使用できなくなります。新しいモジュー ル・ユーティリティは <url url="http://www.pi.se/blox/"> にあります。 <item> いろいろな共有ライブラリを含む <bf>X ウィンドウシステム</bf>。 新しいプログラムは ELF 形式になり、ELF 形式のプログラムは a.out ライブ ラリでは使用できませんので、X に関するプログラムを開発する場合、新しい X ウィンドウシステム一式をインストールする必要があります。XFree86 3.1.2 は a.out と ELF の双方の形式で提供されています。XFree86 の配布元 は <tt>ftp.xfree86.org</tt>ですが、国内にも多数のミラーサイトがありま す(例えば <tt>ftp.iij.ad.jp</tt>)ので、ネットワーク的に近いサイトから 入手してください。これらのサイトから<tt>common</tt>と<tt>elf</tt>ディ レクトリ以下を入手したら、<tt>/usr/X11R6/lib/X11/config/linux.cf</tt> ファイルの中の以下の2行の<tt>NO</tt>のところを <tscreen><verb> #define LinuxElfDefault NO #define UseElfFormat NO </verb></tscreen> <tt>YES</tt>にしてください。そうしないと xpm をコンパイルする際に <tt>jumpas</tt> で昔の名残りの奇妙なエラーが生じます。現在の XFree86 のバイナリは ELF 化された termcap ライブラリ<tt>libtermcap.so.2</tt> がインストールされている必要があることに注意してください。 Motif を使っている場合は、ELF 化された Motif ライブラリを提供する予定 があるかベンダーに問いあわせてください。私は Motif は使っていないので 何の役にも立てません。 <item> ELF 化と同時に Linux 2.0 へアップグレードする場合、カーネルのソー スコードと共に配布されている <tt>Documentation/Changes</tt> ファイルを 忘れずにチェックして、必要なものがどこで入手できるか調べてください。 </itemize> <sect1>ファイルシステムの再調整 <p> え〜っと、私が以下で「削除する」と言った場合、「バックアップを取っ てから削除する」と読みかえてください :-) まず、深呼吸して、、 <p> <bf/エッセンス --- バイナリ・インストール/ <enum> <item> a.out バイナリを移動するためのディレクトリを作成 <tscreen><verb> mkdir -p /usr/i486-linuxaout/bin mkdir -p /usr/i486-linuxaout/include mkdir -p /usr/i486-linuxaout/lib mkdir /lib-aout </verb></tscreen> <item> 動的リンカのパッケージ <tt>ld.so-1.7.14</tt> をいつものソースコー ドを置いている場所で展開し、取り出された <tt>ld.so-1.7.14/instldso.sh</tt> スクリプトを読んでください。本当に標 準的なシステムをお使いなら、<tt>sh instldso.sh</tt> を実行してインストー ルすることができますが、何か非標準的なものを組みこんでいる場合、手動で インストールすることになります。「何か非標準的なもの」とは、 <itemize> <item> zsh (いくつかのバージョンの zsh は <tt>$VERSION</tt> と いう変数を定義しており、<tt>instldso.sh</tt> が混乱するようです) <item> <tt>/lib/elf</tt> から <tt>/lib</tt> へのシンボリックリンク(これは必要 なわけではありませんが、レスキューディスクが必要になるような場合には多 少の慰めになるかも知れません) </itemize> <item><tt>/etc/ld.so.conf</tt> を修正して、 <tt>/usr/i486-linuxaout/lib</tt> を加え(必要ならば <tt>/lib-aout</tt> も加え)、<tt>/sbin/ldconfig -v </tt> を再実行して、新しいディレクトリ を探しにいくかチェックします。 <item> <tt>/usr/*/lib</tt> にある全ての a.out 形式の「ライブラリ」を <tt>/usr/i486-linuxaout/lib</tt> に移します。移すものは <tt>lib*.so*</tt> や <tt>lib*.sa*</tt>、<tt>lib*.a</tt> などの「ライブ ラリ」であって、その他のファイルを移す必要はありません。 <tt>/usr/lib/gcc-lib</tt> などもまだ動かしてはいけません。 <item>次に <tt>/lib</tt> をチェックします。<tt>libc.so*</tt> や <tt>libm.so*</tt>、<tt>libdl.so*</tt> はそのままにしておきます。X のラ イブラリ(<tt>libX*.so.3*</tt>へのシンボリックリンクもそのままにしてお きましょう --- <tt>XView</tt> 等のプログラムがそれらのライブラリを使っ ているかも知れません。<tt>ld.so*</tt> 、<tt>ld-linux.so*</tt> など <tt>ld</tt> で始まっているファイルもそのままにしておきます。残りのライ ブラリについては(もしあれば): ルートパーティションに <tt>/usr</tt> が あれば、そこにあるファイルは <tt>/usr/i486-linuxaout/lib</tt> に移しま す。<tt>/usr</tt> が別パーティションにマウントされていれば、 <tt>/lib-aout</tt> に移します。これで <tt>ldconfig -v</tt> してみてく ださい。 <item> binutils をインストールする準備として、もし <tt>/usr/lib/ldscripts</tt> ディレクトリがあれば削除します(binutils が このディレクトリを新たに作ります) <item> <tt>/usr/bin</tt> にある(<tt/ld86/ と <tt/as86/ 以外の)全ての <tt/ld/ と <tt/as/ のコピーを削除します。 <item> <tt>/usr/include</tt> 以下のディレクトリを削除します。標準的な システムでは、ここにあるファイルのいくつかはシステムの「核」となる機能 を担っており、libc と共に配布されています。それ以外にも、あなた自身が インストールしたり、使っているディストリビューションの作成者がインストー ルしたファイルもあるはずです。これらを整理するために、0 から作り直すこ とをお勧めします。まず既存の<tt>/usr/include</tt>を <tt>/usr/include.old</tt>に変更し、<tt>libc-5.2.18.bin.tar.gz</tt>をルー トディレクトリで展開します。 <item> binutils パッケージをインストールします。このためには <tt>tar - xvzf binutils-2.6.0.12.bin.tar.gz -C /</tt> がお勧めの方法です。 <item> gcc パッケージはルートディレクトリで展開する必要があります。gcc パッケージはいくつかのファイルを <tt>/usr/bin</tt> に、残りの多くのファ イルを <tt>/usr/lib/gcc-lib/i486-linux/2.7.2</tt> と <tt>/usr/lib/gcc-lib/i486-linuxaout/2.7.2</tt> にインストールします。 gcc をインストールするには、まず <tscreen><verb> $ tar ztf gcc-2.7.2.bin.tar.gz </verb></tscreen> として、何が入っているかをチェックしてください。残しておきたいファイル に上書きするようであれば(例えば Gnu ADA をインストールしていれば <tt>/usr/bin/gcc</tt> を残しておきたいでしょう)、まずそれらのファイル を安全な所に移します。その上で、 <tscreen><verb> # tar -zxf gcc-2.7.2.bin.tar.gz -C / </verb></tscreen> とします。この時点で、<tt>gcc -v</tt> して gcc のバージョンを確かめた り、テスト用のプログラムをコンパイルして、きちんと動いているかチェック してください。 <tscreen><verb> $ 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 </verb></tscreen> 次に伝統的な ``Hello, world'' プログラムを試してください。そのプログラ ムを <tt>gcc</tt> や <tt>gcc -b i486-linuxaout</tt> で、コンパイルし、 a.out と ELFのコンパイラが正しく設定されているか確認してみましょう。 終りましたかって?もう少し頑張って。まだいくつかのライブラリが残ってい ます。また、シンボリックリンクをごちゃごちゃ張らないといけません。頑張っ て、、 <p> <bf/ シンボリックリンク/ <item> いくつかのプログラム(特にいくつかの X 関連プログラム)は <tt>/lib/cpp</tt> を使います。<tt>/lib/cpp</tt> は Linux では <tt>/usr/lib/gcc-lib/i486-linux</tt><em>version</><tt>/cpp</tt>にあり ます。ここまでの段階で <tt>/lib</tt> の下にあるシンボリックリンクは全 て削除しているはずなので、リンクを張り直す必要があります。 <tscreen><verb> # cd /lib # ln -s /usr/lib/gcc-lib/i486-linux/2.7.2/cpp . </verb></tscreen> <item> <tt>/usr/include</tt> 以下を <tt>/usr/include.old</tt> 以下に移 すと、カーネルのソースコードへのシンボリックリンクが失なわれるので、 <tscreen><verb> # cd /usr/include # ln -s ../src/linux/include/linux . # ln -s ../src/linux/include/asm . </verb></tscreen> としてリンクを張り直してください。 (ここではカーネルのソースコードは <tt>/usr/src/linux</tt> にあると仮定 しています。そうでない場合、適切な場所を指定してください) <item> FSSTND の連中は、ここでも <tt>utmp</tt> と <tt>wtmp</tt> ファイ ルを <tt>/var/adm</tt> から <tt>/var/run</tt> と <tt>/var/log</tt> に それぞれ移すことにしました。必要に応じて <tt>/var/log</tt> や <tt>/var/adm</tt> を作り、<tt>utmp</tt> や <tt>wtmp</tt> の現在位置へ リンクを張るようにしてください。私は以下の <tt>ls -l</tt> に示すような 配置にしました。 <tscreen><verb> $ 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 </verb></tscreen> FSSTND の全体については <url url="ftp://sunsite.unc.edu/pub/Linux/docs/fsstnd/" name="sunsite にあ る LDP のアーカイブ">などにある文書をご覧ください。 <p> <bf>おめでとう!</bf> ここまでで(多少なりとも)完全に機能する ELF の開発環境が完成したはずで す。一歩下って、しばらく静かに喜びをかみしめましょう。 <p> <bf>重要なソースコードのパッケージ</bf> <item> <bf>ncurses のインストール</bf>はかなり時間のかかる仕事です。もっ とも、その大部分の時間はコンパイルしながらネットニュースを読むことに費 すことができますが。tar ファイルを展開したら <tt>INSTALL</tt> ファイル を、自分が「Linux 何たらシステム」のディストリビューションの作成/まと め役である、と思って読んでみましょう。すなわち、コンパイルの際には、多 分、以下のようなコマンドラインで設定する必要がある、ということです。 <tscreen><verb> $ ./configure --with-normal --with-shared --disable-termcap --enable-overwrite --prefix=/usr </verb></tscreen> デフォルトになっているターミナルの種類にも注意しましょう。1.3 と 2.0 のカーネルでは、起動時のデフォルトのターミナルは <tt>linux</tt> になっ ています。場合によっては <tt>/etc/inittab</tt> を修正して <tt>console</tt> や <tt>getty</tt> にしなければならないかも知れません。 ルートパーティションのあるハードディスクに <tt>/usr/lib/terminfo</tt> が無い場合、ncurses の `fallback' 機能でごまかす必要があるでしょう。こ の機能は上述の <tt>INSTALL</tt> ファイルに説明してあり、単純ですが、退 屈な仕事になります(ライブラリを 2 度作成する必要があります)。fallback として <tt>linux</tt> や <tt>vt100</tt> を使えばいい場合、幸いなことに 既存の <tt>fallback.c</tt>に置き替え可能な <tt>fallback.c</tt> が <url url="ftp://ftp.uk.linux.org/pub/Linux/libc/non-core/fallback.c" name="ftp.uk.linux.org"> に用意されています。 ncurses をインストールした後、<tt>/usr/lib</tt> 以下で多少面倒な仕事を する必要があります。これは不定形な作業なので、手でやるのが最も簡単です。 バージョン番号が多少不一致になっていることに注意してください。これは醜 いですが、健康に害があるわけではありません。 <enum> <item> <tt>/usr/lib/libncurses.so.1.9.9e</tt> を <tt>/lib</tt> に移し、 シングルユーザーモードでも curses プログラムが動けるようにします。ルー トパーティション に <tt>/usr/lib</tt> がある場合、特にこの作業は不要で すが、やっておいても害はありません。 <item> <tt>/lib</tt> ディレクトリで <tt>libncurses.so.1.9.9e</tt> から <tt>/libncurses.so.3.0</tt> へリンクを張ります。 <item> その他、<tt>/lib/libncurses.so.3.0</tt> から <tt>/usr/lib/libncurses.so</tt> や <tt>/usr/lib/libcurses.so</tt> 、 <tt>/usr/lib/libtermcap.so</tt> へのリンクも必要かも知れません。 </enum> 考えるのがメンドウな人向けに簡単に言うと、以下のような作業になります。 <tscreen><verb> # 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 </verb></tscreen> <item><bf>gdbm</bf> のインストール。ソースコード用のディレクトリでソー スコードを展開し、<tt>gdbm.patch</tt> をあて、<tt>README</tt> と <tt>INSTALL</tt> ファイルに目を通します。 構築の手順は以下のようなものになるはずです。 <tscreen><verb> $ 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 </verb></tscreen> 最後の 2 つは古いバージョンとの互換性を保つためです。最近のディスト リビューションでは <tt>libgdbm.so.2</tt> というバージョンになっていま すが、これは <tt>libdgbm.so.1</tt> と全く同じコードで、バージョン番号 だけが歴史的な理由から間違えて付けられているものです。 <p> <bf>オプションのソースコードパッケージ</bf> <p> 一般に、それぞれのパッケージに付属の指示にしたがってインストールすれば 大丈夫なので、ここで繰り返すことはしません。ただし、例外が 2 つあり、 <item> <bf>GNU 風の termcap</bf> が必要な場合(厳密に言うと必須ではあり ませんが、実際には XFree86 のバイナリが必要とするので、ほぼ必須でしょ う)、ソースコードから構築する必要がありますが、必要な作業は以下に示す 程度です。 <tscreen><verb> $ tar zxf termcap-2.0.8.tar.gz $ cd termcap-2.0.8 $ make $ su # cp libtermcap.so.2.0.8 /usr/lib # ldconfig </verb></tscreen> <bf>決して</bf> <tt>make install</tt> は実行しないように。<tt>make install</tt> すると ncurses のプログラムを一部上書きしてしまいます。こ のライブラリを使うようにコンパイルされた既存のバイナリを使うのではなく、 新たにこのライブラリを使ってプログラムをコンパイルする場合、ヘッダーファ イルとスタティック・ライブラリをどこか別の場所に用意して <tt>-I</tt> と <tt>-L</tt> フラグを使ってコンパイル時にその場所を明示するようにし てください。この部分は他の部分に比べて記述が曖昧だと思われるかも知れま せんが、それには理由があります。すなわち、よほどの理由がないかぎり、 termcap を使い続けることはお勧めできないからです。 <item> <tt>libdb</tt> は以下のように作成します。 <tscreen><verb> $ 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 </verb></tscreen> 注意点としては <itemize> <item> <tt>PORT/linux/OTHER-PATCHES</tt> をあててはいけません。 <tt>db.patch</tt> に含まれています。 <item> gdbm のインクルードファイルと衝突するので、インクルードファイル は <tt>/usr/include</tt> 以外の部分にインストールし、<tt>libdb</tt> が 必要なプログラムをコンパイルする場合、C コンパイラのコマンドラインに <tt>-I/usr/include/db</tt> と指定してください。 </itemize> </enum> <sect1> どういう風になるのか(ディレクトリ構成のアウトライン) <p> 以下に示すものは今までにインストールしてきたファイルのかなりおおま かな概観です。トラブルシューティングや削除すべきものを決める際にご利用 ください。 <sect2><tt> /lib </tt> <p><itemize> <item>動的リンカ <tt>ld.so</tt> (a.out 用)と <tt>ld-linux.so.1</tt> (ELF 用)。 両者ともシンボリックリンクかも知れませんが、指しているファ イルがきちんと存在することを確認してください。 <item>基本的な共有ライブラリ <tt>libc.so.4</tt>と <tt>libm.so.4</tt>(a.out)。これらはシンボリックリンクになっていますが、 正しいファイルを指しているか確認してください。 <item>基本的な共有ライブラリ <tt>libc.so.5</tt> と <tt>libm.so.5</tt>、 <tt>libdl.so.1</tt>、<tt>libncurses.so.1</tt>、 <tt>libtermcap.so.2</tt> (ELF 用)。これらもまたシンボリックリンクになっ ているので、正しいファイルを指しているか確認してください。 </itemize> <sect2><tt>/usr/lib</tt> <p><itemize> <item>かってここにあったライブラリ以外のファイルとディレクトリ <item><tt>libbfd.so*</tt>, <tt>libdb.so*</tt>, <tt>libgdbm.so*</tt> と いった ELF 形式の共有ライブラリ <item> さまざまなシンボリックリンク。<tt>/lib</tt> や <tt>/usr/lib</tt> にあるライブラリへのシンボリックリンクがここに必要で す。リンクの名前は本当のファイル名からバージョン番号を取ったものです。 例えば、<tt>libc</tt> について言うと、 <tscreen><verb> lrwxrwxrwx 1 root root 14 May 2 20:09 /lib/libc.so.5 -> libc.so.5.3.12 -rwxr-xr-x 1 bin bin 583795 Apr 25 06:15 /lib/libc.so.5.3.12 lrwxrwxrwx 1 root root 12 Oct 27 1995 /usr/lib/libc.so -> /lib/libc.so.5 </verb></tscreen> となります。これらのリンクは、リンク時に <tt>ld</tt>が利用します。 <item> <tt>libbsd.a</tt>、<tt>libgmon.a</tt>、<tt>libmcheck.a</tt> と <tt>/lib</tt> や <tt>/usr/lib</tt> にある ELF 形式の共有ライブラリ各々 に用意されている<tt>lib*.a</tt> ライブラリ。これらは ELF 形式の静的ラ イブラリです。大部分の人にとっては、共有ライブラリと同じ静的ライブラリ があってもそれほど有難味はないでしょう。特に ELF 形式を使う場合には。 ELF では、共有ライブラリを使いながら <tt>gcc -g</tt> オプションを指定 することも可能なので、静的ライブラリを組みこむべき理由はほとんどありま せん。でも、ライブラリ自身をデバッグしたくなる日のために、それらの静的 ライブラリは残しておいた方がいいでしょう。 <item> <tt>crt0.o</tt> と <tt>gcrt0.o</tt>。これらは a.out 形式の「プ ログラム起動用の」ファイルです。特に避けることをしなければ、全ての a.out 形式のプログラムにこれらのうちの一つのファイルがまずリンクされる ことになります。 <item> <tt>crt1.o</tt>、<tt>crtbegin.o</tt>、<tt>crtbeginS.o</tt>、 <tt>crtend.o</tt>、<tt>crtendS.o</tt>、<tt>crti.o</tt>、 <tt>crtn.o</tt>、<tt>gcrt1.o</tt>。これらは ELF 用の起動用ファイルです。 これらは上記 <tt>*crt0.o</tt> と同様の機能を ELF 形式のプログラムに対 して行います。 </itemize> <sect2><tt> /usr/lib/ldscripts </tt> <p><itemize> <item> このディレクトリは、その名が示す通り、 <tt>ld</tt> 用の各種ドラ イバスクリプトを置くところです。このディレクトリには以下のようなファイ ルがあります。 <tscreen><verb> $ ls /usr/lib/ldscripts/ elf_i386.x elf_i386.xs i386coff.xn i386linux.xbn elf_i386.xbn elf_i386.xu i386coff.xr i386linux.xn elf_i386.xn i386coff.x i386coff.xu i386linux.xr elf_i386.xr i386coff.xbn i386linux.x i386linux.xu </verb></tscreen> </itemize> <sect2><tt>/usr/i486-linux/bin</tt> <p><itemize> <item> <tt/ar/, <tt/as/, <tt/gasp/, <tt/ld/, <tt/nm/, <tt/ranlib/, <tt/strip/ これらは <tt>/usr/bin</tt> にある実際のバイナリ操作用プログラムへのシ ンボリックリンクです。 </itemize> <sect2><tt>/usr/i486-linuxaout/bin</tt> <p><itemize> <item> a.out 用のアセンブラ <tt>as</tt> と、そのマクロ・プリプロセッサ <tt>gasp</tt> があります。 <item> <tt/ar/, <tt/ld/, <tt/nm/, <tt/ranlib/, <tt/strip/ --- これらは <tt>/usr/bin</tt> にある実際のバイナリ操作用プログラムへのシンボリック リンクです。 </itemize> <sect2><tt>/usr/i486-linux/lib</tt> <p><itemize> <item> <tt>ldscripts</tt> は <tt>/usr/lib/ldscripts</tt> へのシンボリッ クリンクです。 </itemize> <sect2><tt>/usr/i486-linuxaout/lib</tt> <p><itemize> <item> a.out 用の共有ライブラリ本体の <tt>lib*.so*</tt> があります。 a.out 形式のプログラムを動かすには必須です。 <item> <tt>lib*.sa</tt> は a.out 形式の共有ファイルのスタブ(stub)です。 共有ライブラリを使う プログラムを a.out 形式にコンパイルするために必要 です。a.out 形式にコンパイルすることが無ければ削除してしまっても構いま せん。 <item> <tt>lib*.a</tt> は a.out 用の静的ライブラリです。a.out 形式で静 的にリンクされたバイナリを作るために必要です(例えば <tt>-g</tt> オプショ ン付きでコンパイルする時)。このファイルも a.out 形式のプログラムを作成 する必要がなければ削除して構いません。 <item> <tt>ldscripts</tt> は <tt>/usr/lib/ldscripts</tt> へのシンボリッ クリンクです。 </itemize> <sect2><tt>/usr/lib/gcc-lib/i486-linux/2.7.2</tt> <p><itemize> <item> このディレクトリには ELF 形式のプログラムをコンパイルするための gcc 2.7.2 が収められています。 </itemize> <sect2><tt>/usr/lib/gcc-lib/i486-linuxaout/2.7.2</tt> <p><itemize> <item> このディレクトリには a.out 形式のバイナリを出力するための gcc 2.7.2 一式が収められています。この gcc は新しい(ここで示したような)ディ レクトリ構成を理解する機能を持っています。もし a.out にコンパイルする 必要がない場合、このディレクトリを削除すれば約 4MB 節約できます。パッ チ済みでない 1.2 シリーズのカーネルをコンパイルする場合には、このコン パイラが必要なことをお忘れなく。 </itemize> <sect1> よくあるエラー ――― あわてないで! <p> (以下の内容の大部分は親切なメールでいただいたものです) <!-- FIXME: no mention of _h_errno yet --> <descrip> <tag/何か間違ったものを動かして、何も動かなくなってしまった!/ その場合でも shell は動いているはずなので、多少工夫すれば shell の組み こみ機能だけでかなりの仕事をこなすことが可能です。<tt>echo *</tt> は <tt>ls</tt> の代わりに使え、<tt>echo >>filename</tt> はファイル に書き足すのに使えます。<tt>ldconfig</tt> も静的にリンクされていること をお忘れなく。例えば、<tt>libc.so.4</tt> を間違って <tt>lib-aout</tt> ディレクトリに移してしまった場合、<tt>echo &dquot;/lib-aout&dquot; >>/etc/ld.so.conf ; ldconfig -v</tt>すれば、復旧します。 <tt>/lib/ld.so</tt> を動かしてしまった場合、 静的にリンクされた ln が あれば、<tt>sln /sillyplace/ld.so /lib/ld.so</tt>することで、多分復旧 するでしょう。 <tag><tt> bad address </tt></tag> ELF 形式のプログラムを動かそうとすると、いつも<tt>bad address</tt> エ ラーになる場合、多分、カーネルの 1.3.<em>x</em> の <em>x</em> <3 の バージョンをお使いなのでしょうが、そのバージョンを使ってはいけません。 それらは多分、最悪のバージョンの一つです。2.0 へバージョンアップするか 1.2.13 にバージョンを落しましょう。似たような環境でカーネルパニックが 発生すると報告している人たちもいますが、私は詳しく調べていません。なぜ なら、開発版のバージョンを使いたいとも思わないし、使う必要があるとも感 じないので、最新版の追っかけはしていないからです。 <tag><tt> gcc: installation problem, cannot exec <em>something</em>: No such file or directory</tt></tag> a.out 形式でコンパイルしようとして(<bf>something</bf> の部分はたいてい の場合 <tt>cpp</tt> か <tt>cc1</tt> のはずです)、このエラーが生じる場 合、実際に <tt>cpp</tt> や <tt>cc1</tt> に問題があるか、 <tscreen><verb> $ gcc -b -i486-linuxaout </verb></tscreen> のように入力したのでしょう。実際には <tscreen><verb> $ gcc -b i486-linuxaout </verb></tscreen> と入力しなければなりません。`i486'の部分はダッシュではじまらないことに 注意してください。 <tag><tt/make: *** No targets specified and no makefile found. Stop./</tag> このエラーが出る場合、<tt>make</tt> にパッチをあてて再コンパイルしてい ないか、古いバージョンの <tt>make</tt> がシステムのどこかに残っている のでしょう。 <tag><tt> no such file or directory: /usr/bin/gcc </tt></tag> 実際にそのファイルが存在するのにこういうエラーが出る(gcc 以外のプログ ラムでもこうなるかも知れません)。この場合、ELF の動的ローダー <tt>/lib/ld-linux.so.1</tt> をインストールしていないか、何らかの理由で ローダーが読めない状態になっているのでしょう。先に述べたインストールス テップの 2 を読んで <tt>/lib/ld-linux.so.1</tt> を正しくインストールし てください。 <tag><tt> not a ZMAGIC file, skipping </tt></tag> このエラーは <tt>ldconfig</tt> が出しています。古いバージョンの ld.so のパッケージをお使いのようなので、新しいものを入手してください。もう一 度、インストールのステップ 2 を読んでください。 <tag><tt> _setutent: Can't open utmp file </tt></tag> このメッセージは xterm を起動した時に 3 行ずつ出力されることがよくあり ます。インストール手順の最後のあたりにある FSSTND の長文の説明を読んで ください。 </descrip> <sect> プログラムの構築 <sect1> 一般的なプログラム <p> プログラムを ELF 形式でコンパイルする場合、いつものように <tt>gcc</tt> を使います。a.out 形式でコンパイルする場合、<tt>gcc -b i486-linuxaout</tt> としてください。 <tscreen><verb> $ 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 </verb></tscreen> さて、そろそろ「a.out 形式のコンパイラが出力するバイナリのデフォルト名 が <tt>a.out</tt> なら、ELF コンパイラの出力するバイナリのデフォルト名 は何というの?」という質問に答えるべき時でしょう。答は、「やっぱり <tt>a.out</tt>」なんです。残念でしたか? <tt>:-)</tt> <sect1> ライブラリの作り方 <p> <tt>libfoo.so</tt> を共有ライブラリとして構築したい場合、基本的な手順 は以下のようになります。 <tscreen><verb> $ 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 </verb></tscreen> これにより、<tt>libfoo.so.1.0</tt> と呼ばれる共有ライブラリと ld 用の シンボリックリンク(<tt>libfoo.so</tt>)、動的リンカ用のシンボリックリン ク(<tt>libfoo.so.1</tt>)が作成されます。ライブラリのテストの際は、最後 に示したように、現在のディレクトリを <tt>LD_LIBRARY_PATH</tt> に加えて 試してみましょう。 ライブラリが正しく動くことが確認できれば、適切な場所、例えば <tt>/usr/local/lib</tt> に移し、リンクを張り直しましょう。 <tt>libfoo.so</tt> のリンクは <tt>libfoo.so.1</tt> へ張られているので、 バージョン番号のマイナーチェンジがあってもリンクを張り直す必要はありま せん。<tt>libfoo.so.1.0</tt> から <tt>libfoo.so.1</tt> へのリンクは、 たいていのシステムでは <tt>ldconfig</tt> が起動時に更新します。 <tscreen><verb> $ su # cp libfoo.so.1.0 /usr/local/lib # /sbin/ldconfig # ( cd /usr/local/lib ; ln -s libfoo.so.1 libfoo.so ) </verb></tscreen> <sect1> a.out 形式の構築 <p> ELF 環境の中でも古い a.out 形式のバイナリを作成しなければならない 場合があるかも知れません。「普通の」プログラムの場合、必要なことは gcc を起動する時に <tt>-b i486-linuxaout</tt>フラグを使って a.out 用のコン パイラを起動し、(もし) ld を起動する場合は <tt>-m i386linux</tt> フラ グを使います。a.out 形式の DLL 共有ライブラリを未だに必要とする人は、、 可哀想に。私の知る限りでは、一言で言えば「動きません」。別の方法を御存 知ならばメールで私に教えてください。 <sect> ELF 用パッチとELF 化済みのプログラム <p> ここまでで、お好みならば終了することが可能です。ELF 形式のプログラ ムをコンパイルして動かすために必要な環境は全てインストールできました。 「美意識」的な観点やメモリ使用量を最小化するためには、お使いのプログラ ムを全て ELF 形式でコンパイルし直したくなるかも知れません。ELF 形式で の再コンパイルはほとんどのエンドユーザー用のアプリケーションではごく簡 単です。しかしながら、動作環境について何らかの前提のあるプログラムもい くつかあり、それらは以下のような理由でエラーになるかも知れません。 <itemize> <item>アセンブラのアンダスコアの使い方の違い:a.out の実行形式では外部 ラベルには <tt>_</tt>(アンダスコア) が頭に付いていますが、ELF の実行形 式ではそうなっていません。これは、手書きのアセンブラコードを組みこまな い限り問題にはなりません。<tt>_foo</tt> の形のラベルを全て <tt>foo</tt> に翻訳してやるか、(移植性を高めたければ) <tt>EXTERNAL(foo)</tt> のようなマクロを用意して、(<tt>__ELF__</tt> が 定義されていればそのまま変数を返し、定義されていなければ <tt>_</tt> を 付けるようにするのがいいでしょう。 <item>libc 5 と libc 4 の違い。例えば locale サポートへのインターフェ イスは変更されています。 <item>使っているバイナリ形式をアプリケーションや構築過程が参照している 場合。例えば emacs はその一例で、メモリイメージを実行形式としてディス クに書きだすので、実行形式のフォーマットをプログラムが理解している必要 があります。 <item>共有ライブラリや共有ライブラリを含むアプリケーション(X11 が分り やすい例)。これらの場合、ELF 形式で共有ライブラリを作るような方法に修 正する必要があります。 </itemize> とにかく、以下に 2 つのリストを示します。最初のリストは既に ELF 形式の バージョンが作成されているもの(すなわち、ELF 形式でコンパイルするには 新しいバージョンを入手すればいいもの)で、2 つめのリストは第三者からの パッチが必要なプログラムです。 <sect1>アップグレードすればいいもの: <p> <itemize> <item> <bf>Dosemu</bf> 現在では dosemu も ELF 形式で動きます。ただし、Makefile に多少の修正が 必要なようです。最新版の dosemu は <url url="ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/"> から入手できます。 <item> <bf>e2fsutils</bf> e2fs ファイルシステム用の各種ユーティリティ e2fsutils は、バージョン 0.5c 以降のものは変更なく ELF 形式でコンパイルできます。 <item> <bf>Emacs</bf> Emacs には 2 つの潜在的な問題があります。(i) Emacs は、まず最小規模の システムを動かして、必要な lisp ファイルを全て読みこんだ上で、メモリイ メージを実行形式のファイルとして直接ディスクへ書きだす、というかなり変っ た手順で作成されます。(FSF) Emacs 19.29 と XEmacs 19.12(かっては Lucid Emacs と呼ばれていました)は ELF 形式かどうかを自動的に見分けて、正しい 手順で構築されます。(ii) いくつかのバージョンの emacs を ncurses を使 うようにコンパイルする場合、emacs のソースパッケージの <tt>src/s/linux.h</tt> の先頭付近に <tt>#define TERMINFO</tt> の一行を 加えないと、正しく構築されないことがあります。これは 19.31 では必要な いですが、XEmacs 19.13 には必要です。次のバージョン、19.14 では間違い なく修正されることでしょう。 <item> <bf>gdb 4.16</bf> 既存の gdb でも問題なくそのまま使えますが、4.16 で採用された共有ライブ ラリ機能はずっと便利になっています。ですから、もしライブラリ関連の妙な エラーに悩まされている場合、gdb をバージョンアップするのもいいでしょう。 <item> <bf>Kernel 本体</bf> カーネルのバージョン 2.0 以降は ELF 形式で問題なく動きます。カーネル構 築時の設定(<tt>make config</tt>)の時に以下の 2 つの項目に `yes' と答え てください(これは 1.3 でも同じです)。1.2 をまだ使っている場合、次のリ ストに示すパッチを入手してください。 <tscreen><verb> Kernel support for ELF binaries (CONFIG_BINFMT_ELF) [Y/m/n/?] Compile kernel as ELF - if your GCC is ELF-GCC (CONFIG_KERNEL_ELF) [Y/n/?] </verb></tscreen> <item> <bf>perl 5</bf> Perl 5.001m 以降のバージョンは ELF システムで、動的ロード機能も完璧に、 変更なくコンパイルできます。最新版の Perl は CPAN(Comprehensive Perl Archive Network)サイトから入手できます。CPAN は funet でも<url url="ftp://ftp.funet.fi/pub/mirros/perl/CPAN" name="ミラーされています ">、が身近なサイトから入手するようにしてください。 <item><bf>ps</bf> と <bf>top</bf> Procps 0.98 以上のバージョンは ELF 形式をサポートしています(より古いバー ジョンでも動きますが、WCHAN の名前をカーネルから読みとることができませ ん)。2.0 シリーズのカーネルには procps 0.99a 以降のバージョンが必要な ことをお忘れなく。 <item> <bf>util-linux 2.2</bf> に入っている <tt>cal</tt> プログラムは 動きません。tsx-11 にある <url url="ftp://tsx-11.mit.edu/pub/linux/packages/utils" name="version 2.5">以降のバージョンを使ってください。 <item> <bf/Mosaic/ 私自身は Mosaic をコンパイルできる環境にありませんが、NCSA からリリー スされている 2.7b1 以降の Mosaic のバイナリは ELF 形式になっています。 ところが、X の設定が変な風になっていて、通常のシステムでは <tt>libXpm.so.4.5</tt> が見付からない、というエラーになります。最後の バージョン番号(<tt>.5</tt>)が余計なので、単純な修正方法は、emacs など のバイナリファイルを操作できるエディタで直接修正してしまうことでしょう。 <tt>libXpm.so.4.5^@</tt> という文字列を探して(ここで <tt>^@</tt> は NUL キャラクタ --- ASCII の 0 ---です)、<tt>.5</tt> を削除し、ファイル 名の長さが変らないように、注意深く NUL キャラクタの後に 2 つのスペース を追加しましょう。 </itemize> <sect1> パッチが公開されているもの <p> <itemize> <item> <bf>file</bf> file は特に問題なく動きますが、改良の余地があります:<url url="ftp://ftp.uk.linux.org/pub/Linux/libc/non-core/file.patch" name="ftp.uk.linux.org"> にあるパッチをあてれば、バイナリが strip されているかどうかやエンディアンが混在した ELF バイナリかを見分けるこ とも可能になります。 <item> <tt>make-3.74</tt> GNU の ftp サイトにあるソースコードを入手して libc-5.3.12 のリリースノー トにあるパッチをあてるか、<tt>tsx-11</tt> から <tt>make-3.74.gz</tt> のバイナリを入手してください。GNU の make には新しい ELF 版の libc バー ジョンでのみ露呈するバグがあります -- このバグは、実際には古い GNU の libc にあったバグに依存した実装になっているせいで、その libc のバグは つい最近までの Linux の libc にもありました。そのため、古い a.out 版の <tt>make</tt> プログラムを使っている場合は動作しますが、新しい ELF 用 にはパッチが必要です。 GNU Make の開発者たちもこのバグには気付いていて、将来のバージョンでは 修正されるはずです。 <item> <bf>1.2.x カーネル</bf> 1.2.x シリーズのカーネルについては 3 つのオプションがあります。 <enum> <item> Makefile を少し修正して、a.out コンパイラを使うようにします。 <tt>cd /usr/src/linux</tt> し、以下のパッチを切り出して <tt>patch - p1</tt> であててください。以下のパッチを見ながら Makefile を手動で修正 してもかまいません。以下のパッチファイルは簡単に理解できるでしょう (<tt>-</tt> で始まる行を削除して <tt>+</tt> で始まっている行を追加しま す) <tscreen><verb> diff -u linux-1.2.13/Makefile.orig linux/Makefile --- linux-1.2.13/Makefile.orig Wed Aug 16 20:53:26 1995 +++ linux/Makefile Fri Dec 8 16:19:49 1995 @@ -12,9 +12,9 @@ TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) -AS =as -LD =ld -HOSTCC =gcc -I$(TOPDIR)/include -CC =gcc -D__KERNEL__ -I$(TOPDIR)/include +AS =/usr/i486-linuxaout/bin/as +LD =ld -m i386linux +HOSTCC =gcc -b i486-linuxaout -I$(TOPDIR)/include +CC =gcc -b i486-linuxaout -D__KERNEL__ -I$(TOPDIR)/include MAKE =make CPP =$(CC) -E AR =ar </verb></tscreen> あるいは、 <item> H.J.Lu 作のパッチをあてて、カーネルを ELF 形式でコンパイルでき るようにする(この場合、ELF 形式のコアダンプも可能になります)このパッチ は<url url="ftp://ftp.cdrom.com/pub/linux/slackware_source/kernel-source/v1.2/linuxelf-1.2.13.diff.gz"> から入手できます。 1.2 シリーズのカーネルを含んだELF 形式のディストリビューション(RedHat 2.1 や Slackware 3)にはこのパッチが含まれているか、似たパッチが既にあ たっているはずです。 しかし、最善のアイデアは、多分、 <item> 2.0 へバージョンアップしましょう。とにかく 1.2 のころは ELF に ついて配慮されていませんでした。 </enum> 1.2.13 のバージョンを gcc 2.7.2 以上のバージョンでコンパイルする場合、 別の問題も生じます。<tt>asm/io.h</tt> には gcc 2.7.2 でのみ露呈するバ グがあり、修正するためのパッチは <url url="ftp://ftp.uk.linux.org/pub/Linux/libc/misc/io.h"> にあります。 </itemize> <sect>より詳しい情報 <p> <itemize> <item> <url url="GCC-HOWTO.html" name="GCC-HOWTO">には、Linux でプログ ラムを開発する際に有益な情報が多数含まれています(少なくとも私はそう考 えています。私が保守していますから)。GCC-HOWTO は、この文書と同じ場所 にあるはずなので、上記のリンクは相対指定になっています。 <item> <tt>linux-gcc</tt> メーリングリスト(これは <tt>linux.*</tt> のニュー スを受信している場合、<tt>linux.dev.gcc</tt> ニュースグループにもなっ ています)は、自分からは投稿しなくても何が起きているかを知ることのでき る最善の場所でしょう。これは Usenet とは違うので、実際に開発に関わる問 題のみを投稿するようにしてください。メーリングリストに参加するには、 <tt>help</tt> という語を含むメールを <tt>majordomo@vger.rutgers.edu</tt> に送ってください。メーリングリスト のアーカイブは <url url="http://www.linux.ncm.com/linux-gcc/"> にあり ます。 <item> linux-gcc のメーリングリストで何が行なわれているかの情報は、私 が更新を怠らない限り、<url url="http://ftp.uk.linux.org/~barlow/linux/gcc-list.html" name="linux-gcc web page"> にあります。このページには、この HOWTO の最 新版へのリンクもあり、本文の中で参照しているパッチも集めています。米国 や英国の学術サイトへのリンクが細い人たち(英国の学術ネット以外のところ ではたいていそうでしょうけど)用に、このページは <url url="http://www.blackdown.org/elf/elf.html"> にミラーされています。 <item>ELF 形式についての文書が <url url="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ELF.doc.tar.gz" name="tsx-11"> にあります。この文書は多分ファイル形式を理解したい人や デバッグしたい人、バイナリのオブジェクトを直接操作するようなプログラム の作者にもっとも役立つものでしょう。 <item>H.J Lu が書いた <url name="ELF: From The Programmer's Perspective" url="ftp://tsx-11.mit.edu/pub/linux/packages/GCC/elf.latex.tar.gz"> は ELF 形式でプログラムする際に有用な情報がずっと詳しく説明されています。 もし LaTeX を処理できなければ、同じバージョンの PostScript 版がありま す。 <item><bf>ncurses</bf> ライブラリについての情報と terminfo データベー スは<url url="http://www.ccil.org/~esr/ncurses.html" name="Eric Raymond's ncurses resource page"> にあります。 <item> <tt>ld.so</tt> パッケージに含まれている <tt>dlopen(3)</tt> の man page には関連する機能についての説明が書かれています。 </itemize> <sect> その他 <sect1> フィードバックのお願い <p> Feedback は歓迎します。メールは <htmlurl url="mailto:daniel.barlow@linux.org" name="daniel.barlow@linux.org"> へお願いします。秘密のメールを送る必要がある場合、私の <url url="http://ftp.uk.linux.org/~barlow/" name="web pages"> にある PGP の 公開鍵(ID 5F263625)を使ってください。 この文書に答があるべき問題で、答が見つからない場合も私にメールしてくだ さい。この文書の中で触れられるべきではない問題で、私が答を知っているか も知れない問題については、まず <tt>comp.os.linux.*</tt> ニュースグルー プに投稿してみてください。たいていメールの問い合わせにも答えていますが、 メールを無くすこともよくあるので。 私の名前がゴミメーリングリストに載っているのを見た人は削除してくださる ようにお願いします。 <sect1> 翻訳版 <p> この文書の翻訳版を作りたい場合、積極的にやっていただいて構いません が、一言連絡してください。私が話せる言語に翻訳してもらえる可能性は(悲 しいことに)数百分の一でしょうが、それはさておき、私の出来ることはよろ こんでお手伝いします。 <p> 私が知っている翻訳版は: <itemize> <item> <url url="http://www.psico.unipd.it/ildp/docs/HOWTO/ELF-HOWTO.html" name="イタリア語版"> をFavro Renata が翻訳しました。 (その他のイタリア語版 HOWTO も<url url="http://www.psico.unipd.it/ildp/docs/HOWTO/INDEX.html"> にあります。 <item> こじまみつひろが日本語版を作成しました。 <url url="http://jf.gee.kyoto-u.ac.jp/JF/index.html">から入手できます。 </itemize> <sect1> 法的な話題 <p> All trademarks used in this document are acknowledged as being owned by their respective owners. Yow! <p> 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 <tt/<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 <tt/gregh@sunsite.unc.edu/. <p> この文書に現われたトレードマークは全てその所有者に帰属しています。 <p> この文書の原著者である Daniel Barlow の権利は 1988 年に制定された ``COpyright Desings and Patents" 法の 77 条と 78 条に規定されています。 この文書は Daniel Barlow<tt/<daniel.barlow@linux.org>/ が著作権 を有しています。この著作権表示が示される限り、どのような物理的、電子的 媒体を用いて、この文書の全体でも一部だけでも、コピーして再配布すること が可能です。商的利用も許諾され、推奨されますが、そのような場合には著者 まで一言お知らせください。 翻訳やこの文書から派生した文書、あらゆる Linux HOWTO 文書との組みあわ せた文書集なども、この著作権表示によって保護されることになります。すな わち、Linux の HOWTO から派生した作品に対して、その配布を妨げるような 制限を課すことはできません。一定の条件のもとで例外を設けることも可能な ので、詳細については以下に示す Linux HOWTO のコーディネータに尋ねてく ださい。 簡単に言えば、私たちは可能なかぎりの方法でこの文書などの情報を広く知ら せようと考えています。しかしながら、私たちは HOWTO 文書に著作権を設定 し、HOWTO の再配布計画については知らせてもらいたいと思っています。 質問があれば、現在の Linux HOWTO のコーディネータ、Grep Hankins <tt>gregh@sunsite.unc.edu</tt> へ連絡してください。 </article>