私は、通常の X86 (Linux) マシンだけでなく、ARM 組み込みターゲットでも動作するソフトウェア用のモジュラー ビルド システムを使用しています。私はGNUツールチェーンでコンパイルしているので、ld
.
モジュールの 1 つは、リンカー スクリプトのトリックを使用して、「登録済み」オブジェクトの配列をアセンブルします。オブジェクトは、次のようなマクロで作成されます。
#define RegObject(name, arg1, arg2, etc) \
static TRegObject name \
__attribute__((section ("regobj_table"), used)) = \
{ arg1, arg2, etc }
このモジュールは、次のような暗黙的なリンカー スクリプトもリンク ステップに追加します。
SECTIONS
{
.data : ALIGN(4)
{
regobj_table_start = .;
KEEP(*(regobj_table))
regobj_table_end = .;
}
}
regobj_table_start
とのregobj_table_end
記号は、登録されたオブジェクトを検索するためにコードで使用されます。このソリューションは、ネイティブ (Linux) でコンパイルされたターゲットに対してうまく機能します。
ただし、これは ARM ターゲットでは機能しません。その理由は、.data
セクションのロード メモリ アドレスを定義する、ターゲット (OS なしで実行される小さなマイクロコントローラー) 用のカスタムの既定のリンカー スクリプトがあるためです。これは、セクションがフラッシュ メモリに格納されているためですが、マイクロコントローラが起動すると RAM にコピーされます。リンカー スクリプトの関連部分は次のようになります。
MEMORY
{
ROM (rx) : ORIGIN = 0x00000000, LENGTH = 512k
RAM (rwx) : ORIGIN = 0x40000000, LENGTH = 32k
}
SECTIONS
{
/* ... other stuff ... */
.data :
{
_data = .;
*(.data)
*(.data.*)
} >RAM AT>ROM
/* ... even more stuff ... */
}
これにより、セクションの VMA が.data
0x4000000 の範囲のどこかに設定され、LMA が 0x00000000 の範囲に設定されます。
問題は、暗黙のリンカ スクリプトが のコマンド ラインに追加されるとld
、LMA を忘れて、再び VMA と同じになることです。ld
暗黙のリンカ スクリプトをロードするときに LMA に触れないように指示する方法を必死に探しています。