60 votes

Que signifie KEEP dans un linker script ?

El Manuel LD n'explique pas ce que le KEEP fait. Voici un extrait d'un linker tiers script qui présente les caractéristiques suivantes KEEP . Que fait le KEEP commande faire dans 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

8 votes

KEEP est documenté dans ce version du manuel.

58voto

Marco van de Voort Points 15378

Il semble que LD conserve les symboles dans la section même si les symboles ne sont pas référencés. (--gc-sections).

Généralement utilisé pour les sections qui ont une signification particulière dans le processus de démarrage binaire, plus ou moins pour marquer les racines de l'arbre de dépendance.


(Pour Sabuncu ci-dessous)

Arbre de dépendance :

Si vous éliminez le code inutilisé, vous analysez le code et marquez toutes les sections accessibles (code + variables globales + constantes).

Ainsi, vous choisissez une section, vous la marquez comme "utilisée" et vous voyez à quelle autre section (inutilisée) elle fait référence, puis vous marquez ces sections comme "utilisées", et vous vérifiez à quoi elles font référence, etc.

Les sections qui ne sont pas marquées "utilisées" sont alors redondantes et peuvent être éliminées.

Étant donné qu'une section peut faire référence à plusieurs autres sections (par exemple, une procédure appelant trois autres sections différentes), si l'on dessine le résultat, on obtient un arbre.

Racines :

Le principe ci-dessus nous laisse cependant avec un problème : quelle est la "première" section qui est toujours utilisée ? Le premier nœud (racine) de l'arbre, pour ainsi dire ? C'est ce que fait "keep()", il indique à l'éditeur de liens quelles sections (si elles sont disponibles) sont les premières à être regardées. Par conséquent, elles sont toujours liées.

Il s'agit généralement de sections qui sont appelées par le chargeur de programme pour effectuer des tâches liées à la liaison dynamique (peut être facultative et dépend du système d'exploitation/format de fichier) et au point d'entrée du programme.

7 votes

+1 Qu'est-ce que l'arbre de dépendance ? Pourquoi est-il important de marquer ses racines ? Merci.

1 votes

J'ajoute une courte explication au message.

0 votes

MERCI ! Vous dites "...indique au linker quelles sections (si elles sont disponibles) sont les premières à être regardées". Pourquoi une section ne serait-elle pas disponible si elle est marquée comme KEEP ? Peut-être que je manque certaines des bases ici, mais ce sujet est vraiment obscur (pourtant vital) et j'ai du mal à trouver des ressources pour m'éduquer.

20voto

Ciro Santilli Points 3341

Exemple minimal de Linux IA-32 qui illustre son utilisation

principal.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

lien.ld

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

Compilez et exécutez :

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

Sortie :

1

Si nous commentons le KEEP la sortie est :

2

Si on est soit :

  • ajouter un mannequin mov keep, %eax
  • supprimer --gc-sections

La sortie retourne à 1 .

Testé sur Ubuntu 14.04, Binutils 2.25.

Explication

Il n'y a aucune référence au symbole keep et, par conséquent, la section qu'il contient .keep .

Par conséquent, si le garbage collection est activé et que nous n'utilisons pas de KEEP pour faire une exception, cette section ne sera pas mise dans l'exécutable.

Puisque nous ajoutons 4 à l'adresse de before si le keep n'est pas présente, alors l'état de sortie sera 2 qui est présent sur le prochain .after section.

TODO : rien ne se passe si on supprime le "a" de .keep ce qui le rend allouable. Je ne comprends pas pourquoi il en est ainsi : cette section sera placée dans la section .text qui, en raison de son nom magique, sera allouable.

2voto

leesagacious Points 83

Force l'éditeur de liens à conserver certaines sections spécifiques

SECTIONS 
{
....
....

*(.rodata .rodata.*)

KEEP(*(SORT(.scattered_array*)));
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X