Retourner aux forums || Retourner au forum Programmation.c
Programmation.c : GCC et taille des exécutables
Posté par Gilles G. () le 26 janvier 2008je viens de me rendre compte que le programme suivant:
fichier: minimal.c
int main(){ return 0;}génère un exécutable de 6,2ko lorsqu'on le compile avec GCC de la façon suivante:
gcc minimal.c -o minimal
Pourtant normalement (sous linux) le code assembleur de ce programme est le suivant:
.global _start
_start: mov $1,%eax /* Mettre 1 dans eax (appel système ''Exit'') */
mov $0,%ebx /* Mettre 0 dans ebx (valeur de retour du programme) */
int $0x80 /* Interruption 0x80, executant un appel systeme sous Linux) */Et ce code assembleur une fois assemblé fait 460 octets.
J'ai l'impression qu'il y a une question de runtime C derrière tout ça, mais j'avoue que j'ai quand même un peu de mal à comprendre comment GCC réussit à inclure plus de 6ko de données inutiles: il n'y a pas de suppression du code mort dans GCC?
Merci pour vos lumières!
> Lire le message (11 commentaires, moyenne: 3,2).
460 octets pour ça ?!?
deux mov et un int ? je crois que tu te fais rouler :)
bon, il faut un poil plus d'enrobage pour que ca tourne mais au final tu peux t'en tirer en 45 octets.
http://www.muppetlabs.com/~breadbox/software/tiny/teensy.htm(...)
Windows has no users. It has hostages.
-
[^]Re: 460 octets pour ça ?!?
Posté par NeoX () le 26/01/2008 à 21:23. (lien). Évalué à 1.surement 460octets avec les commentaires
sinon pour son code qui fait 6.2Ko
il faut surement ajouté les "entetes" qui decrivent le fichier comme etant binaire, eventuellement (enfin j'imagine) le mapping memoire necessaire à ce programme
Gniarf : je viens de lire ton lien, tres instructif.--
Apprendre par les autres, c'est bien.
Apprendre par soi-meme (RTFM, man, et notre ami google) c'est mieux
Readelf, objdump
Deux choses importantes.
La première, c'est que ton code C est fonctionnellement équivalent au code assembleur, mais ce n'est pas pour ça qu'ils sont identiques. main() et _start, c'est pas pareil. Dans le cas du code en C, la fonction main() est appelée par la libc (c'est elle qui définit le _start). Donc, par défaut, ton programme en C est lié dynamiquement à la libc. Ça prend un peu de place.
Ensuite, le plus gourmand en taille : gcc, par défaut, n'est pas avare d'informations.
Utilise readelf -a minimal ou objdump -x minimal pour lister tout ce qui se trouve dans ton exécutable. Toutes les sections présentes dans ton ELF sont facultative et ne servent qu'à donner des informations (par exemple pour déboguer, mais pas seulement).
En bref, ce n'est pas du tout du "code mort". Ce sont des informations complètement facultatives, mais qui peuvent être très utiles.
Le programme sstrip, des Elf-Kickers, permet d'enlever un bon paquet de ces infos facultatives.
-
[^]Re: Readelf, objdump
Posté par Gilles G. () le 26/01/2008 à 22:45. (lien). Évalué à 1.ton code C est fonctionnellement équivalent au code assembleur, mais ce n'est pas pour ça qu'ils sont identiques. main() et _start, c'est pas pareil
C'est justement ça le problème: GCC devrait utiliser la méthode la plus efficace en temps et en taille, non?
Toutes les sections présentes dans ton ELF sont facultatives et ne servent qu'à donner des informations (par exemple pour déboguer, mais pas seulement
Voilà ce que j'ai essayé:
gilles@ordi:~$ strip --strip-all --remove-section=".comment" minimal -o minimal_stripped
gilles@ordi:~$ strip --strip-all --remove-section=".comment" cminimal -o cminimal_stripped
gilles@ordi:~$ ls -l cminimal minimal cminimal_stripped minimal_stripped
-rwxr-xr-x 1 gilles gilles 6332 2008-01-26 22:31 cminimal
-rwxr-xr-x 1 gilles gilles 2556 2008-01-26 22:37 cminimal_stripped
-rwxr-xr-x 1 gilles gilles 596 2008-01-26 22:12 minimal
-rwxr-xr-x 1 gilles gilles 248 2008-01-26 22:37 minimal_stripped
Apparement, la commande strip permet la suppression de code mort dans le cas du programme C mais aussi dans le cas du programme ASM.
Donc au final, en utilisant strip, on a toujours un facteur 10 entre les tailles des exécutables.
PS: Au boulot j'utilise des DSP motorola qui ont 16Ko de mémoire programme, et on arrive quand même à faire pas mal de choses (en assembleur), donc je trouve que prendre 6ko pour un programme en C qui ne fait rien c'est abusé.-
[^]Re: Readelf, objdump
Posté par Amand Tihon (page perso, ) le 27/01/2008 à 10:46. (lien). Évalué à 6.GCC devrait utiliser la méthode la plus efficace en temps et en taille, non?
Tu peux commencer par regarder du coté de l'option -nostdlib
À toi alors d'ajuster ton code C comme il faut pour que ça fonctionne toujours. Le fonctionnement standard du C, c'est que la libc est disponible.
strip permet la suppression de code mort
Non, ce n'est pas du "code mort". À moins que tu n'appelles "code" la section .comments ?
Le reste, ce sont des informations, parfois nécessaire à l'OS :
- Quel est l'interpréteur ? (/lib/ld-linux.so.2 ou /lib64/ld-linux-x86-64.so.2)
- Quelles sont les bibliothèques nécessaires pour faire tourner le programme ? (la libc)
- Quelles versions nécessaires desdites bibliothèques ? (parfois, il y a un changement d'ABI entre les versions)
- Quels sont les symboles qui sont visibles de l'extérieur ? (le main, pour qu'il puisse être appelé)
- Quels sont les symboles externes qui sont visibles dans le programme ? (stdin, stdout, optarg, ... par défaut, libc oblige)
- Comment doit être configurée la pile ? (non-exécutable)
un facteur 10
Dans ce cas extrême où le programme ne fait rien. Je passe, la comparaison est spécieuse.
... [DSP Motorola] ... [6ko pour un programme en C qui ne fait rien] ...
Ton programme C fait en réalité beaucoup de choses pour que l'OS puisse l'utiliser de manière optimale (ou même parfois l'utiliser tout court). Le programme du DSP a beaucoup moins de contraintes à ce niveau.-
[^]Re: Readelf, objdump
Posté par Gilles G. () le 27/01/2008 à 11:39. (lien). Évalué à 1.Merci pour ta réponse, je comprends mieux à présent. Effectivement, en ouvrant les fichiers binaires avec un éditeur hexadécimal, je me suis rendu compte qu'il y a pas mal de chaînes de caractères qui contiennent des noms "manglés".
Par ailleurs le lien donné par Gniarf m'a fait découvrir l'option -nostdlib de GCC, et ça m'a aussi permis de découvrir que:
* GCC fait *toujours* le lien avec la libc.
* la fonction main est une fonction fournie par la libc, pas par le langage.
Merci pour ces explications!
-
-
relire...
A mon avis, qui n'engage evidemment que moi...
PS: Au boulot j'utilise des DSP motorola qui ont 16Ko de mémoire programme, et on arrive quand même à faire pas mal de choses (en assembleur), donc je trouve que prendre 6ko pour un programme en C qui ne fait rien c'est abusé.
relis bien les 2 posts precedents et le lien fournit plus haut.
entre ecrire un programme en assembleur sans commentaire et sans lien/description
et ecrire un programme en C qui sort un format executable.
il y a des differences.
d'ailleurs le lien donné par le premier post explique bien cela.
meme ton code assembleur, une fois "compilé" prend plus que place que le code en lui meme
alors que dans le DSP tu lui envoie uniquement le code assembleur et pas le code compilé...
Apprendre par les autres, c'est bien.
Apprendre par soi-meme (RTFM, man, et notre ami google) c'est mieux
-
[^]Re: relire...
C'est une blague ?
Non, sérieux, cette discussion, c'est une blague ? Je voyais déjà exactement ce même type de discussion il y a 14 ans. Et quand je dis exactement, c'est du mot pour mot, et un étonnement, une naïveté identiques.
Faut avancer les enfants, si les linkages par défaut de GCC ne vous conviennent pas, vous faites les votre, qui feront moins de choses, mais qui seront plus petit.
-
[^]Re: C'est une blague ?
Posté par Gilles G. () le 27/01/2008 à 11:12. (lien). Évalué à 9.Je voyais déjà exactement ce même type de discussion il y a 14 ans. Et quand je dis exactement, c'est du mot pour mot, et un étonnement, une naïveté identiques.
Heureux de l'apprendre.
Il y a 14 ans j'avais 12 ans, j'espère que tu ne m'en veux pas de ne pas avoir suivi les discussions de l'époque.-
[^]Re: C'est une blague ?
-
Revenir en haut de page || Retourner aux forums || Retourner au forum Programmation.c



Cette discussion est archivée, il n'est plus possible de laisser des commentaires.
Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.