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?
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?
Antworten:
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.
strings
.
-a
Option angeben strings
, da das Dienstprogramm .comment
standardmäßig nicht in den Abschnitt schaut .
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)
.
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..
...
-p
Option 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>
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.
Sie können das Dienstprogramm elfinfo verwenden . Dies unterstützt neben GCC auch die Erkennung der Compilerversionen von Go und FPC.