I'd like to retrieve the GCC version used to compile a given executable. I tried readelf
but didn't get the information. Any thoughts?
5 回答
一般存放在评论区
strings -a <binary/library> |grep "GCC: ("
返回 GCC: (GNU) XXX
strip -R .comment <binary>
strings -a <binary/library> |grep "GCC: ("
不返回任何输出
剥离 .comment(以及 .note)部分以减小大小的情况并不少见
strip --strip-all -R .note -R .comment <binary>
strip --strip-unneeded -R .note -R .comment <library>
注意:busybox 字符串默认指定 -a 选项,这是 .comment 部分所需要的
编辑:与 Berendra Tusla 的回答相反,它不需要使用任何调试标志进行编译,此方法即可工作。
二进制示例:
# 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
#
对象示例:
# 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
#
请注意没有任何 -g (调试)标志和 -s 标志的存在,它去除了不需要的符号。除非删除 .comment 部分,否则 GCC 信息仍然可用。如果您需要保持此信息完整,您可能需要检查您的 makefile(或适用的构建脚本)以验证 -fno-ident 不在您的 $CFLAGS 中并且 $STRIP 命令缺少 -R .comment。-fno-ident 阻止 gcc 在注释部分开始生成这些符号。
完成其他人所说的:它不存储在对象(或exe)文件中,除非您使用调试信息进行编译!(选项-g
)。如果您使用调试信息进行编译,则可以使用以下命令将其取回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
看看它怎么说GNU C 4.4.3 20100108 (prerelease)
。
我刚刚在这里读到的另外两种方法(可能更简单): 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
...
和
$ 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..
...
此信息不存储在编译对象 (c) 中。
实际上,对于 C 代码,您完全不走运。但是,对于 C++ 代码,您可能会从符号版本中找到一些信息。C++ 运行时库中的一些函数是特定于版本的,并且在目标文件中被标记为这样。尝试这个:
readelf -Wa file.exe | grep 'GCC[[:alnum:]_.]*' --only-match | sort | uniq | tail -n 1
但是,它不会向您显示使用的 GCC 版本。它显示的是运行时提供给编译器的符号版本。通常运行时是一个编译器发货的,它的版本不低于上面命令显示的版本。
您可以使用elfinfo实用程序。除了 GCC,它还支持检测 Go 和 FPC 的编译器版本。