Wie kann ich die GCC-Version abrufen, die zum Kompilieren einer bestimmten ausführbaren ELF-Datei verwendet wird?

74

Ich möchte die GCC-Version abrufen, die zum Kompilieren einer bestimmten ausführbaren Datei verwendet wird. Ich habe es versucht readelf, aber keine Informationen erhalten. Irgendwelche Gedanken?

Ilyes Gouta
quelle

Antworten:

82

Es wird normalerweise im Kommentarbereich gespeichert

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

gibt GCC zurück: (GNU) XXX

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

gibt keine Ausgabe zurück

Es ist nicht ungewöhnlich, den Abschnitt .comment (sowie .note) zu entfernen, um die Größe über zu reduzieren

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

Hinweis: Busybox-Zeichenfolgen geben standardmäßig die Option -a an, die für den Abschnitt .comment benötigt wird

Bearbeiten: Im Gegensatz zu Berendra Tuslas Antwort muss es nicht mit Debugging-Flags kompiliert werden, damit diese Methode funktioniert.

Binäres Beispiel:

# 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
#

Objektbeispiel:

# 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
#

Beachten Sie das Fehlen von -g-Flags (Debugging) und das Vorhandensein des Flags -s, mit dem nicht benötigte Symbole entfernt werden. Die GCC-Informationen sind weiterhin verfügbar, sofern der Abschnitt .comment nicht entfernt wird. Wenn Sie diese Informationen intakt halten müssen, müssen Sie möglicherweise Ihr Makefile (oder das entsprechende Build-Skript) überprüfen, um sicherzustellen, dass -fno-ident nicht in $ CFLAGS enthalten ist und dem Befehl $ STRIP -R .comment fehlt. -fno-ident verhindert, dass gcc diese Symbole zunächst im Kommentarbereich generiert.

Technosaurus
quelle
1
Was meinst du mit "normal"? Mein Compiler / meine Version speichert diese Informationen nicht, wenn die Kompilierung mit den Standardoptionen durchgeführt wird.
Konrad Rudolph
Ich verwende GCC 4.6.2, das unter OS X kompiliert wurde, jedoch ohne systemspezifische Patches. Es ist ein Vanille-GCC.
Konrad Rudolph
Gar nichts. Wenn ich Literalzeichenfolgen in den Quellcode einbinde, werden diese von korrekt gefunden strings.
Konrad Rudolph
Sie müssten die -aOption angeben strings, da das Dienstprogramm .commentstandardmäßig nicht in den Abschnitt schaut .
jkoshy
2
objdump -s --section .comment foo.o entleert den Kommentarbereich auf dem Bildschirm
MarcH
20

Um das zu vervollständigen, was andere gesagt haben: Es wird nicht in der Objekt- (oder Exe-) Datei gespeichert, es sei denn, Sie kompilieren mit Debugging-Informationen ! (Option -g). Wenn Sie mit Debug-Informationen kompilieren, können Sie diese zurückerhalten mit 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  

Sehen Sie, wie es heißt GNU C 4.4.3 20100108 (prerelease).


quelle
9

Noch zwei weitere Möglichkeiten (vielleicht etwas einfacher), über die ich gerade hier gelesen habe: /unix/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
...

und

$ 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..
 ...
marcin
quelle
Erweitern Sie dies ein wenig: Die -pOption ist in meiner alten Kopie von readelf(von binutils 2.14) nicht vorhanden , daher musste ich den Index des .comment-Abschnitts finden und ihn dann wie readelf --hex-dump=$(readelf -S <so_file> | grep .comment | awk '{ print $1 }' | tr -d '[]') <so_file>
folgt hexadezimal ausgeben
2

Diese Informationen werden nicht im kompilierten Objekt (c) gespeichert.

Für C-Code haben Sie eigentlich kein Glück. Für C ++ - Code finden Sie jedoch möglicherweise einige Informationen aus Symbolversionen. Einige Funktionen aus C ++ - Laufzeitbibliotheken sind versionierungsspezifisch und in Objektdateien als solche gekennzeichnet. Versuche dies:

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

Es wird jedoch nicht die verwendete Version von GCC angezeigt. Was es zeigt, ist die Version der Symbole in der Laufzeit, die dem Compiler zur Verfügung gestellt werden. Normalerweise ist die Laufzeit die einer Compilersendung, und ihre Version ist nicht kleiner als die mit dem obigen Befehl gezeigte.

P Shved
quelle
Okay, danke Jungs! Ich kann nicht herausfinden, warum so wichtige Informationen nicht in den ELF-Header gelangen. Mein Ziel ist eigentlich ein eingebetteter Linux-Kernel.
Ilyes Gouta
0

Sie können das Dienstprogramm elfinfo verwenden . Dies unterstützt neben GCC auch die Erkennung der Compilerversionen von Go und FPC.

Alexander
quelle