説明
ELF
の a.out
a.out というファイル名は、リンクエディタ ld(1) からのデフォルトの出力ファイル名です。
リンク中にエラーがなければ、リンクエディタは a.out 実行可能ファイルを作成します。
アセンブラ as(1) の出力ファイルも、そのデフォルトの名前は異なりますが、 a.out ファイルのフォーマットに従います。
ELF ファイルを扱うプログラムは、 elf(3E) で記述するライブラリを使用する可能性があります。
このファイルフォーマットの概要は、次のとおりです。 詳細は下で述べる「参照」をご覧ください。
リンクビュー 実行ビュー
_______________________ _______________________
ELF ヘッダー ELF ヘッダー
|_____________________| |______________________|
|プログラムヘッダー | |プログラムヘッダー |
| テーブル | | テーブル |
| 任意 | | |
|_____________________| | _____________________|
| セクション 1 | | |
|_____________________| | |
| . . . | | セグメント 1 |
| | | |
|_____________________| | _____________________|
| セクション n | | |
|_____________________| | |
| . . . | | セグメント 2 |
| | | |
|_____________________| | _____________________|
| . . . | | . . . |
|_____________________| | _____________________|
|セクションヘッダー | |セクションヘッダー |
| テーブル | | テーブル |
| | | 任意 |
|_____________________| |______________________|
ELF ヘッダーは先頭にあり、その中にはファイルの構成を記述する「ロードマップ」があります。セクションには、命令、データ、シンボルテーブル、再配置情報など、リンクビューへの大半のオブジェクトファイル情報が入っています。
セグメントには、プログラム実行ビューへのオブジェクトファイル情報が入っています。
上で示したように、セグメントは 1 つまたは複数のセクションを含む可能性があります。
プログラムヘッダーテーブルが存在する場合、それは、プロセスイメージの作成方法をシステムに指示します。
プロセスイメージの作成 (プログラムの実行) に使用されるファイルにはプログラムヘッダーテーブルがなければなりません。
再配置可能なファイルには、プログラムヘッダーテーブルは必要ありません。
セクションヘッダーテーブルには、ファイルのセクションを説明する情報が含まれています。
テーブル内のそれぞれのセクションにはエントリーが 1 つずつあり、それぞれのエントリーがセクション名、セクションサイズなどの情報を与えます。
リンク中に使用されるファイルには、セクションヘッダーテーブルがなければなりません。
他のオブジェクトファイルには、セクションヘッダーテーブルはあってもなくてもかまいません。
この図では、ELF ヘッダーの直後にプログラムヘッダーテーブルを、またセクションの後にセクションヘッダーテーブルを示していますが、実際のファイルでは異なる可能性があります。
さらに、セクションおよびセグメントの順序に指定はありません。 ELF ヘッダーだけがファイル内の固定位置にあります。
a.out ファイルが実行のためにメモリ内にロードされると、テキストセグメント、データセグメント
(初期化済みデータの次に初期化されていないデータの順、後者は実際にはすべてゼロで初期化済み)、およびスタックという
3 つの論理セグメントが設定されます。 テキストセグメントは、プログラムからは書き込み不可です。
つまり、別々のプロセスが同じ a.out ファイルを実行している場合、これらのプロセスは
1 つのテキストセグメントを共有します。
データセグメントは、最後のテキストアドレスの後にある最大のページ境界から始まります
(システムで複数のページサイズがサポートされている場合「最大のページ」とはサポートされている最大のサイズです)。
プロセスイメージが作成される際に、テキストの最後およびデータの先頭が入っているファイルの部分が
2 度現れる可能性があります。 データの先頭にある重複したテキスト部分が実行されることはありません。
このように重複している場合、オペレーティングシステムは、データセクションの先頭をページ境界に配置し直さないで、ファイルの部分を実際のページサイズの倍数で取り込むことがあります。したがって、最後のテキストの後にある最大のページ境界に、最後のテキストアドレスを最大のページサイズで割った余りを加算した値が、最初のデータアドレスとなります。
最後のテキストアドレスが最大のページサイズの倍数である場合は、重複は起こりません。
スタックは、必要に応じて、自動的に拡張されます。 データセグメントは、 brk(2) システムコールで要求された通りに拡張されます。
SOM
の a.out (PA-RISC のみ)
ファイル名 a.out は、アセンブラ (as(1)を参照)、コンパイラ、およびリンカ
(ld(1)を参照) の出力ファイルのデフォルトファイル名です。アセンブラとコンパイラは、リンカにすぐ入力できる再配置可能オブジェクトファイルを作成します。リンカは、実行可能オブジェクトファイルと共有ライブラリファイルを作成します。
オブジェクトファイルは、ファイルヘッダー、補助ヘッダー、スペースディクシ
ョナリ、サブスペースディクショナリ、シンボルテーブル、再配置情報、コンパイ
ラレコード、空白文字列テーブル、シンボル文字列テーブル、および初期化済みコー
ドとデータについてのデータで構成されます。これらのセクションのすべてがあらゆる
オブジェクトファイルで必要なわけではありません。ファイルの先頭はファイル
ヘッダーでなければなりませんが、残りのセクションは特定の順序である必要はありま
せん。ファイルヘッダーには、ファイルの他の各セクションを指し示すポインターが 入っています。
アセンブラまたはコンパイラが作成する再配置可能ファイルには、少なくとも、ファイ ルヘッダー、スペースディクショナリ、サブスペースディクショナリ、シンボ
ルテーブル、再配置情報、空白文字列テーブル、シンボル文字列テーブル、および
コードとデータのセクションがなければなりません。補助ヘッダーとコンパイラレ
コードが入っていてもかまいません。再配置可能ファイルには、一般に、未解決のシン
ボルが入っています。リンカは再配置可能ファイルを結合し、ライブラリを検索して
実行可能ファイルを作成します。リンカを使用して、再配置可能ファイルを結合し、後
のリンカ実行の入力に適切な新しい再配置可能ファイルを作成することもできます。
リンカの作成する実行可能ファイルは通常、ファイルヘッダー、HP-UX
補助ヘッ ダー、スペースディクショナリ、サブスペースディクショナリ、シンボルテーブ
ル、コンパイラレコード、空白文字列テーブル、シンボル文字列テーブル、および初
期化済みコードとデータについてのセクションで構成されます。また、リンカは、補助 ヘッダーとコンパイラレコードを、入力ファイルから出力ファイルにコピーします。 ファイルが削除されている
(strip(1)を参照) 場合、ファイルにはシンボルテーブル、シンボル文字列テーブル、またはコンパイ
ラレコードがありません。実行可能ファイルには、未解決のシンボルが入っていては
なりません。
リンカの作成する共有ライブラリファイルには、実行可能ファイルと同じファイルが 入っているだけでなく、ファイルのコードセクションに情報が追加されています。こ の追加情報には、ヘッダー、エクスポートテーブル、インポートテーブル、および
動的ローダーの使用する動的再配置レコードが含まれます。
プログラムは、次の 2 つのロード可能スペースで構成されています。 $TEXT$ という名称の読み取り専用共有コードスペースと、 $PRIVATE$ という名称の書き込み可能プライベートデータスペースです。
プログラムには他に、 $THREAD_SPECIFIC$ という名称のロード可能プライベートデータスペースを入れることもできます。
プログラムには、開発ツールに必要なデータが入った他のロード不可能なスペースが入っていることもあり ます。たとえば、シンボリックデバッグ情報は、 $DEBUG$ または $PINFO$ というスペースに入っています。リンカは、ロード可能なスペースもロード不可能なス
ペースも、まったく同じように取り扱うので、シンボル解決と再配置は、シンボリッ
クデバッグ情報として完全な一般性を保持します。
スペースのアドレス指定範囲は 4,294,967,296 (2^32) バイトです。ロード可能な各ス ペースは、1/4
ずつ 4 つの 1,073,741,824 (2^30) バイトに分割されていま す。HP-UX オペレーティングシステムは、コードをすべて最初の
1/4 $TEXT$ スペースに入れ、データをすべて 2 番目の
1/4 $PRIVATE$ スペースに入れ、共有ライブラリコードをすべて
3 番目の 1/4 共有メモリスペース に入れます。
各スペースはさらにサブスペースと呼ばれる論理単位に分割されます。リンカは、再配 置可能オブジェクトファイルを結合するとき、入力ファイルの全サブスペースを名称 ごとにグループ分けしてから、スペース内のグループを各サブスペースに対応する ソートキーで配列します。サブスペースはアーキテクチャとしては重要ではありませ ん。多数の入力ファイルから独立に、スペースの個々の部分を結合するためのメカニズ ムに過ぎません。プログラムの代表的なサブスペースを次表に示します。
| $SHLIB_INFO$ | 動的ロードに必要な情報 |
| $MILLICODE$ | ミリコードルーチン用コード |
| $LIT$ | 共有可能リテラル |
| $CODE$ | コード |
| $UNWIND$ | スタックアンワインド情報 |
| $GLOBAL$ | Pascal の外側ブロック宣言 |
| $DATA$ | 初期化済み静的データ |
| $COMMON$ | FORTRAN コモン |
| $BSS$ | 初期化されていないデータ |
| $TBSS$ | スレッドのローカル記憶領域 |
サブスペースは初期化しても初期化しなくてもかまいません (通常は、 $BSS$ と $TBSS$ だけは初期化されません)。初期化済みサブスペースに関するサブスペースディクショ
ナリエントリーには初期化データを指し示すファイルポインターが入れられるのに
対し、初期化済みでないサブスペースに関するエントリーには、ロード時に領域全体を
初期化するために使用される 32 ビットのパターンだけが入れられます。
再配置可能ファイルでは、初期化済みコードとデータに、ファイル内の他のどこかの位 置の参照、および他のファイルで定義されている未解決シンボルの参照が入っているこ とがよくあります。これらの参照は、リンク時に再配置情報を使用して埋め込まれま す。再配置情報
(「解決情報」) 内の各エントリーは、サブスペースに関して初期化済み
データ内の位置を指定し、1 つまたは 2 つのシンボルに相対的にその位置に配置しなけ
ればならない実際の値を定義する式を指定します。
リンカは、実行可能ファイルを作成するとき、サブスペースディクショナリ
を HP-UX 補助ヘッダー内に要約します。HP-UX プログラムが別個に保持できのるは、
コード用セクション、初期化済みデータ用セクション、および初期化されていないデー
タ用セクションの 3 つだけです。通常、この補助ヘッダーはファイルヘッダーの直後
に配置されます。
a.out ファイルが実行のためにメモリにロードされるとき、次の
3 つのメモリ領域がセットアップされます。 a.out コードは、新しい共有可能スペースの最初の
1/4 にロードされます。データ (初期化済 みのデータの後に初期化されていないデータが続く) は、新しいプライベートスペー
スの 2 番目の 1/4 にロードされます。スタックは、データスペースの
2 番目の 1/4 の中央付近の固定アドレスで開始するように作成されます。
a.out ファイルが共有ライブラリを使用する場合は、動的ローダー /usr/lib/dld.sl が、メモリにロードされ、プログラムの要求する共有ライブラリをすべてメモリ
にマップするために呼び出されます。共有ライブラリテキストは、共有メモリ
スペースの 3 番目の 1/4 にロードされ、共有ライブラリデータはデータスペース
の 2 番目の 1/4 に割り当てられます。
ここで説明するファイルフォーマットは、HP のプレシジョンアーキテクチャ向けに
設計されたあらゆるオペレーティングシステムに共通なフォーマットです。したがって、HP-UX
には、使用されないフィールドおよび構造体、または将来使用するために予約済みの
フィールドおよび構造体もあります。
ファイルヘッダー
ファイルヘッダーのフォーマットは、 <filehdr.h> 内の次の構造体宣言で記述されます。
struct header {
short int system_id; /* system id */
short int a_magic; /* magic number */
unsigned int version_id; /* a.out format version */
struct sys_clock file_time; /* timestamp */
unsigned int entry_space; /* index of space containing entry point */
unsigned int entry_subspace; /* subspace index of entry */
unsigned int entry_offset; /* offset of entry point */
unsigned int aux_header_location; /* file ptr to aux hdrs */
unsigned int aux_header_size; /* sizeof aux hdrs */
unsigned int som_length; /* length of object module */
unsigned int presumed_dp; /* DP value assumed during compilation */
unsigned int space_location; /* file ptr to space dict */
unsigned int space_total; /* # of spaces */
unsigned int subspace_location; /* file ptr to subsp dict */
unsigned int subspace_total; /* # of subspaces */
unsigned int loader_fixup_location; /* space reference array */
unsigned int loader_fixup_total; /* # of space reference recs */
unsigned int space_strings_location; /* file ptr to sp. strings */
unsigned int space_strings_size; /* sizeof sp. strings */
unsigned int init_array_location; /* location of init pointers */
unsigned int init_array_total; /* # of init pointers */
unsigned int compiler_location; /* file ptr to comp recs */
unsigned int compiler_total; /* # of compiler recs */
unsigned int symbol_location; /* file ptr to sym table */
unsigned int symbol_total; /* # of symbols */
unsigned int fixup_request_location; /* file ptr to fixups */
unsigned int fixup_request_total; /* # of fixups */
unsigned int symbol_strings_location; /* file ptr to sym strings */
unsigned int symbol_strings_size; /* sizeof sym strings */
unsigned int unloadable_sp_location; /* file ptr to debug info */
unsigned int unloadable_sp_size; /* size of debug info */
unsigned int checksum; /* header checksum */
};
タイムスタンプは、次に示すように 2 ワードの構造体です。タイムスタンプが使用されない場合は、両方のフィールドがゼロになります。
struct sys_clock {
unsigned int secs;
unsigned int nanosecs;
};
補助ヘッダー
補助ヘッダーは、ファイル内の 1 つの連続領域に入れられ、ファイルヘッダー内のポインターによって配置されます。補助ヘッダーは次の
2 つの目的のために使用されます。ユーザーのバージョンと著作権文字列をオブジェクトファイルに結び付けるためと、実行可能プログラムをロードするのに必要な情報を入れるためです。実行可能プログラム内では、HP-UX
補助ヘッダーは他の補助ヘッダーの前になければなりません。次の宣言は、 <aouthdr.h> にあります。
struct aux_id {
unsigned int mandatory : 1; /* linker must understand aux hdr info */
unsigned int copy : 1; /* copy aux hdr without modification */
unsigned int append : 1; /* merge multiple entries of same type */
unsigned int ignore : 1; /* ignore aux hdr if type unknown */
unsigned int reserved : 12; /* reserved */
unsigned int type : 16; /* aux hdr type */
unsigned int length; /* sizeof rest of aux hdr */
};
/* Values for the aux_id.type field */
#define HPUX_AUX_ID 4
#define VERSION_AUX_ID 6
#define COPYRIGHT_AUX_ID 9
#define SHLIB_VERSION_AUX_ID 10
struct som_exec_auxhdr { /* HP-UX auxiliary header */
struct aux_id som_auxhdr; /* aux header id */
long exec_tsize; /* text size */
long exec_tmem; /* start address of text */
long exec_tfile; /* file ptr to text */
long exec_dsize; /* data size */
long exec_dmem; /* start address of data */
long exec_dfile; /* file ptr to data */
long exec_bsize; /* bss size */
long exec_entry; /* address of entry point */
long exec_flags; /* loader flags */
long exec_bfill; /* bss initialization value */
};
/* Values for exec_flags */
#define TRAP_NIL_PTRS 01
struct user_string_aux_hdr { /* Version string auxiliary header */
struct aux_id header_id; /* aux header id */
unsigned int string_length; /* strlen(user_string) */
char user_string[1]; /* user-defined string */
};
struct copyright_aux_hdr { /* Copyright string auxiliary header */
struct aux_id header_id; /* aux header id */
unsigned int string_length; /* strlen(user_string) */
char copyright[1]; /* user-defined string */
};
struct shlib_version_aux_hdr {
struct aux_id header_id; /* aux header id */
short version; /* version number */
};
スペースディクショナリ
スペースディクショナリは、 <spacehdr.h> に定義されているように、一連のスペースレコードで構成されています。
struct space_dictionary_record {
union name_pt name; /* index to space name */
unsigned int is_loadable: 1; /* space is loadable */
unsigned int is_defined: 1; /* space is defined within file */
unsigned int is_private: 1; /* space is not sharable */
unsigned int has_intermediate_code: 1; /* contains intermediate
code */
unsigned int is_tspecific: 1; /* space is $thread_specific$ */
unsigned int reserved: 11; /* reserved */
unsigned int sort_key: 8; /* sort key for space */
unsigned int reserved2: 8; /* reserved */
int space_number; /* space index */
int subspace_index; /* index to first subspace */
unsigned int subspace_quantity; /* # of subspaces in space */
int loader_fix_index; /* index into loader fixup array */
unsigned int loader_fix_quantity; /* # of loader fixups in space */
int init_pointer_index; /* index into init pointer array */
unsigned int init_pointer_quantity; /* # of init ptrs */
};
スペース名称用の文字列は、ファイルヘッダーのポインターが位置付けるスペース文字列テーブルに入れられます。
スペース文字列テーブルの各エントリーの先頭には文字列の長さを定義する
4 バイトの整数が付けられ、各エントリーの末尾は、ワード境界まで文字列をパディングする
1〜5 個のヌル文字で終了されます。 このテーブルのインデックスは、テーブルの先頭に相対的で、文字列の最初のバイト
(その前にある長さを示すワードではありません) をポイントします。
次に定義する共用体は、そのような文字列ポインターすべてに使用されます。
文字列テーブルをメモリに読み込み、スペースレコードのメモリ内コピーを再配置するプログラムについて、文字ポインターが定義されています。
union name_pt {
char *n_name;
unsigned int n_strx;
};
サブスペースディクショナリ
サブスペースディクショナリは、 <scnhdr.h> に定義されている一連のサブスペースレコードで構成されます。サブスペース名称の文字列はスペース文字列テーブルに入っています。
struct subspace_dictionary_record {
int space_index; /* index into space dictionary */
unsigned int access_control_bits: 7; /* access and priv levels
of subsp */
unsigned int memory_resident: 1; /* lock in memory during exec */
unsigned int dup_common: 1; /* duplicate data symbols allowed */
unsigned int is_common: 1; /* initialized common block */
unsigned int is_loadable: 1; /* subspace is loadable */
unsigned int quadrant: 2; /* quadrant in space subsp
should reside in */
unsigned int initially_frozen: 1; /* lock in memory
when OS booted */
unsigned int is_first: 1; /* must be first subspace */
unsigned int code_only: 1; /* subspace contains only code */
unsigned int sort_key: 8; /* subspace sort key */
unsigned int replicate_init: 1; /* init values to be replicated
to fill subsp len */
unsigned int continuation: 1; /* subspace is a continuation */
unsigned int is_tspecific: 1; /* subspace contains TLS */
unsigned int reserved: 5; /* reserved */
int file_loc_init_value; /* file location or init value */
unsigned int initialization_length; /* length of initialization */
unsigned int subspace_start; /* starting offset */
unsigned int subspace_length; /* total subspace length */
unsigned int reserved2: 16; /* reserved */
unsigned int alignment: 16; /* alignment required */
union name_pt name; /* index of subspace name */
int fixup_request_index; /* index to first fixup */
unsigned int fixup_request_quantity; /* # of fixup requests */
};
シンボルテーブル
シンボルテーブルは、 <syms.h> から取られた、次に示す一連のエントリーで構成されています。シンボルと修飾子の名称の文字列は、シンボル文字列テーブルにあります。このテーブルの構造はスペース文字列テーブルと同じです。
struct symbol_dictionary_record {
unsigned int hidden: 1; /* symbol not visible to loader */
unsigned int secondary_def: 1; /* secondary def symbol */
unsigned int symbol_type: 6; /* symbol type */
unsigned int symbol_scope: 4; /* symbol value */
unsigned int check_level: 3; /* type checking level */
unsigned int must_qualify: 1; /* qualifier required */
unsigned int initially_frozen: 1; /* lock in memory
when OS booted */
unsigned int memory_resident: 1; /* lock in memory during exec */
unsigned int is_common: 1; /* common block */
unsigned int dup_common: 1; /* duplicate data symbols allowed */
unsigned int xleast: 2; /* MPE-only */
unsigned int arg_reloc: 10; /* parameter relocation bits */
union name_pt name; /* index to symbol name */
union name_pt qualifier_name; /* index to qual name */
unsigned int symbol_info; /* subspace index */
unsigned int symbol_value; /* symbol value */
};
/* Values for symbol_type */
#define ST_NULL 0 /* unused symbol entry */
#define ST_ABSOLUTE 1 /* non-relocatable symbol */
#define ST_DATA 2 /* initialized data symbol */
#define ST_CODE 3 /* generic code symbol */
#define ST_PRI_PROG 4 /* program entry point */
#define ST_SEC_PROG 5 /* secondary prog entry point*/
#define ST_ENTRY 6 /* procedure entry point */
#define ST_STORAGE 7 /* storage request */
#define ST_STUB 8 /* MPE-only */
#define ST_MODULE 9 /* Pascal module name */
#define ST_SYM_EXT 10 /* symbol extension record */
#define ST_ARG_EXT 11 /* argument extension record */
#define ST_MILLICODE 12 /* millicode entry point */
#define ST_PLABEL 13 /* MPE-only */
#define ST_OCT_DIS 14 /* Used by OCT only--ptr to translated code */
#define ST_MILLI_EXT 15 /* address of external millicode */
#define ST_TSTORAGE 16 /* TLS common symbol */
/* Values for symbol_scope */
#define SS_UNSAT 0 /* unsatisfied reference */
#define SS_EXTERNAL 1 /* import request to external symbol */
#define SS_LOCAL 2 /* local symbol */
#define SS_UNIVERSAL 3 /* global symbol */
シンボル値の意味は、シンボルのタイプで定まります。コードシンボル
(総称コード、プログラムエントリー点、手続き、およびミリコードエントリー点)
の場合、シンボル値の下位 2 ビットが実行特権レベルをエンコードします。これは
HP-UX では使用されませんが、一般には 3 に設定されます。これらのビットをマスクしたシンボル値が、シンボルのアドレスです
(必ず 4 の倍数です)。データシンボルの場合、シンボル値はシンボルの単なるアドレスです。
スレッドの (共通ではない) ローカル記憶領域シンボルの場合、シンボル値は、ライブラリまたは実行可能ファイルにおけるスレッドローカル記憶領域のオフセットです。また再配置可能ファイルでは、シンボル値はシンボルの大きさです。
記憶領域要求またはスレッドの共通ローカル記憶領域の場合、シンボル値は要求されたバイト数です。リンカは、 $BSS$ または $TBSS$ サブスペース内の各シンボルについて、最大の要求を満たすスペースを割り当てます。ただし、そのシンボルについてローカルシンボルまたは普遍的シンボルが見つかった場合は別です
(この場合、記憶領域要求は満足されない参照のように処理されます)。
再配置可能ファイルをパラメータの型チェックを指定してコンパイルすると、拡張レ コードが、手続きエントリー点とグローバル変数を定義するシンボルの後に続きます。 最初の拡張レコードである 「シンボル拡張レコード」 が、戻り値またはグローバル変数の型を定義し、(定義値または関数の場合)
パラメー ターの数と最初の 3 つのパラメータの型を定義します。多数のパラメータの型記述
子が必要は場合は、その後に 1 つまたは複数の「引き数拡張レコード」 が続き、それぞれにさらに
4 つの記述子が入れられます。チェックレベルが 0 の場合 は型チェックは行われません。拡張レコードは後続しません。チェックレベル
1 以上 の場合、戻り値またはグローバル変数の型のチェックが指定されます。チェックレベ
ルが 2 以上の場合、パラメータ数のチェックが指定されます。チェックレベルが
3 の場合、個々の各パラメータの型のチェックが指定されます。リンカは、シンボル参
照を解決するとき、満たされないシンボルと、ローカルシンボルまたは普遍的シンボ
ルの間で、要求されたレベルの型チェックを行います。
union arg_descriptor {
struct {
unsigned int reserved: 3; /* reserved */
unsigned int packing: 1; /* packing algorithm used */
unsigned int alignment: 4; /* byte alignment */
unsigned int mode: 4; /* type of descriptor and its use */
unsigned int structure: 4; /* structure of symbol */
unsigned int hash: 1; /* set if arg_type is hashed */
int arg_type: 15; /* data type */
} arg_desc;
unsigned int word;
};
struct symbol_extension_record {
unsigned int type: 8; /* always ST_SYM_EXT */
unsigned int max_num_args: 8; /* max # of parameters */
unsigned int min_num_args: 8; /* min # of parameters */
unsigned int num_args: 8; /* actual # of parameters */
union arg_descriptor symbol_desc; /* symbol type desc. */
union arg_descriptor argument_desc[3]; /* first 3 parameters */
};
struct argument_desc_array {
unsigned int type: 8; /* always ST_ARG_EXT */
unsigned int reserved: 24; /* reserved */
union arg_descriptor argument_desc[4]; /* next 4 parameters */
};
arg_descriptor の alignment フィールドは、データの最小整列を示します。ここで、 n の値は
2^n バイトの整列を表わします。 arg_descriptor 内の mode\c 、structure\c 、および arg_type の各フィールドの値
(データ型がハッシュされないとき) を次表に示します。
| 値 | モード | 構造 | arg_type |
|---|
| 0 | 任意 | 任意 | 任意 |
| 1 | 値パラメータ | スカラー | void |
| 2 | 参照パラメータ | 配列 | 符号付きバイト |
| 3 | 値の結果 | 構造体 | 符号なしバイト |
| 4 | 名称 | ポインター | 符号付きショート |
| 5 | 変数 | ロングポインター | 符号なしショート |
| 6 | 関数戻り値 | C 文字列 | 符号付きロング |
| 7 | 手続き | Pascal 文字列 | 符号なしロング |
| 8 | ロング参照パラメータ | 手続き | 符号付きダブルワード |
| 9 | | 関数 | 符号なしダブルワード |
| 10 | | ラベル | ショート実数 |
| 11 | | | 実数 |
| 12 | | | ロング実数 |
| 13 | | | ショート複素数 |
| 14 | | | 複素数 |
| 15 | | | ロング複素数 |
| 16 | | | パック 10 進数 |
| 17 | | | 構造体/配列 |
手続きエントリー点の場合、パラメータ再配置ビットが、仮パラメータと戻り値の位置を定義します。通常、パラメータリストの最初の
4 ワードは、スタックではなく汎用レジスタ (r26-r23)
で渡され、戻り値は r29 で返されます。これに対し、この範囲の浮動小数点パラメータは、浮動小数点レジスタ
(fr4-fr7) で渡され、浮動小数点値は fr4 で返されます。パラメータ再配置ビットは、パラメータリストの最初の
4 ワードと戻り値を記述する 5 組のビットで構成されます。最上位の
1 組のビットが最初のパラメータワードを記述し、最下位の 1 組のビットは戻り値を表します。これらのビットの意味を次表に示します。
| ビット | 意味 |
|---|
| 00 | パラメータも戻り値もなし |
| 01 | パラメータまたは戻り値は汎用レジスタ |
| 10 | パラメータまたは戻り値は浮動小数点レジスタ |
| 11 | 倍精度値 |
倍精度浮動小数点パラメータの場合、奇数のパラメータワードは 11 とマークされ、奇数のパラメータワードは 10 とマークされるはずです。倍精度浮動小数点戻り値は単に 11 とマークされます。
手続きの呼び出しごとに、類似のビットの集合がタグ付けされる
(以下の「再配置情報」を参照) ので、リンカは、各呼び出しを、予想される手続きエントリー点と照合できます。呼び出しとエントリー点が一致しない場合、リンカは、パラメータと戻り値を適宜再配置するポインターの控えを作成します。
再配置情報
初期化されたサブスペースはそれぞれ、そのサブスペース内のデータに適用される解決 情報の範囲を定義します。解決情報要求は、再配置が必要な各ワード、または満たされ ていない参照の入っている各ワードと対応させられます。シリーズ
800 システム上 で HP-UX リリース 3.0 以前に作成された再配置可能オブジェクトファイルでは、各
解決情報要求は、リンク時に記入されるコードまたはデータを記述する
5 ワードの構造 体です。リリース 3.0 以降で作成されたオブジェクトファイルには、サブスペース
の各バイトを記述する可変長の解決情報要求が入っています。ファイルヘッダー内の version_id フィールドは、これら 2 つの形式を区別します。古いオブジェクトファイルには定数 VERSION_ID があり、新しいオブジェクトファイルには定数 NEW_VERSION_ID があります。
古いオブジェクトファイルでは、解決情報はゼロ個、1 個、または
2 個のシンボル と 1 個の定数を含む式を計算し、その結果からビットの
1 フィールドを抽出し、それら のビットを (プレシジョンアーキテクチャ命令セットに対応する)
いくつかの異なる 形式でため込めます。サブスペースディクショナリエントリーの fixup_request_index フィールドは、ファイルヘッダーで定義される解決情報要求領域をインデックスで指 し示し、 fixup_request_quantity フィールドは、そのサブスペースに使用される解決情報要求の数を指します。解決情報
要求の構造体は、 <reloc.h> に入っています。
struct fixup_request_record {
unsigned int need_data_ref: 1; /* reserved */
unsigned int arg_reloc: 10; /* parameter relocation bits */
unsigned int expression_type: 5; /* how to compute value */
unsigned int exec_level: 2; /* reserved */
unsigned int fixup_format: 6; /* how to deposit bits */
unsigned int fixup_field: 8; /* field to extract */
unsigned int subspace_offset; /* subspace offset of word */
unsigned int symbol_index_one; /* index of first symbol */
unsigned int symbol_index_two; /* index of second symbol */
int fixup_constant; /* constant */
};
/* Values for expression_type */
#define e_one 0 /* symbol1 + constant */
#define e_two 1 /* symbol1 - symbol2 + constant */
#define e_pcrel 2 /* symbol1 - pc + constant */
#define e_con 3 /* constant */
#define e_plabel 7 /* symbol1 + constant */
#define e_abs 18 /* absolute, 1st sym index is address */
/* Values for fixup_field (assembler mnemonics shown) */
#define e_fsel 0 /* F': no change */
#define e_lssel 1 /* LS': inverse of RS' */
#define e_rssel 2 /* RS': rightmost 11 bits, signed */
#define e_lsel 3 /* L': leftmost 21 bits */
#define e_rsel 4 /* R': rightmost 11 bits */
#define e_ldsel 5 /* LD': inverse of RD' */
#define e_rdsel 6 /* RD': rightmost 11 bits, filled left with ones */
#define e_lrsel 7 /* LR': L' with "rounded" constant */
#define e_rrsel 8 /* RR': R' with "rounded" constant */
#define e_nsel 9 /* N1': set all bits to zero: for id of 3-inst
code gen sequence */
/* Values for fixup_format (typical instructions shown) */
#define i_exp14 0 /* 14-bit immediate (LDW, STW) */
#define i_exp21 1 /* 21-bit immediate (LDIL, ADDIL) */
#define i_exp11 2 /* 11-bit immediate (ADDI, SUBI) */
#define i_rel17 3 /* 17-bit pc-relative (BL) */
#define i_rel12 4 /* 12 bit pc-relative (COMBT, COMBF, etc.) */
#define i_data 5 /* whole word */
#define i_none 6
#define i_abs17 7 /* 17-bit absolute (BE, BLE) */
#define i_milli 8 /* 17-bit millicode call (BLE) */
#define i_break 9 /* reserved (no effect on HP-UX) */
新しいオブジェクトファイルでは、再配置エントリーはバイトストリームで構成さ
れます。サブスペースディクショナリエントリー内の fixup_request_index フィールドはファイルヘッダーで定義された解決情報ディクショナリへのバイトオ
フセットであり、 fixup_request_quantity フィールドはそのサブスペースに関する解決情報要求ストリームの長さをバイト単位で
定義します。各解決情報要求の最初のバイト (命令コード) で、要求が識別され、要求
の長さが決定されます。
一般に、解決情報ストリームは、 a.out ファイル内のデータをリンカがどのように配置するかを制御する一連のリンカ命令です
。入力サブスペースから出力サブスペースに変更なしに 1 バイトまたは複数バイトをリ
ンカにコピーさせる解決情報要求もありますし、複数ワードを再配置したり、外部参照
を解決するようリンカに指示する解決情報要求もあります。出力サブスペースにゼロを
挿入したり、または入力サブスペースからデータをコピーせずに領域を初期化しないま
まにするようリンカに指示する解決情報要求もありますし、新しいデータを出力ファイ
ルに入れずにコード内のポイントを記述するようリンカに指示する解決情報要求もあり
ます。
インクルードファイル <reloc.h> は、主な各命令コードについて定数を定義します。数多くの解決情報要求が、ある範囲
の命令コードを使用します。範囲の先頭の定数だけが定義されます。各解決情報要求の
意味を以下に説明します。各解決情報の命令コードの範囲とパラメータについては、
その下の表で説明します。
| R_NO_RELOCATION | | 再配置なしに L バイトだけコピー |
| R_ZEROES | | L 個のゼロバイトを出力シーケンスに挿入 |
| R_UNINIT | | 出力サブスペース内の L バイトをスキップ |
| R_RELOCATION | | 再配置を行いながら 1 データワードをコピー。ワードには、自身のサブスペースに相対的な
32 ビットのポインターが含まれると仮定する |
| R_DATA_ONE_SYMBOL |
| | | シンボルインデックスが S の外部シンボルに相対的に、再配置を行いながら
1 ワードをコピー |
| R_DATA_PLABEL | | シンボル S を参照しながら、1 データワードを 32 ビットの手続きラベルとしてコピー。ワードのオリジナルの内容は
0 (静的リンクなし) または 2 (静的リンク必要) でなければならない |
| R_SPACE_REF | | 1 データワードをスペース参照としてコピー。この解決情報は現時点ではサポートされていない |
| R_REPEATED_INIT | | 出力サブスペース内の M バイトを埋めるデータを複写しながら、入力サブスペースから
L バイトをコピー |
| R_PCREL_CALL | | 再配置を行いながら 1 命令ワードをコピー。ワードは、プログラムカウンターに相対的な手続き呼び出し命令と仮定される
(たとえば、 BL) 。ターゲットの手続きは、シンボル
S で識別され、パラメータ再配置ビットは R である |
| R_ABS_CALL | | 再配置を行いながら 1 命令ワードをコピー。ワードは絶対的な手続き呼び出し命令と仮定される
(たとえば、 BLE) 。ターゲットの手続きは、シンボル
S で識別され、パラメータ再配置ビットは R である |
| R_DP_RELATIVE | | 再配置を行いながら 1 命令ワードをコピー。ワードは、データポインターに相対的なロード命令または保存命令と仮定される
(たとえば、 ADDIL\c 、LDW\c 、STW)
。ターゲットシンボルはシンボル S で識別される。リンカは、シンボル
S の値とシンボル $global$ の値の間の相違を形成する。通常、 $global$ の値は必ずレジスタ
27 に入れられる。命令の変位フィールドには小さな定数を入れることができる |
| R_DLT_REL | | 再配置を行いながら 1 命令ワードをコピー。ワードは、レジスタ
18 に相対的なロード命令または保存命令と仮定される (たとえば、 LDW\c 、LDO\c 、STW)
。ターゲットシンボルはシンボル S で識別される。リンカは、シンボル
S についてレジスタ 18 (位置独立コード内のリンクテーブルポインター用に予約済み)
に相対的なリンクテーブルオフセットを計算する |
| R_CODE_ONE_SYMBOL |
| | | 再配置を行いながら 1 命令ワードをコピー。ワードは、シンボル S
を参照する命令と仮定される (たとえば、 LDIL\c 、LDW\c 、BE)
。命令の変位フィールドには小さな定数を入れることができる |
| R_MILLI_REL | | 再配置を行いながら 1 命令ワードをコピー。ワードは、ショートミリコード呼び出し命令と仮定される
(たとえば、 BLE) 。リンカは、ターゲットシンボル
S の値とモジュール内のシンボル 1 の値の間の相違を形成する。通常、シンボル
1 の値は、BLE 命令で使用される基底レジスタに既にロード済みでなければならない。命令の変位フィールドには小さな定数を入れることができる |
| R_CODE_PLABEL | | 再配置を行いながら 1 命令ワードをコピー。ワードは、シンボル
S を参照している手続きラベル (たとえば、 LDIL\c 、LDO)
を形成するコードシーケンスの一部と仮定される。 LDO 命令の変位フィールドには値
0 (静的リンクでない) または 2 (静的リンクが必要) が入らなければならない |
| R_BREAKPOINT | | 条件に応じて 1 命令ワードをコピー。HP-UX では、リンカは必ずワードを NOP 命令と置き換える |
| R_ENTRY | | 手続きエントリー点を定義。スタックアンワインドビット
U、およびフレームサイズ F が、スタックアンワインド記述子に記録される |
| R_ALT_ENTRY | | 代わりの手続きエントリー点を定義 |
| R_EXIT | | 手続き終了点を定義 |
| R_BEGIN_TRY | | 試行/回復領域の先頭を定義 |
| R_END_TRY | | 試行/回復領域の末尾を定義。オフセット R は、領域の末尾から、回復ブロックの先頭までの距離をバイト単位で定義する |
| R_BEGIN_BRTAB | | 分岐テーブルの先頭を定義 |
| R_END_BRTAB | | 分岐テーブルの末尾を定義 |
| R_AUX_UNWIND | | 補助アンワインドテーブルを定義。 CN は、コンパイル単位文字列テーブルの先頭のラベルとなるシンボルインデックスである。 SN は、有効範囲名称文字列のオフセットで、 CN に相対的である。 SK は有効範囲の種類を指定する整数である |
| R_STATEMENT | | 文番号 N の先頭を定義 |
| R_SEC_STATEMENT | | 2 次的文番号 N の先頭を定義 |
| R_DATA_EXPR | | 式スタックから 1 ワード取り出し、入力サブスペースの
1 データワードにその取り出した値を加え、出力サブスペースにコピー |
| R_CODE_EXPR | | 式スタックから 1 ワード取り出し、入力サブスペースの
1 命令ワードの命令変位フィールドにその取り出した値を加えながら、出力サブスペースにコピー |
| R_FSEL | | 命令に該当するデフォルトの代わりに、次の解決情報要求に
F\(fm フィールドを使用 |
| R_LSEL | | 命令に該当するデフォルトの代わりに、次の解決情報要求に
L クラスフィールド選択子を使用。現在の丸めモードにしたがって、L\(fm、LS\(fm、LD\(fm、または
LR\(fm が使用できる |
| R_RSEL | | 命令に該当するデフォルトの代わりに、次の解決情報要求に
R クラスフィールド選択子を使用。現在の丸めモードにしたがって、R\(fm、RS\(fm、RD\(fm、または
RR\(fm が使用できる |
| R_N_MODE | | 切り捨てモード (L\(fm/R\(fm) を選択。これは各サブスペースの始めでのデフォルトモードである。この設定は、明示的に変更されるまで、またはサブスペースの終わりまで有効である |
| R_S_MODE | | 最も近いページに四捨五入モード (LS\(fm/RS\(fm) を選択。この設定は、明示的に変更されるまで、またはサブスペースの終わりまで有効である |
| R_D_MODE | | 切り上げモードを (LD\(fm/RD\(fm) を選択。この設定は、明示的に変更されるまで、またはサブスペースの終わりまで有効である |
| R_R_MODE | | 調整済み定数で切り捨てモード (LR\(fm/RR\(fm) を選択。この設定は、明示的に変更されるまで、またはサブスペースの終わりまで有効である |
| R_DATA_OVERRIDE | | 入力サブスペースのデータワードまたは命令からの定数の代わりに、次の解決情報要求に定数
V を使用 |
| R_TRANSLATED | | 「変換済み」モードをトグル。この解決情報要求は、再配置可能リンクの間に、もともと古い形式の再配置可能なオブジェクトファイルから読み取られたサブスペースを示すためにだけ、リンカが生成する |
| R_COMP1 | | 操作をスタック。この解決情報要求の 2 バイト目には、二次命令コードが入れられる。以下の説明で、A
はスタックの一番上、B はスタックの次の項目を指す。スタック上の項目はすべて符号付き
32 ビット整数とみなされる。 | R_PUSH_PCON1 | | (正の) 定数 V をプッシュ | | R_PUSH_DOT | | 現在の仮想アドレスをプッシュ | | R_MAX | | A と B を取り出してから、max(A, B) をプッシュ | | R_MIN | | A と B を取り出してから、min(A, B) をプッシュ | | R_ADD | | A と B を取り出してから、A + B をプッシュ | | R_SUB | | A と B を取り出してから、B \(mi A をプッシュ | | R_MULT | | A と B を取り出してから、A * B をプッシュ | | R_DIV | | A と B を取り出してから、B / A をプッシュ | | R_MOD | | A と B を取り出してから、B % A をプッシュ | | R_AND | | A と B を取り出してから、A & B をプッシュ | | R_OR | | A と B を取り出してから、A | B をプッシュ | | R_XOR | | A と B を取り出してから、A XOR B をプッシュ | | R_NOT | | A をその補数で置き換え | | R_LSHIFT | | C = 0 の場合、A と B を取り出してから、B << A をプッシュ。そうでない場合は、A
を << C で置き換え | | R_ARITH_RSHIFT | | C = 0 の場合、A と B を取り出してから、B >> A をプッシュ。そうでない場合は、A
を A >> C で置き換え。シフトでは符号拡張を行う | | R_LOGIC_RSHIFT | | C = 0 の場合、A と B を取り出してから、B >> A をプッシュ。そうでない場合は、A
を A >> C で置き換え。シフトではゼロを埋める | | R_PUSH_NCON1 | | (負の) 定数 V をプッシュ |
|
| R_COMP2 | | その他のスタック操作 | R_PUSH_PCON2 | | (正の) 定数 V をプッシュ | | R_PUSH_SYM | | シンボル S の値をプッシュ | | R_PUSH_PLABEL | | シンボル S の手続きラベル値をプッシュ。静的リンクビットは
L | | R_PUSH_NCON2 | | (負の) 定数 V をプッシュ |
|
| R_COMP3 | | その他のスタック操作 | R_PUSH_PROC | | 手続きエントリー点 S の値をプッシュ。パラメータ再配置ビットは
R | | R_PUSH_CONST | | 定数 V をプッシュ |
|
| R_PREV_FIXUP | | リンカは、最後の 4 つの重複しない複数バイトの解決情報要求の待ち行列を保持する。これは、待ち行列にあるものと同一の解決情報要求の短縮形である。待ち行列インデックス
X は、4 つのうちの 1 つを参照する。X = 0 は、最も新しいものを指す。この解決情報要求の副次効果として、参照された解決情報は待ち行列の前面に移動される |
| R_N0SEL | | 次の解決情報が、コンパイラが生成した、データにアクセスするための
3 命令シーケンスの最初のものに適用され、共有ライブラリデータのインポートを使用可能にすることを示す |
| R_N1SEL | | 次の解決情報用に、(N\(fm) フィールド選択子を使用。これは、命令の変位にゼロのビットが使用されることを示す。この解決情報は、(共有ライブラリデータをインポートするため)
データにアクセスする 3 命令シーケンスを識別するのに使用される |
| R_LINETAB | | 行テーブルの先頭を定義。CU は、行テーブルの先頭のラベルであるシンボルのインデックスである。SM
は、CU シンボルに相対的なオフセットである。ES は、現在の行テーブルについて、バージョン情報を示す |
| R_LINETAB_ESC | | 行テーブルに記入するエスケープエントリーを定義。ES
は、テーブルに記入されるエスケープエントリーを示す。M は、raw の
8 ビットテーブルデータとして解釈される R_STATEMENT 解釈情報の数を示す |
| R_LTP_OVERRIDE | | 次の解決情報を上書きする。この解決情報は、共有ライブラリを生成するときに、再配置なしに
1 データワードをコピーする R_DATA_ONE_SYMBOL 解決情報であると予想される。リンクテーブルポインターに相対的なシンボルの絶対バイトオフセットがコピーされる。リンカが完全な実行可能ファイルを生成している場合は、絶対仮想アドレスがコピーされる |
| R_COMMENT | | コンパイラからリンカへコメント情報を渡すために使用する解決情報 |
| R_TP_OVERRIDE | | 命令の解決時にスレッドローカル記憶領域のオフセットを使用するため、R_DP_RELATIVE、R_DLT_REL、R_DATA_ONE_SYMBOL
解決情報のうちの次の 1 つを上書きする。 この解決情報は、スレッドローカル記憶領域シンボルの不一致の際にも使用される。 |
| R_RESERVED | | この範囲内の解決情報は、コンパイラとリンカが内部的に使用するために予約済みである |
次表に、各範囲の命令コードについてのニーモニック解決情報要求タイプと長さ、およびパラメータ情報を示します。パラメータの欄で、シンボル
D は、命令コードと、そのテーブルエントリーが記述する範囲の先頭との間の差を指します。シンボル
B1、B2、B3、および B4 はそれぞれ、解決情報要求の、次の 1、2、3、または
4 バイトの値を指します。
| | 命令 | | |
|---|
| ニーモニック | コード | 長さ | パラメータ |
|---|
| R_NO_RELOCATION | 0-23 | 1 | L = (D+1) * 4 |
| 24-27 | 2 | L = (D<<8 + B1 +
1) * 4 |
| 28-30 | 3 | L = (D<<16 + B2
+ 1) * 4 |
| 31 | 4 | L = B3 + 1 |
| R_ZEROES | 32 | 2 | L = (B1 + 1) * 4 |
| 33 | 4 | L = B3 + 1 |
| R_UNINIT | 34 | 2 | L = (B1 + 1) * 4 |
| 35 | 4 | L = B3 + 1 |
| R_RELOCATION | 36 | 1 | なし |
| R_DATA_ONE_SYMBOL | 37 | 2 | S = B1 |
| 38 | 4 | S = B3 |
| R_DATA_PLABEL | 39 | 2 | S = B1 |
| 40 | 4 | S = B3 |
| R_SPACE_REF | 41 | 1 | なし |
| R_REPEATED_INIT | 42 | 2 | L = 4; M = (B1 + 1) * 4 |
| 43 | 3 | L = (B1 + 1) * 4; M = (B1 + 1) * L |
| 44 | 5 | L = (B1 + 1) * 4; M = (B3 + 1) * 4 |
|