Comstackr et exécuter le programme sans main () dans C

J’essaie de comstackr et d’exécuter le programme suivant sans fonction main() dans C J’ai compilé mon programme en utilisant la commande suivante.

 gcc -nostartfiles nomain.c 

Et le compilateur donne un avertissement

 /usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400340 

Ok, pas de problème. Ensuite, j’ai exécuté le fichier exécutable (a.out), les deux instructions printf imprimées avec succès, puis elles ont généré une erreur de segmentation .

Donc, ma question est la suivante: pourquoi la segmentation des erreurs après une exécution réussie des instructions d’impression?

mon code:

 #include  void nomain() { printf("Hello World...\n"); printf("Successfully run without main...\n"); } 

sortie:

 Hello World... Successfully run without main... Segmentation fault (core dumped) 

Remarque:

Ici, l’ -nostartfiles gcc empêche le compilateur d’utiliser des fichiers de démarrage standard lors de la liaison

Regardons l’ assemblage généré de votre programme:

 .LC0: .ssortingng "Hello World..." .LC1: .ssortingng "Successfully run without main..." nomain: push rbp mov rbp, rsp mov edi, OFFSET FLAT:.LC0 call puts mov edi, OFFSET FLAT:.LC1 call puts nop pop rbp ret 

Notez la déclaration ret . Le point d’entrée de votre programme est déterminé à être nomain , tout va bien avec cela. Mais une fois que la fonction revient, elle tente de sauter dans une adresse de la stack d’appels … qui n’est pas renseignée. C’est un access illégal et une erreur de segmentation suit.

Une solution rapide serait d’appeler exit() à la fin de votre programme (et en supposant que C11 nous pourrions aussi bien marquer la fonction comme _Noreturn ):

 #include  #include  _Noreturn void nomain(void) { printf("Hello World...\n"); printf("Successfully run without main...\n"); exit(0); } 

En fait, maintenant, votre fonction se comporte à peu près comme une fonction main normale, car après le retour de main , la fonction de exit est appelée avec main valeur de retour main .

Dans C, lorsque des fonctions / sous-routines sont appelées, la stack est remplie comme (dans l’ordre):

  1. Les arguments,
  2. Adresse de retour,
  3. Variables locales, -> haut de la stack

main () étant le sharepoint départ, ELF structure le programme de manière à ce que les instructions soient envoyées en premier.

Maintenant, le programme est en quelque sorte tronqué sans return-address OR __end__ et en fait, il suppose que tout ce qui existe sur la stack à cet emplacement ( __end__ ) est l’adresse de retour, mais malheureusement elle ne fonctionne pas.