web-dev-qa-db-fra.com

Comment récupérer la version de GCC utilisée pour compiler un exécutable ELF donné?

J'aimerais récupérer la version de GCC utilisée pour compiler un exécutable donné. J'ai essayé readelf mais je n'ai pas eu l'information. Des pensées?

63
Ilyes Gouta

Il est normalement stocké dans la section commentaire

strings -a <binary/library> |grep "GCC: ("

retourne GCC: (GNU) X.X.X

strip -R .comment <binary>
strings -a <binary/library> |grep "GCC: ("

ne renvoie aucune sortie

Il n'est pas rare de supprimer la section .comment (ainsi que .note) pour réduire la taille via

strip --strip-all -R .note -R .comment <binary>
strip --strip-unneeded -R .note -R .comment <library>

Remarque: les chaînes busybox spécifient l'option -a par défaut, nécessaire pour la section .comment.

Edit: Contrairement à la réponse de Berendra Tusla, il n’a pas besoin d’être compilé avec un indicateur de débogage pour que cette méthode fonctionne.

Exemple binaire:

# echo "int main(void){}">a.c
# gcc -o a a.c -s
# strings -a a |grep GCC
GCC: (GNU) 4.3.4
# strip -R .comment a
# strings -a a |grep GCC
#

Exemple d'objet:

# gcc -c a.c -s
# strings -a a.o |grep GCC
GCC: (GNU) 4.3.4
# strip -R .comment a.o
# strings -a a |grep GCC
#

Notez l'absence d'indicateurs -g (débogage) et la présence de l'indicateur -s qui supprime les symboles inutiles. Les informations GCC sont toujours disponibles, sauf si la section .comment est supprimée. Si vous devez conserver ces informations intactes, vous devrez peut-être vérifier votre makefile (ou le script de construction applicable) pour vérifier que -fno-ident ne figure pas dans votre $ CFLAGS et que la commande $ STRIP manque de -R .comment. -fno-ident empêche gcc de générer ces symboles dans la section commentaire.

69
technosaurus

Pour compléter ce que d'autres ont dit: il n'est pas stocké dans le fichier object (ou exe), sauf si vous compilez avec les informations de débogage ! (option -g). Si vous compilez avec les informations de débogage, vous pouvez les récupérer avec readelf:

$ cat a.c
int main(void){ return 0; }
$ gcc a.c
$ readelf -wi a.out
$ gcc a.c -g       
$ readelf -wi a.out
Contents of the .debug_info section:

  Compilation Unit @ offset 0x0:
   Length:        0x42 (32-bit)
   Version:       2
   Abbrev Offset: 0
   Pointer Size:  4
 <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
    < c>   DW_AT_producer    : (indirect string, offset: 0x0): GNU C 4.4.3 20100108 (prerelease)    
    <10>   DW_AT_language    : 1    (ANSI C)
    <11>   DW_AT_name        : a.c  
    <15>   DW_AT_comp_dir    : (indirect string, offset: 0x22): /tmp    
    <19>   DW_AT_low_pc      : 0x8048394    
    <1d>   DW_AT_high_pc     : 0x804839e    
    <21>   DW_AT_stmt_list   : 0x0  
 <1><25>: Abbrev Number: 2 (DW_TAG_subprogram)
    <26>   DW_AT_external    : 1    
    <27>   DW_AT_name        : (indirect string, offset: 0x27): main    
    <2b>   DW_AT_decl_file   : 1    
    <2c>   DW_AT_decl_line   : 1    
    <2d>   DW_AT_prototyped  : 1    
    <2e>   DW_AT_type        : <0x3e>   
    <32>   DW_AT_low_pc      : 0x8048394    
    <36>   DW_AT_high_pc     : 0x804839e    
    <3a>   DW_AT_frame_base  : 0x0  (location list)
 <1><3e>: Abbrev Number: 3 (DW_TAG_base_type)
    <3f>   DW_AT_byte_size   : 4    
    <40>   DW_AT_encoding    : 5    (signed)
    <41>   DW_AT_name        : int  

Voyez comment il est écrit GNU C 4.4.3 20100108 (prerelease).

18
Berendra Tusla

Encore deux autres façons (peut-être un peu plus simples) que je viens de lire ici: https://unix.stackexchange.com/questions/719/can-we-get-compiler-information-from-an-elf -binary

$ readelf -p .comment /usr/lib64/flash-plugin/libflashplayer.so

String dump of section '.comment':
  [     1]  GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)
  [    2e]  GCC: (GNU) 4.3.2
...

et

$ objdump -s --section .comment /usr/lib64/flash-plugin/libflashplayer.so

/usr/lib64/flash-plugin/libflashplayer.so:     file format elf64-x86-64

Contents of section .comment:
 0000 00474343 3a202847 4e552920 342e332e  .GCC: (GNU) 4.3.
 0010 32203230 30383131 30352028 52656420  2 20081105 (Red 
 0020 48617420 342e332e 322d3729 00004743  Hat 4.3.2-7)..GC
 0030 433a2028 474e5529 20342e33 2e320000  C: (GNU) 4.3.2..
 ...
8
marcin

Cette information n'est pas stockée dans l'objet compilé (c).

En fait, pour le code C, vous n’êtes absolument pas chanceux. Cependant, pour le code C++, vous pouvez trouver des informations à partir des versions de symboles. Certaines fonctions des bibliothèques d'exécution C++ sont spécifiques à la version et sont marquées comme telles dans les fichiers objet. Essaye ça:

readelf -Wa file.exe | grep 'GCC[[:alnum:]_.]*' --only-match | sort | uniq | tail -n 1

Il ne vous montrera cependant pas la version de GCC utilisée. Ce qu'il montre est la version des symboles du moteur d'exécution fournie au compilateur. Généralement, l'exécution est celle d'un envoi de compilateur et sa version est pas moins que celle indiquée avec la commande ci-dessus.

2
P Shved

Cette information n'est pas stockée dans l'objet compilé.

0
kennytm

Vous pouvez utiliser l'utilitaire elfinfo . Ceci prend également en charge la détection des versions de compilateur de Go et FPC, en plus de GCC.

0
Alexander