44 votes

.sev section dans le fichier elf

Si je comprends bien, l' .bss section ELFE de fichiers est utilisé pour allouer de l'espace pour initialisé à zéro des variables. Notre outil de la chaîne de produit ELFE de fichiers, d'où ma question: est ce que l' .bss section ont en fait pour contenir tous ces zéros? C'est un terrible gaspillage d'espaces que quand, par exemple, j'alloue un mondial des dix mégaoctets tableau, il en résulte une dizaine de mégaoctets de zéros dans le fichier ELF. Que suis-je voir le problème ici?

68voto

Johannes Schaub - litb Points 256113

A été un certain temps depuis que j'ai travaillé avec ELF. Mais je pense que je me souviens encore de ce genre de choses. Non, il n'est pas physiquement contiennent ces zéros. Si vous regardez dans un ELFE fichier d'en-tête du programme, puis vous verrez de chaque en-tête a deux nombres: l'Un est la taille du fichier. Et l'autre est la taille de la section a quand alloué dans la mémoire virtuelle (readelf -l ./a.out):

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4
  INTERP         0x000114 0x08048114 0x08048114 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00454 0x00454 R E 0x1000
  LOAD           0x000454 0x08049454 0x08049454 0x00104 0x61bac RW  0x1000
  DYNAMIC        0x000468 0x08049468 0x08049468 0x000d0 0x000d0 RW  0x4
  NOTE           0x000128 0x08048128 0x08048128 0x00020 0x00020 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4

Les en-têtes de type LOAD sont celle qui sont copiés dans la mémoire virtuelle lorsque le fichier est chargé de l'exécution. D'autres en-têtes contiennent d'autres informations, comme les bibliothèques partagées qui sont nécessaires. Comme vous le voyez, l' FileSize et MemSiz différer de façon importante de l'en-tête qui contient l' bss section (le deuxième LOAD - en un):

0x00104 (file-size) 0x61bac (mem-size)

Pour cet exemple de code:

int a[100000];
int main() { }

L'ELFE de la spécification indique que la partie d'un segment de la mem-taille est plus grande que la taille de fichier est juste rempli avec des zéros dans la mémoire virtuelle. Le segment de la section de la cartographie de la deuxième LOAD - tête est comme ceci:

03     .ctors .dtors .jcr .dynamic .got .got.plt .data .bss

Donc, il ya quelques autres articles de la là aussi. Pour le C++ constructeur/destructeurs. La même chose pour Java. Ensuite, il contient une copie de l' .dynamic section et d'autres choses utiles pour la liaison dynamique (je crois que c'est l'endroit qui contient les bibliothèques partagées nécessaires parmi d'autres choses). Après que l' .data section qui contient initialisé les variables globales et locales des variables statiques. À la fin, l' .bss section apparaît, qui est rempli par des zéros au moment du chargement, car de taille de fichier pour ne pas le couvrir.

Par ailleurs, vous pouvez voir en sortie de section un symbole particulier va être placés par l'aide de la -M option de l'éditeur de liens. Pour gcc, vous utilisez -Wl,-M pour mettre l'option par le biais de l'éditeur de liens. L'exemple ci-dessus montre que l' a est allouée dans .bss. Il peut vous aider à vous assurer que vos objets non initialisées vraiment finir par en .bss et pas ailleurs:

.bss            0x08049560    0x61aa0
 [many input .o files...]
 *(COMMON) 
 *fill*         0x08049568       0x18 00
 COMMON         0x08049580    0x61a80 /tmp/cc2GT6nS.o
                0x08049580                a
                0x080ab000                . = ALIGN ((. != 0x0)?0x4:0x1) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                . = ALIGN (0x4) 
                0x080ab000                _end = .

GCC continue non initialisée globales dans une section COMMUNE par défaut, pour la compatibilité avec les anciens compilateurs, qui permettent d'avoir des variables globales définies deux fois dans un programme, sans définition de plusieurs erreurs. Utiliser -fno-common faire GCC utiliser le .sev sections pour les fichiers de l'objet (ne pas faire une différence pour la finale exécutable lié, parce que, comme vous le voyez, c'est ce qui va devenir un .sev section de sortie de toute façon. Ceci est contrôlé par le linker script. Afficher en ld -verbose). Mais cela ne doit pas vous faire peur, c'est juste un détail interne. Voir la page de man de gcc.

21voto

D.Shawley Points 30324

L' .bss section dans un ELFE de fichier est utilisé pour les données statiques qui n'est pas initialisé par programme, mais la garantie d'être mis à zéro au moment de l'exécution. Voici un petit exemple qui va vous expliquer la différence.

int main() {
    static int bss_test1[100];
    static int bss_test2[100] = {0};
    return 0;
}

Dans ce cas - bss_test1 est placé dans l' .bss , car il est non initialisée. bss_test2 , cependant, est placé dans l' .data segment avec un tas de zéros. Le chargeur dynamique fondamentalement alloue la quantité d'espace réservé pour l' .bss et de zéros avant tout userland code commence à exécuter.

Vous pouvez voir la différence à l'aide de objdump, nm, ou d'autres utilitaires:

moozletoots$ objdump -t a.out | grep bss_test
08049780 l     O .bss   00000190              bss_test1.3
080494c0 l     O .data  00000190              bss_test2.4

C'est habituellement l'une des premières surprises que les développeurs de logiciels embarqués exécuter en... jamais initialiser la statique à zéro de manière explicite. Le chargeur dynamique (en général) qui s'en occupe. Dès que vous initialisez rien explicitement, en vous disant que le compilateur/linker pour inclure les données dans le fichier exécutable de l'image.

3voto

mouviciel Points 36624

Un .bss section ne sont pas stockées dans un fichier exécutable. Le plus commun des sections (.text, .data, .bss), seulement .text (en code) et .data (données initialisées) sont présents dans un fichier ELF.

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