57

LDのマニュアルには、このKEEPコマンドが何をするかが説明されていません。以下は、KEEP. KEEPコマンドは で何をしldますか?

SECTIONS
{  
    .text :
    {
        . = ALIGN(4);
        _text = .;
        PROVIDE(stext = .);
        KEEP(*(.isr_vector))
        KEEP(*(.init))
        *(.text .text.*)        
        *(.rodata .rodata.*)        
        *(.gnu.linkonce.t.*)
        *(.glue_7)
        *(.glue_7t)
        *(.gcc_except_table)
        *(.gnu.linkonce.r.*)
        . = ALIGN(4);
        _etext = .;
        _sidata = _etext;
        PROVIDE(etext = .);   
            _fini = . ;
                *(.fini)

    } >flash
4

3 に答える 3

55

Afaik LD は、シンボルが参照されていない場合でも、セクション内のシンボルを保持します。(--gc-セクション)。

通常、バイナリの起動プロセスで特別な意味を持つセクションに使用され、多かれ少なかれ依存関係ツリーのルートをマークします。


(以下サブンクの場合)

依存関係ツリー:

未使用のコードを削除する場合は、コードを分析し、到達可能なすべてのセクション (コード + グローバル変数 + 定数) をマークします。

したがって、セクションを選択し、それを「使用済み」としてマークし、それが参照する他の(未使用の)セクションを確認してから、それらのセクションを「使用済み」としてマークし、それらが参照するものを確認します。

「使用済み」とマークされていないセクションは冗長であり、削除できます。

セクションは他の複数のセクションを参照できるため (たとえば、1 つのプロシージャが他の 3 つの異なるセクションを呼び出すなど)、結果を描画するとツリーが得られます。

ルーツ:

ただし、上記の原則には問題があります。常に使用される「最初の」セクションは何ですか? いわばツリーの最初の節(ルート)?これは "keep()" が行うことであり、リンカにどのセクション (利用可能な場合) を最初に確認するかを伝えます。結果として、これらは常にリンクされています。

通常、これらは動的リンクに関連するタスクを実行するためにプログラム ローダーから呼び出されるセクション (オプションであり、OS/ファイル形式に依存する場合があります) と、プログラムのエントリ ポイントです。

于 2012-03-22T20:42:48.633 に答える
19

その使用法を示す最小限の Linux IA-32 の例

main.S

.section .text
.global _start
_start:
    /* Dummy access so that after will be referenced and kept. */
    mov after, %eax
    /*mov keep, %eax*/

    /* Exit system call. */
    mov $1, %eax

    /* Take the exit status 4 bytes after before. */
    mov $4, %ebx
    mov before(%ebx), %ebx

    int $0x80

.section .before
    before: .long 0
/* TODO why is the `"a"` required? */
.section .keep, "a"
    keep: .long 1
.section .after
    after: .long 2

link.ld

ENTRY(_start)
SECTIONS
{
    . = 0x400000;
    .text :
    {
        *(.text)
        *(.before)
        KEEP(*(.keep));
        *(.keep)
        *(.after)
    }
}

コンパイルして実行します。

as --32 -o main.o main.S
ld --gc-sections -m elf_i386 -o main.out -T link.ld main.o
./main.out
echo $?

出力:

1

行をコメントアウトするとKEEP、出力は次のようになります。

2

次のいずれかの場合:

  • ダミーを追加mov keep, %eax
  • 削除する--gc-sections

出力は に戻り1ます。

Ubuntu 14.04、Binutils 2.25 でテスト済み。

説明

シンボルへの参照がないkeepため、そのセクションを含んでいます.keep

したがって、ガベージコレクションが有効になりKEEP、例外を作成するために使用しない場合、そのセクションは実行可能ファイルに入れられません。

のアドレスに 4 を追加しているためbeforekeepセクションが存在しない場合、終了ステータスは2次の.afterセクションに存在する になります。

"a"TODO: fromを削除しても何も起こらないため、.keep割り当て可能になります。なぜそうなのかわかりません。そのセクションは.textセグメント内に配置され、その魔法の名前のために割り当て可能になります。

于 2015-10-08T10:44:42.743 に答える