2012-03-22 9 views
34

Il LD manual non spiega cosa fa il comando KEEP. Di seguito è riportato uno snippet di uno script di linker di terze parti con KEEP. Che cosa fa il comando KEEP in ld?Che cosa significa KEEP in uno script di linker?

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

KEEP è documentato in [questo] (https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep) versione del manuale. – alexei

risposta

37

Afaik LD mantiene i simboli nella sezione anche se i simboli non sono referenziati. (--gc-sezioni).

Solitamente utilizzato per le sezioni che hanno un significato speciale nel processo di avvio binario, più o meno per contrassegnare le radici dell'albero delle dipendenze.


(Per Sabuncu sotto)

Dipendenza albero:

Se si elimina il codice non utilizzato, si analizza il codice e contrassegnare tutte le sezioni raggiungibili (codice + globali variabili + costanti).

Quindi si sceglie una sezione, segnare come "usati" e vedere che cosa altra sezione fa riferimento, allora si contrassegna quelli sezione come "usato", e controllare che cosa fanno riferimento ecc

La sezione che non sono contrassegnati come "usati" sono quindi ridondanti e possono essere eliminati.

Poiché una sezione può fare riferimento a più sezioni diverse (ad esempio una procedura che chiama tre diverse altre), se si disegna il risultato si ottiene un albero.

Roots:

Il principio sopra però ci lascia con un problema: che cosa è la sezione "prima" che viene sempre utilizzato? Il primo nodo (radice) dell'albero per così dire? Questo è ciò che fa "keep()", dice al linker quali sezioni (se disponibili) sono le prime a guardare. Di conseguenza, questi sono sempre collegati in.

In genere si tratta di sezioni chiamate dal programma di caricamento per eseguire attività correlate al collegamento dinamico (può essere facoltativo e dipende dal formato del file/OS) e dal punto di ingresso del programma .

+1

+1 Che cos'è l'albero delle dipendenze? Perché è importante segnare le sue radici? Grazie. – Sabuncu

+0

aggiungo una breve spiegazione al post. –

+0

GRAZIE! Dici "... dice al linker quali sezioni (se disponibili) sono le prime a guardare". Perché una sezione non dovrebbe essere disponibile se è contrassegnata come KEEP? Forse mi mancano alcuni dei fondamenti qui, ma questo argomento è davvero oscuro (ma vitale) e ho difficoltà a trovare risorse per educarmi. – Sabuncu

7

Minimal Linux IA-32 esempio che illustra il suo utilizzo

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 

collegamento.ld:

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

Compilare ed eseguire:

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

uscita:

1 

Se noi commentare la riga KEEP l'output è:

2 

Se ci sia:

  • Aggiungiamo un manichino mov keep, %eax
  • rimuovere --gc-sections

L'uscita risale al 1.

Testato su Ubuntu 14.04, Binutils 2.25.

Spiegazione:

Non v'è alcun riferimento al simbolo keep, e quindi la sua contenenti sezione .keep.

Pertanto, se la garbage collection è abilitata e non si utilizza KEEP per fare un'eccezione, quella sezione non verrà inserita nell'eseguibile.

Poiché stiamo aggiungendo 4 all'indirizzo di before, se la sezione keep non è presente, allora lo stato di uscita sarà 2, che è presente sulla sezione successiva .after.

TODO: non succede nulla se rimuoviamo il "a" da .keep, che lo rende allocabile. Non capisco perché sia ​​così: quella sezione verrà inserita nel segmento .text, che a causa del suo nome magico sarà allocabile.

Problemi correlati