[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5. BFD

GNU リンカは, オブジェクトファイルとアーカイブファイルをアクセスするのに BFD ライブラリを使っている. このライブラリは, オブジェクトファイルを 扱う時に, そのオブジェクトファイル形式が何であっても, 同じルーチンを 使うのを可能にする. 異なるオブジェクトファイル形式は, 単に新しい BFD バックエンドをつくって, それをライブラリに追加するだけで 対応できる. ただし, 実行時のメモリを節約するために, リンカや関係ツールは, 普通は利用可能なオブジェクトファイル形式の一部だけに対応するように コンフィギュレーションされる. objdump -i (see section `objdump' in The GNU Binary Utilities) を使うと, 読者のところのコンフィギュレーションで利用可能な 形式を全て表示する.

大概の実装がそうであるように, BFD はたくさんの矛盾する要件の折衷案 と言える. BFD の設計に一番影響を及ぼす要因は, 効率である. 形式間の変換に使われる時間は全て, BFD が入っていなかった頃には 費やされることのなかった時間である. これは, 抽象化による恩恵で 部分的には相殺される. BFD によりアプリケーションとバックエンドが 簡単になるので, 速度を追求するためにアルゴリズムを改善するのに, 時間と注意をさらに振り向けられるようになったのである.

BFD による方法の小さなゆがみで読者が気をつけなければならないのは, 情報損失の可能性である. BFD の仕組みを使う時には有用な情報が失われる 可能性がある場所が二箇所ある. 変換時と出力時である. See section 5.1.1 情報の損失.

5.1 動作の仕組み: BFD の概要  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1 動作の仕組み: BFD の概要

オブジェクト・ファイルがオープンされると、BFD のサブルーチン群は 自動的に入力オブジェクトファイルの形式を決定する。次に、 オブジェクトファイルのデータ構造の要素をアクセスするのに使われる ルーチン群へのポインタによる記述子をメモリ中に構築する。

オブジェクトファイルの別の情報が必要になると、BFD はそのファイルの 別の区画から読み込みを行ない、処理を行なう。例えば、リンカが 非常に良く使う操作にシンボルテーブルの処理がある。各バックエンドは、 シンボルのオブジェクトファイル注での表現と内部の正規形との変換を 行なうルーチンを提供している。リンカがあるオブジェクトファイルの シンボル表を要求すると、BFD は、適切な BFD バックエンドのルーチンを ポインタを経由して呼び出し、シンボル表を読み込んで正規形に変換を行なう。 そうするとリンカはその正規形に対し操作を行なう。リンクが完了し、 リンカが出力ファイルのシンボル表を書き出すと、別の BFD バックエンド ルーチンが呼ばれて、新しく作成されたシンボル表を受けとって、 選ばれた出力形式に変換する。

5.1.1 情報の損失  
5.1.2 BFD 正規オブジェクトファイル形式  


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.1 情報の損失

出力の際には情報が失われる可能性がある。 BFD がサポートしている 出力形式は同一の機能を提供しているわけではない。ある形式で 記述可能な情報が他の形式では入れる場所がないということがある。 一つの例は b.out のアラインメント情報である。a.out形式の ファイルには含まれるデータについてのアラインメントを入れておく場所が ないので、b.out のファイルをリンクして a.out の イメージを作ると、アラインメント情報は出力ファイルに伝わらないのである。 (リンカは内部的にアライメント情報を使っているので、リンク自体は 正しく行なわれる。)

もう一つの例は COFF のセクション名である。COFF ファイルに入れられる セクション数には制限がなく、それぞれテキスト文字列のセクション名がある。 リンクのターゲットの形式がたくさんセクションを保持できなかったり、 名前がないもの(例えば Oasys 形式)だと、リンクは単純には行なえない。 この問題は、入力セクションから出力セクションへの望ましい対応を リンカコマンド言語で記述することで克服できる。

正規化の過程で情報が失われる可能性がある。 外部形式に対する、BFD の内部正規形は完全には網羅していない。 入力形式には、内部的に直接的に表現できない構造が存在する。 これは、BFD のバックエンドは、外部形式から内部形式への変換と 外部形式に戻す際に全ての可能なデータを充分には保持できないという ことを意味する。

この制限が問題になるのは、アプリケーションがある一つの形式で 読み込んで、それとは別の形式で書き出す場合だけである。 各 BFD バックエンドには可能な限りたくさんのデータを保持する 責任があり、内部 BFD 正規形には BFD の中心部からは隠されている、 そのバックエンドにしか公開されていない構造体がある。 あるファイルが一つの形式で読み込まれると BFD とアプリケーション用に 正規形が作られる。同時に、バックエンドがたくわえない限り失われて しまう情報を、バックエンドが格納する。次にデータが同じ形式で 書き戻されると、バックエンドルーチンは、事前に準備された情報だけでなく、 BFD の中核部が提供する正規形も使えるようになる。バックエンド間で 共通する部分が多いので、ビッグエンディアンの COFF をリトルエンディアンの COFF に、あるいは a.outb.out にリンクしたり、コピーする 時には情報の損失はない。形式を混ぜてリンクすると、目的のファイル形式 と異なる形式のファイルの情報だけが失われる。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

5.1.2 BFD 正規オブジェクトファイル形式

最も情報が失われる可能性が大きいのは、ソース形式が提供する情報と、 正規形で蓄える情報と、目的形式が必要とする情報の間に重なる部分が 最も少ない時である。正規形の概要を説明しておけば、変換の際に どんな種類のデータが保存されると期待して良いかを理解する助けに なるだろう。

files
ファイル単位で格納される情報には、ターゲット機種アーキテクチャ、 特定の実装形式型、デマンドページング可ビット、書き込み防止ビット がある。Unix のマジック番号のような情報は格納されない。 マジック番号はその意味するところだけが書き込まれる。 つまり、ZMAGIC のファイルなら、デマンドページング可ビットと 書き込み防止ビットの両方が立てられる。ターゲットのバイト順は ファイル単位で格納されるので、ビッグエンディアンのファイルと リトルエンディアンのファイルはお互い一緒に使うことができる。

sections
入力ファイルの各セクションには、そのセクション名、オブジェクトファイル中 でのセクションの先頭のアドレス、大きさ、アラインメント情報、色々なフラグ、 それに、他の BFD のデータ構造へのポインタが含まれている。

symbols
各シンボルは、それを定義しているオブジェクトファイル、名前、値、色々な フラグビットについての情報へのポインタを持っている。 BFD バックエンドがシンボル表を読み込むと、全てのシンボルを、 そのシンボルを定義しているセクションの基底からの相対になるように 再配置する。こうすると、各シンボルがそれを含むセクションを指すことが 保証される。各シンボルには、多い少ないはあるものの、 BFD バックエンド用の隠された私的なデータも持っている。 シンボルは元のファイルを指しているので、そのシンボルの私的データの 形式もアクセスできるのである。ld は、 全くことなる形式のシンボルの集まりを問題なく扱うことができる。

普通のグローバルシンボルと単純なローカルシンボルは出力の際にも 保持されるので、出力ファイル(その形式はなんであれ)には、 関数と、グローバル変数、静的変数、コモン変数を指すシンボルが 保持される。シンボル情報の中には残す意味のないものがある。a.out では、型情報はシンボル表に長いシンボル名として格納される。この情報は、 ほとんどの COFF デバッガには意味がない。GNU リンカには、こういう シンボル情報を捨てるコマンド行オプションがある。

シンボルには、1 ワードで表される型情報が含まれているので、 オブジェクトファイル形式がシンボル内にシンボルの型情報を入れられる ものであり(例えば、COFF、IEEE、Oasys)、その型が 1 ワードに収まる程度の 簡単なものであれば(集合体以外のすべてと考えて良い)、その型情報は保存される。

relocation level
BFD の正規形再配置レコードには、再配置対象のシンボルへのポインタ、再配置 すべきデータのオフセット、データが入っているセクション、再配置型記述子 へのポインタを保持している。再配置は、再配置型記述しとシンボルポインタを 経由してメッセージを送ることで実行される。このため、入力ファイル形式の うちの一つでしか利用できない再配置方法を使って、出力データに対し 再配置を実行することができる。例えば、Oasys 形式はバイト単位の 再配置形式を提供している。この再配置型を要求する再配置レコードは、 これを実行するルーチンを間接的に指すので、この再配置は、 68k COFF ファイルに書き込まれるバイトに対して実行することができるのである。 68k COFF にそのような再配置型がないとしてもである。

line numbers
オブジェクトファイル形式は、デバッグ用に、シンボルとソースコード行番号、 アドレスの間のなんらかの形の対応を出力ファイルに入れることができる。 これらのアドレスは、シンボル情報に従って再配置を行なわなければならない。 各シンボルには行番号レコードのリストが付属しており、そのリストの 先頭のレコードを指している。行番号リストの先頭は、そのシンボルへのポインタ からなっており、記述しようとしている行番号を持つ関数のアドレスを 探すのを可能にしている。リストの残りは、対から成っている。セクションへの オフセットと行番号である。どんな形式であれ、この情報を簡単に導き 出せるものは、これを形式間で(COFF、IEEE、 Oasys)うまく渡すことができる。


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by YABUKI Youichi on March, 15 2002 using texi2html