リンカーは、入力配置可能オブジェクトの入力セクションを出力ファイルオブジェクトのセグメントに、自動的にかつ効率的に対応付けします。対応する mapfile を -M オプションに指定すれば、リンカーの初期値の対応付けの方法を変更できます。
この mapfile オプションを使えば、以下のことができます。
セグメントを宣言し、セグメント型、アクセス権、アドレス、長さ、および整列などセグメント属性の値を指定する
特定のセグメントに対応付けするのにセクションで必要な属性値を指定することにより (属性とは、セクション名、セクション型、およびアクセス権)、また必要ならば、入力セクションをどのオブジェクトファイルから取ってくるかを指定することにより、入力セクションのセグメントへの対応付けを制御する
指定したセグメントのサイズに等しい値に (リンカーが) 割り当てた、オブジェクトファイルから参照できる大域絶対シンボルを宣言する
mapfile オプションによって、ifiles (以前のリンカーで使用できた機能で、コマンド言語による指示を使用する) のユーザーは、mapfiles に移行できます。ただし、以前の ifiles で利用できた機能で、前述の説明に含まれていないものすべては、mapfile オプションでは利用できません。
mapfile オプションを使う場合、実行できない a.out ファイルを簡単に作れてしまうことに留意してください。リンカーは、mapfile オプションなしでも、正しい a.out を作ることができます。mapfile オプションは、システムプログラム用のもので、アプリケーションプログラムでの使用を意図したものではありません。
mapfile 指示をファイル、たとえば mapfile に入力する
リンカーのコマンド行に、-M mapfile を指定する
mapfile が現在のディレクトリにない場合、フルパス名を入れます。初期値の検索パスは存在しません。
以下の 4 つの基本的な指示を mapfile に入力できます。
セグメント宣言
対応付け指示
サイズシンボル宣言
ファイル制御指示
それぞれの指示は複数の行にまたがることができ、最後にセミコロンを付ければ、いくつでも空白 (改行を含む) を入れることができます。mapfile に指示をまったく入れないことも、複数入れることもできます (指示をまったく入れない場合、リンカーは mapfile を無視し、自らの初期値を使います)。
通常、セグメント宣言の後には、対応付け指示がきます。つまり、セグメントを宣言し、次にセクションがそのセグメントの一部分になる条件を定義するわけです。対応付け先のセグメントを最初に宣言しないで、対応付け指示あるいはサイズシンボル宣言を入力した場合、後で説明する組み込みのセグメント以外のセグメントには、以下で説明するように初期値の属性が与えられます。この場合このようなセグメントは「暗示的に宣言されたセグメント」になります。
サイズシンボル宣言、およびファイル制御指示は、mapfile のどこにでも入れることができます。
以後の節では、それぞれの指示について説明します。すべての構文説明について、次の表記が適用されます。
固定幅の文字のエントリ、すべてのコロン、セミコロン、等符号、@ 記号は、そのままの文字を入力する
「斜体文字」で示されたエントリはすべて、適切なもので置き換える
{ ... }* は、「無しまたはそれ以上」を意味する
{ ... }+ は、「1 つまたはそれ以上」を意味する
[ ... ] は、「任意指定」を意味する
section_names と segment_names は、C 識別子と同じ規則に従い、ピリオド (.) は文字として扱われる (たとえば、.bss は正当な名前)
section_names、segment_names、file_names、および symbol_names には大文字と小文字の区別があり、それ以外のものには大文字と小文字の区別は無い
空白文字 (あるいは改行文字) は、数字の前および名前や値の間以外はどこにでも入れられる
# で始まり改行で終わるコメントは、空白文字を入れることができる場所であれば、どこにでも入れられる
セグメントの宣言により、a.out に新しいセグメントを作ったり、既存のセグメントの属性値を変更したりできます (既存のセグメントとは、以前に定義したもの、あるいは以下に述べる 3 つの組み込みセグメントの 1 つのことです)。
セグメントの宣言は以下の構文で行います。
segment_name = {segment_attribute_value}*; |
各 segment_names について、任意の数の segment_attribute_values を任意の順序で指定でき、それぞれは空白文字で区切ります (セグメント属性ごとに、1 つの値だけ指定できます)。セグメント属性と、それらの有効な値は表 8-1 に示すとおりです。
表 8-1 mapfile セグメント属性
属性 |
値 |
---|---|
segment_type |
LOAD | NOTE | STACK |
segment_flags |
?[E][N][O][R][W][X] |
virtual_address |
Vnumber |
physical_address |
Pnumber |
長さ |
Lnumber |
丸め |
Rnumber |
整列 |
Anumber |
3 つの組み込みセグメントが存在し、以下のような初期値の属性値を持っています。
テキスト (LOAD、?RX、virtual_address と physical_address と長さは指定なし、CPU 固有の整列値)
データ (LOAD、?RWX、virtual_address と physical_address と長さは指定なし、CPU 固有の整列値)
注釈 (NOTE)
リンカーは、mapfile を読み取る前に、これらのセグメントが宣言されたように動作します。詳細は、「mapfile オプションの初期値」を参照してください。
セグメント宣言を入力する場合、以下のことに注意してください。
数字には、C 言語と同じ形式で、16 進数、10 進数、あるいは 8 進数が使える
V、P、L、R、あるいは A と数字の間には空白文字を入れてはいけない
segment_type 値は、LOAD、NOTE、または STACK のいずれか
segment_type の初期値は、LOAD
segment_flags 値は、R は読み取り可能 、W は書き込み可能、X は実行可能、O は順番です。疑問符 ? と segment_flags 値を構成する個々のフラグの間には、空白文字を入れてはいけない
LOAD セグメントの segment_flags 値は、初期値で RWX になる
NOTE セグメントには、segment_type 以外のセグメント属性値は割り当てられない
タイプ STACK の 1 つの segment_type がアクセス許可され、segment_flags から選択されたセグメントのアクセス要求のみが指定できる
暗示的に宣言されたセグメントでは、segment_type 値は LOAD、segment_flags 値は RWX、 virtual_address と physical_address と整列値は初期値、そして長さは無制限になる
リンカーは、1 つ前のセグメントの属性値に基づいて、現在のセグメントのアドレスや長さを計算します。また、暗示的に宣言されたセグメントがデフォルトで「長さ制限なし」になっていても、マシンのメモリー限界は適用されます。
LOAD セグメントには、 virtual_address 値、 physical_address 値、最大セグメント長値のいずれかまたはすべてを明示的に指定できる
セグメントに ? の segment_flags 値があって後に何もない場合、値は読み取り不可、書き込み不可、および実行不可になる
整列値は、セグメントの最初の仮想アドレスを計算する際に使われる。この整列は、整列指定されたセグメントにだけ影響する。その他のセグメントは、その整列が変更されない限り、デフォルトの整列が使われる
virtual_address、physical_address、あるいは長さの属性値のいずれかが設定されていない場合、リンカーは a.out を作成する際に、これらの値を計算する
セグメントに対して整列値が指定されていない場合、組み込みの初期値に設定される (初期値は CPU により異なり、カーネルのバージョンによっても異ることがある。これらの数字については、適切な資料で確認のこと)
virtual_address と整列値の両方がセグメントに対して指定されている場合、virtual_address の方が優先される
virtual_address 値がセグメントに対して指定されている場合、プログラムヘッダーの整列フィールドには、初期値の整列値が設定される
丸め値がセグメントに対して設定されている場合、そのセグメントの仮想アドレスは与えられた値に一致する次のアドレスに丸められる。この値は、指定の対象となるセグメントにしか効力はない。値が入力されないと、丸めは行われない
?E フラグにより、空のセグメントが作れます。これは、関連するセクションがないセグメントです。このセグメントは実行プログラムについてのみ指定でき、LOAD 型で、長さおよび整列が指定されていなければなりません。この種類のセグメントは複数定義することもできます。
?N フラグにより、ELF ヘッダー、および任意のプログラムヘッダーを最初の読み込み可能なセグメントの一部分として含めるかどうかを制御できます。初期値では、ELF ヘッダーおよびプログラムヘッダーは、これらのヘッダーの情報が対応付けられたイメージ内 (一般に実行時リンカーによって対応付けられる) で使われるため、最初のセグメントに含まれます。?N オプションを使用すると、イメージの仮想アドレス計算が最初のセグメントの最初の「セクション」で開始します。
?O フラグにより、最終的な再配置可能オブジェクト、実行可能ファイル、あるいは共有オブジェクトのセクションの順序を制御できます。このフラグは、コンパイラの -xF オプションと合わせて使うようになっています。ファイルを -xF オプションを使ってコンパイルすると、そのファイル内の各関数が、.text セクションと同じ属性を持つ別個のセクションに置かれます。これらのセクションは、.text%function_name (function_name は関数名) という名前になります。
たとえば、main()、foo()、および bar() の 3 つの関数を持つファイルを、-xF オプションを使ってコンパイルすると、3 つの関数のテキストが .text%main、.text%foo、および .text%bar という名前のセクションにあるオブジェクトファイルが作成されます。-xF オプションは 1 つのセクションに 1 つの関数を割り当てるので、セクションの順番を制御するために ?O フラグを使うと、実際には関数の順番を制御することになります。
次のユーザー定義の mapfile を検討します。
text = LOAD ?RXO; text: .text%foo; text: .text%bar; text: .text%main; |
ソースファイルの関数定義の順序が、main、foo、および bar の場合、最終的な実行プログラムには foo、bar、および main の順序で関数が含まれます。
同じ名前の静的関数を対象とする場合、ファイル名も指定する必要があります。?O フラグを指定すると、mapfile で指定されたとおりにセクションの順序付けが行われます。たとえば、静的関数 bar() がファイル a.o および b.o にあって、ファイル a.o の関数 bar() を、ファイル b.o の関数 bar() の前に置く場合、mapfile のエントリは次のようになります。
text: .text%bar: a.o; text: .text%bar: b.o; |
次の構文を使用することも可能ですが、ファイル a.o の関数 bar() が、ファイル b.o の関数 bar() の前に置かれることが保証されません。2 番目の形式は、結果が予測できないため、お勧めしません。
text: .text%bar: a.o b.o; |
virtual_address が指定されている場合、セグメントはその仮想アドレスに置かれます。これは、システムカーネルに対して、正しい結果を出します。exec(2) を介して開始するファイルの場合、この方法では、セグメントにそのページ境界に対応する正しいオフセットがないため、間違った a.out ファイルが作成されることになります。
対応付け指示は、入力セクションをどのように出力セグメントに対応付けするかをリンカーに伝えます。基本的には、対応付け先のセグメントの名前を指定し、名前を指定したセグメントに対応付けするためにセクションの属性をどうすべきかを指定します。特定のセグメントに対応付けするためにセクションが持っていなければならないセクション属性値 (section_attribute_values) は、そのセグメントの「エントランス基準」と呼ばれます。a.out の指定したセグメントにセクションを置くには、セクションはセグメントのエントランス基準に正確に合致していなければなりません。
対応付け指示には以下のような構文があります。
segment_name : {section_attribute_value}* [: {file_name}+]; |
セグメント名 (segment_name) に対して、任意の数のセクション属性値 (section_attribute_values) を任意の順序で指定し、それぞれは空白文字で区切ります (セクション属性ごとに 1 つの値だけ指定できます)。ファイル名 (file_name) を指定して、特定の .o ファイルからセクションを持ってこなければならないというように指定することもできます。セクション属性とその有効値は表 8-2 に示すとおりです。
表 8-2 セクション属性
セクション属性 |
値 |
---|---|
section_name |
任意の有効なセクション名 |
section_type |
$PROGBITS $SYMTAB $STRTAB $REL $RELA $NOTE $NOBITS |
section_flags |
?[[!]A][[!]W][[!]X] |
対応付け指示を入力する場合、以下の点に注意してください。
上に挙げた section_types から 1 つの値を選択する。上記の section_types は組み込まれているものです。section_types の詳細については、「セクション」を参照
section_flags 値は、A は割り当て可能 、W は書き込み可能、X は実行可能。個々のフラグの前に感嘆符 (!) がついている場合、リンカーは、フラグが設定されていないことを確認する。section_flags 値を構成する疑問符、感嘆符、および個々のフラグの間には空白文字を入れてはいけない
ファイル名には、ファイル名として正当な名前を指定できる。また、/usr/lib/usr/libc.a(printf.o) のように「アーカイブ名 (要素名) 」の形式で指定することもできます。さらに、ファイル名に *filename の形式で指定することもできる
ファイル名が *filename の形式になっている場合、リンカーはコマンド行で与えられた行からファイル名に basename(1) と同等の処理を行い、得られたファイル名を使って指定された filename との一致を調べる。言い換えれば、mapfile で指定する filename は、コマンドラインで与えられるファイル名の最後の部分だけが合致すればよい (「対応付けの例」を参照)
リンク編集の際に -l オプションを使っていて、-l オプションの後のライブラリが現在のディレクトリにある場合、mapfile 内のライブラリと一致させるために mapfile 内のライブラリの前に ./ (あるいはパス名全体) を付ける必要がある
特定の出力セグメントについて複数の指示行を指定できる。たとえば、以下のような一連の指示を行うことができる
S1 : $PROGBITS; S1 : $NOBITS; |
1 つのセグメントに対して複数の対応付け命令行を指示することは、複数のセクション属性値を指定するための唯一の方法です。
1 つのセクションは複数のエントランス基準に合致することがある。その場合、mapfile で最初にエントランス基準が合致したセグメントが使われる。たとえば、mapfile が以下のようになっているとする
S1 : $PROGBITS; S2 : $PROGBITS; |
この場合、$PROGBITS セクションは、セグメント S1 に対応付けられます。
以下のような表記を使うことにより、セグメント内にセクションを配置する順序を指定できます。
segment_name | section_name1; segment_name | section_name2; segment_name | section_name3; |
上記の形式で指定されたセクションは、すべての名前なしセクションの前に、mapfile に列挙されている順序で配置されます。
サイズシンボル宣言を使って、指定したセグメントのサイズをバイトで示す大域絶対シンボルを定義できます。このシンボルは、オブジェクトファイル内で参照できます。サイズシンボルは次の構文で宣言します。
segment_name @ symbol_name; |
symbol_name (シンボル名) には、任意の正当な C 識別子が入ります。ただし、リンカーは、symbol_name の構文の確認は行いません。
ファイル制御指示により、共有オブジェクト内のどのバージョンの定義をリンク編集時に使用可能にするかを指定できます。ファイル制御構文で宣言します。
shared_object_name - version_name [ version_name ... ]; |
version_name (バージョン名) には、指定した shared_object_name (共有オブジェクト名) 内のバージョン定義名が入ります。バージョン制御の詳細については、「バージョン結合の指定」を参照してください。
以下はユーザー定義の mapfile の例です。左の数字は、説明のためにつけたものです。実際には、数字の右の情報だけが、mapfile に含まれます。
1. elephant : .data : peanuts.o *popcorn.o; 2. monkey : $PROGBITS ?AX; 3. monkey : .data; 4. monkey = LOAD V0x80000000 L0x4000; 5. donkey : .data; 6. donkey = ?RX A0x1000; 7. text = V0x80008000; |
4 つの別々のセグメントがこの例では扱われています。暗黙の内に宣言されたセグメント elephant (1 行目) は、ファイル peanuts.o および popcorn.o からすべての .data セクションを受け取ります。*popcorn.o は、リンカーに与えられるすべての popcorn.o ファイルと一致します。ファイルは、現在のディレクトリにある必要はありません。他方、/var/tmp/peanuts.o がリンカーに提供された場合、これには * が前に付かないため peanuts.o とは一致しません。
暗黙の内に宣言されたセグメント monkey (2 行目) は $PROGBITS および割当て可能な実行プログラム (?AX) の両方になっているすべてのセクション、さらに .data (3 行目) という名前のすべてのセクション (セグメント elephant に入らなかったもの) を受け取ります。別の行で section_name にsection_type と section_flags の値が指定されているので、monkey セグメントに入る .data セクションが、$PROGBITS あるいは割当て可能な実行プログラムである必要はありません (and の関係は、2 行目の $PROGBITS and ?AX で示されるように、同じ行の属性の間に存在します。or の関係は、2 行目の $PROGBITS ?AX or 3 行目の .data のように、複数の行にまたがる同じセグメントの属性の間に存在します)。
monkey セグメントは、segment_type が LOAD、segment_flags が RWX、virtual_address と physical_address は無指定、長さや整列の値は、初期値として 2 行目で暗黙の内に宣言されています。4 行目では、monkey の segment_type 値は LOAD に (segment_type 属性は変わっていないので、警告は出ません)、virtual_address 値は 0x80000000 に、最大長値は 0x4000 に設定されています。
5 行目では、donkey セグメントを暗黙の内に宣言しています。エントランス基準 は、このすべての .data セクションをこのセグメントに振り向けるようになっています。実際には、3 行目の monkey のエントランス基準はこれらのセクションのすべてを取り込むので、このセグメントに入るセクションはありません。6 行目では、segment_flags 値は ?RX に設定され、整列値は 0x1000 に設定されています (これらの属性値の両方が変わったので警告が出ます)。
7 行目では、テキストセグメントの virtual_address 値を 0x80008000 に設定します。
ユーザー定義の mapfile の例は、説明のために警告を出すように設計されています。次の例では命令の順序を変更して警告を避けています。
1. elephant : .data : peanuts.o *popcorn.o; 4. monkey = LOAD V0x80000000 L0x4000; 2. monkey : $PROGBITS ?AX; 3. monkey : .data; 6. donkey = ?RX A0x1000; 5. donkey : .data; 7. text = V0x80008000; |
次の mapfile の例では、セグメント内セクションの順序付けを使っています。
1. text = LOAD ?RXN V0xf0004000; 2. text | .text; 3. text | .rodata; 4. text : $PROGBITS ?A!W; 5. data = LOAD ?RWX R0x1000; |
text セグメントおよび data セグメントが、この例では扱われています。1 行目では、text セグメントの virtual_address が 0xf0004000 になるように、またこのセグメントのアドレス計算の一部分として ELF ヘッダーやプログラムヘッダーを含めないように宣言しています。2 行目と 3 行目では、セグメント内セクションの順序付けを有効にし、このセグメントでは .text セクションと .rodata セクションが最初の 2 つのセクションになるように指定しています。この結果、.text セクションは仮想アドレスが 0xf0004000 になり、その直後に .rodata セクションがきます。
text セグメントを構成するその他の $PROGBITS セクションは、.rodata セクションの後にきます。5 行目では data セグメントを指定し、その仮想アドレスは 0x1000 バイト境界で始まらなければならないと指定しています。data を構成する最初のセクションも、ファイルイメージ内の 0x1000 バイト境界に存在します。
リンカーは、「セグメントの宣言」で説明したように、初期値の segment_attribute_values で 3 つの組み込みセグメント (text、data、および note)、および対応する初期値の対応付け命令を定義します。リンカーは初期値を提供するのに実際の mapfile は使いませんが、ここでは初期値の内容を mapfile に書かれているものとして、リンカーがユーザーの mapfile を処理する際にどのようなことが起こるかを説明します。
以下に示す例は、リンカーの初期値を mapfile として表現したものです。リンカーは、mapfile をすでに読み取ったかのように実行を開始します。その後でリンカーは、mapfile を読み取ったり、あるいは初期値への追加や変更を行なったりします。
text = LOAD ?RX; text : ?A!W; data = LOAD ?RWX; data : ?AW; note = NOTE; note : $NOTE; |
mapfile の各セグメント宣言は読み取られる際、以下のようにセグメント宣言の既存リストと比較されます。
セグメントが mapfile に存在しておらず、同じ segment-type 値の別のセグメントが存在する場合、そのセグメントは、すべての同じ segment_type の既存セグメントの前に追加される
セグメントが読み取られたとき、既存の mapfile に同じ segment_type のセグメントがない場合、セグメントは、segment_type 値が以下の順序になるように追加される
INTERP
LOAD
DYNAMIC
NOTE
セグメントの segment_type が LOAD で、この LOAD 可能なセグメントに virtual_address 値を定義していた場合、セグメントは、virtual_address 値が定義されていない、あるいはより高い virtual_address 値の LOAD が指定されたセグメントの前、そしてそれよりも低い virtual_address 値のセグメントの後に置かれる
mapfile の各対応付け指示が読み取られる際、同じセグメントに対してすでに指定されたその他の対応付け指示の後 (かつ、そのセグメントのデフォルトの対応付け指示の前) に、指示が追加されます。
ELF ベースのリンカーのもっとも重要なデータ構造の 1 つとして対応付け構造があります。上記で述べた初期値 mapfile に対応する初期対応付け構造は、コマンド実行時にリンカーで使われます。mapfile オプションが使われる場合、リンカーは mapfile を解析して、特定の値を初期対応付け構造に追加または上書きします。
一般的な (ただし多少簡略化した) 対応付け構造を図 8-1 に示します。「エントランス基準」ボックスは初期値の対応付け指示の情報に対応しており、「セグメント属性記述子」ボックスは、初期値のセグメント宣言の情報に対応しています。「出力記述子」ボックスは、各セグメントの下に来るセクションの詳細な属性を示します。セクション自体は丸で囲んであります。
リンカーはセクションをセグメントに対応付ける際に、以下の手順で行います。
セクションを読み取る際に、リンカーは合致するものを見つけるために、一連のエントランス基準を検査します。指定したすべての条件が合致する必要があります。
図 8-1 では、text セグメントに入るセクションの場合、section_type は $PROGBITS、section_flags は ?A!W でなければなりません。エントランス基準では名前は指定されていないので、名前 .text は必要ありません。エントランス基準では実行ビットは何も指定されていないので、セクションは (section_flags 値の) X または !X のどちらかでもかまいません。
エントランス基準に合致するものが見つからない場合、セクションはその他すべてのセグメントの後の a.out ファイルの最後に置かれます (この情報については、プログラムヘッダーエントリは作られません。詳細は、「プログラムヘッダー」を参照)。
セクションがセグメントの中に入る際に、リンカーは以下のようにそのセグメントの既存の一連の出力セクション記述子を検査します。
セクションの属性値が既存の出力セクション記述子の属性値とまったく合致する場合、セクションは出力セクション記述子に対応するセクションの列挙の最後に置かれます。
たとえば、section_name が .data1、section_type が $PROGBITS、および section_flags が ?AWX のセクションは、図 8-1 の 2 番目のエントランス基準ボックスにあてはまり、data セグメントに置かれます。セクションは 2 番目の出力セクション記述子ボックスにちょうど一致し (.data1、$PROGBITS、?AWX)、このボックスに対応する一連のセクションの最後に追加されます。fido.o、rover.o、および sam.o の .data1 セクションは、このことを示しています。
一致する出力セクション記述子が見つからず、同じ section_type の出力セクション記述子が他に存在する場合、セクションとして同じ属性値で新しい出力セクション記述子が作られ、そのセクションは新しい出力セクション記述子と対応づけられます。出力セクション記述子 (およびセクション) は、同じ section_type の最後の出力セクション記述子の後に置かれます。図 8-1 の .data2 セクションはこのやり方で置かれました。
示された section_type の出力セクション記述子が他に存在しない場合、新しい出力セクション記述子が作られ、セクションはそのセクション内に置かれます。
入力セクションにユーザー定義の section_type が設定されている場合 (つまり、「セクション」で説明しているように、SHT_LOUSER と SHT_HIUSER の間)、これは $PROGBITS セクションとして扱われます。mapfile でこの section_type 値に名前を付ける方法はありませんが、これらのセクションは、エントランス基準でその他の属性値指定 (section_flags、section_name) を使って付け直すことができます。
すべてのコマンド行で指定されたオブジェクトファイルとライブラリが読み取られた後、セグメントがセクションをまったく含まない場合、そのセグメントに対してはプログラムヘッダーエントリは作られません。
$SYMTAB、$STRTAB、$REL、および $RELA 型の入力セクションは、リンカーにより内部で使用されます。これらの section_type を参照する指示は、リンカーで作った出力セクションしかセグメントに対応付けできません。
このカテゴリのエラーメッセージが出力される場合は、リンカーが停止したり、リンカーが実行可能な a.out を作成できないといったことはありません。次のような条件で、警告が発せられます。
physical_address、virtual_address、あるいは長さの値が、LOAD セグメント以外のすべてのセグメントに対して指示されている場合 (指示は無視される)
すでに存在するセグメントに対して、属性値を変更する宣言が行なわれた場合 (2 番目の宣言で指示した属性値が有効になる)
属性値 (text や data に対しては segment_type と segment_flags。note に対しては segment_type) が組み込みセグメントのいずれかに対して変更された場合
暗黙の内に宣言により作成されたセグメントの属性値 (segment_type、segment_flags、長さ、整列の一部または全部) が変更された場合。?O フラグが追加されただけの場合、属性値変更の警告は発せられない
エントランス基準に合わない場合。?O フラグが有効になっていて、エントランス基準に合う入力セクションがない場合、警告が発せられる
このカテゴリのエラーが発生した場合、その時点でリンカーの実行を停止します。以下の条件で致命的エラーが発生します。
対応付けファイルを開いたり読んだりできない場合
構文エラーが mapfile で発見された場合
file_name、section_name、segment_name、あるいは symbol_name が 「mapfile の構造と構文」の規則に合わない場合、リンカーはこの条件が構文エラーを作成しない限り、エラーを返しません。たとえば、名前が特殊な文字で始まり、この名前が指示行の最初にある場合、リンカーはエラーを返します。名前が section_name の場合 (指示内に表示されます)、リンカーはエラーを返しません。
1 つの命令行に複数の segment_type、segment_flags、virtual_address、physical_address、長さあるいは整列の値がある場合
mapfile で interp セグメントまたは dynamic セグメントを操作しようとした場合
interp セグメントおよび dynamic セグメントは特殊な組み込みのセグメントで、これはどのようなやり方を使っても変更できません。
セグメントが、長さ属性値で指定した長さよりも大きくなった場合
ユーザー定義の virtual_address が原因で、セグメントが前のセグメントを上書きする場合
1 つの命令行に複数の section_name、 section_type、 あるいは section_flags 値がある場合
mapfile のサンプルは、/usr/lib/ld ディレクトリにあります。