4

カスタム リンカー スクリプトを使用する組み込みプログラムに取り組んでいます。プログラムは動作しますが、リンカがいくつかのセクションをメモリに配置する方法に問題がある可能性があることに気付きました。

リンカー スクリプトの関連部分は次のとおりです。

MEMORY {
    ROM (rx)    : ORIGIN = 0x00100000, LENGTH = 16k
    RAM (rwx)   : ORIGIN = 0x00200000, LENGTH = 4k
}

SECTIONS {
    /* Other sections go here. */
    .data : {
...
    } >RAM AT>ROM

    .bss : {
...
    } >RAM

    .stack : {
...
    } >RAM
...
}

MAP ファイルの関連部分は次のとおりです。

.data           0x00200040        0x0 load address 0x001003d4
                0x001003d4                __data_load = LOADADDR (.data)
                0x00200040                __data_start = .
 *(.data)
 *(.data*)
                0x00200040                . = ALIGN (0x4)
                0x00200040                _edata = .

.igot.plt       0x00200040        0x0 load address 0x001003d4
 .igot.plt      0x00000000        0x0 ./debug/sam7s_startup.o

.bss            0x00200040        0x0 load address 0x001003d4
                0x00200040                __bss_start__ = .
 *(.bss)
 *(.bss*)
 *(COMMON)
                0x00200040                . = ALIGN (0x4)
                0x00200040                _ebss = .
                0x00200040                __bss_end__ = .
                0x00200040                PROVIDE (end, _ebss)
                0x00200040                PROVIDE (_end, _ebss)
                0x00200040                PROVIDE (__end__, _ebss)

.stack          0x00200040      0x200 load address 0x001003d4
                0x00200040                __stack_start__ = .

したがって、マップ ファイルから、.bss セクションと .stack セクションが ROM でロード アドレスを取得しているように見えます。これは、次の2行のせいだと思います。

.bss 0x00200040 0x0 load address 0x001003d4
.stack 0x00200040 0x200 load address 0x001003d4

ROMのスペースを占有する意味がないため、これは良くありません。.bss セクションは、現在は空ですが、コードでゼロに設定される初期化されていないグローバル変数が含まれます。スタックは、コードで初期化される RAM の一部でもあります。したがって、これらのセクションのいずれかが ROM のスペースを占有する必要はありません。

私の質問は、.bss と .stack が ROM に読み込まれないようにする正しい方法は何ですか? .bss および .stack セクションの末尾を から に変更する必要があり>RAMます>RAM AT>RAMか? これは少し冗長に思えます。

いくつかのことをテストした後、次のことがわかりました。

(1)(NOLOAD)属性を使用しても (たとえば、 に置き換え.stack :.stack (NOLOAD) :)、.stack セクションと .bss セクションの ROM ロード アドレスを示すマ​​ップ ファイルが生成されます。

(2)RAM AT>RAM上記のように を指定すると、.stack セクションと .bss セクションの ROM ロード アドレスがマップ出力に表示されなくなります。

(3) マップ ファイルに .bss および .stack セクションのロード アドレスが示されている場合、実際には ROM のスペースを占有していないように見えます。.stack セクションの長さは 0x200 バイトですが、実際には ROM 内のそのスペースを占有しているようには見えません。これにフィル値を指定し、リンカー スクリプト内でその後にセクションを配置したとしてもです。リンカー スクリプトでそれに続くセクションは、異なるスタック サイズで移動されません。

したがって、マップ ファイルの出力は、私が考えていることを意味していない可能性があります。.stack および .bss セクションには、実際には ROM 内のロード アドレスがまったく指定されていません。いくつかのことを試してみると、確かにこのように表示されます。特に(NOLOAD)が使用されている場合に、セクションに ROM ロード アドレスが指定されているようにマップ出力が表示される理由を知ることは依然として興味深いでしょう。これは、LD がマップ出力ファイルを生成する方法の単なるバグでしょうか?

関連項目: GNU リンカ スクリプトのロケーション カウンタについて

4

1 に答える 1

5

を探していNOLOADます。Gnu LD 出力セクション タイプを参照してください。私は今あなたの投稿全体を読みましNOLOADた. でNOLOAD、すべてのアドレスが定義されます。「C」コード内でそれらを使用すると、そのアドレスからロードされます。通常、 BSS領域をクリアするアセンブラーで、いくつかの起動コードを提供する必要があります。通常、スタックが初期化されることは想定していません。

NOLOADセクションは、コンパイル/リンク時のようなものmalloc()です。使用するメモリを取得しますが、そこには何も期待しないでください。BSSの場合、リンカー スクリプトで__bss_start__とを定義し__bss_end__、短い初期化ルーチンを記述して、これらの変数/アドレスを使用してこのメ​​モリをクリアします。

注:すべてがマップ ファイルに表示されます。生成されたバイナリには表示されず、ELF にはデータがありません。セクションのメタ情報だけが ELF に保持されます。

編集:マップ ファイル内の読み込みアドレスは、読み込み用のロケーション カウンターのようなものです。ロードアドレスは、ldものを置くために設定されている場所です。ldサイズがゼロの場合、実際にはそこに物を置いていません。マップ出力は言語的に明確ではありません。紛らわしいことはわかりますがld、出力バイナリを作成する際に正しく動作します。BSSは通常NOLOAD、オブジェクト ファイル内で gcc によってマークされているため、この例ではスタックセクションのみにNOLOAD. stackのようなものでは、セクションは実際には必要なく、一連のシンボル宣言だけで機能します。

于 2013-01-27T23:41:28.083 に答える