je 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!
# 460 octets pour ça ?!?
Posté par Gniarf . Évalué à 5.
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(...)
[^] # Re: 460 octets pour ça ?!?
Posté par NeoX . Évalué à 1.
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.
# Readelf, objdump
Posté par Amand Tihon (site web personnel) . Évalué à 4.
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. . Évalué à 1.
C'est justement ça le problème: GCC devrait utiliser la méthode la plus efficace en temps et en taille, non?
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 (site web personnel) . Évalué à 6.
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.
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)
Dans ce cas extrême où le programme ne fait rien. Je passe, la comparaison est spécieuse.
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. . Évalué à 1.
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...
Posté par NeoX . Évalué à 1.
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é...
[^] # Re: relire...
Posté par Gilles G. . Évalué à 1.
Non, le DSP tu lui envoies le code assemblé qui peut prendre effectivement plus de place que le code lui-même.
# C'est une blague ?
Posté par nogunner . Évalué à 4.
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. . Évalué à 9.
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 ?
Posté par Barnabé . Évalué à 2.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.