2012-05-02 1 views
15

Un fichier ELF pour executables a un en-tête de programme (segment) et un en-tête de section, qui peut être vu à travers readelf -a, voici un exemple:quelle partie du fichier ELF doit être chargée dans la mémoire?

enter image description here

enter image description here

Les deux images ci-dessus sont en-tête de section et en-tête de programme (segment), respectivement. On peut voir qu'un en-tête de segment est composé de plusieurs en-têtes de section, qui sont utilisés pour charger le programme dans la mémoire.

Est-il seulement nécessaire que les sections .text, .rodata, .data, .bss soient chargées dans la mémoire?

Est-ce que toutes les autres sections du segment (par exemple, les détecteurs, les .derniers .jcr dans le 3ème segment) sont utilisées pour l'alignement?

+1

Pour _aligning_? –

+0

@ Adriano, oui alignement à la taille de la page, si différente protection peut être utilisée pour une partie différente du programme, par exemple .text (rx) ,. data (rw-) –

Répondre

18

Les sections et les segments sont deux concepts complètement différents. Les sections se rapportent à la sémantique des données qui y sont stockées (c'est-à-dire à quoi elles seront utilisées) et sont réellement non pertinentes une fois qu'un programme ou une bibliothèque partagée est lié, sauf à des fins de débogage. Vous pouvez même supprimer entièrement les en-têtes de section (ou les écraser avec des déchets aléatoires) et un programme fonctionnera toujours.

Les segments (c'est-à-dire les directives de chargement d'en-tête de programme) sont ce que le noyau et/ou le lieur dynamique regarde réellement lors du chargement d'un programme. Par exemple, dans votre cas, vous avez deux directives de chargement. Le premier provoque le mappage de la première 4k (1 page) du fichier à l'adresse 0x08048000 et indique que seuls les premiers 0x4b8 octets de ce mappage sont réellement utilisés (le reste est l'alignement). La seconde provoque le mappage des premières 8k (2 pages) du fichier à l'adresse 0x08049000. La grande majorité de cela est l'alignement. Les premiers 0xf14 octets ne font pas partie de la directive de chargement (alignement juste) et seront gaspillés. À partir de 0x08049f14, 0x108 octets mappés à partir du fichier sont réellement utilisés et 0x10 octets (pour atteindre la taille de 0x118) sont remplis par le chargeur (noyau ou éditeur de liens dynamiques). Cela s'étend jusqu'à 0x0804a02c (dans la deuxième page mappée). Le reste de la deuxième page mappée est inutilisé/gaspillé (mais malloc peut être en mesure de le récupérer pour l'utiliser dans le tas).

Enfin, alors que les en-têtes de section ne seront pas utilisés du tout, le contenu de nombreuses sections différentes peut être utilisé par votre programme pendant son exécution. Notez que les plages d'adresses .ctors et .dtors se trouvent au début du deuxième mappage de charge. Elles sont donc mappées et accessibles par le programme au moment de l'exécution (le code de démarrage/de sortie utilisera les constructeurs et destructeurs globaux si C++ ou Le code "GNU C" avec l'attribut ctor/dtor a été utilisé). Notez également que .data commence à l'adresse 0x0804a00c, dans la deuxième page mappée. Cela permet de protéger la première page en lecture seule après l'application des relocalisations (la directive RELRO dans l'en-tête du programme).

+0

+1 pour signaler GNU_RELRO – SquareRootOfTwentyThree

+0

Est-ce que C ont des constructeurs ou des destructeurs comme C++? –

+0

Non, mais GCC n'est pas C, c'est "GNU C". Vous pouvez faire toutes sortes de choses non standard comme des exceptions et des constructeurs. –

Questions connexes