如何检索用于编译给定 ELF 可执行文件的 GCC 版本?

我想检索用于编译给定可执行文件的 GCC 版本。我试过 readelf,但没有得到信息。有什么想法吗?

61592 次浏览

此信息不存储在已编译的对象(c)中。

事实上,对于 C 代码,你完全不走运。但是,对于 C + + 代码,您可以从符号版本中找到一些信息。来自 C + + 运行时库的一些函数是版本特定的,并且在对象文件中标记为版本特定的。试试这个:

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

但是,它不会显示所使用的 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)

它通常存储在注释部分

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

报税表 海湾合作委员会: (GNU) X.X.X

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

不返回任何输出

通过以下方法减小大小并不罕见: 删除.comments (以及.note)部分

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

注意: busybox 字符串在默认情况下指定-a 选项,该选项对于. comments 部分是必需的

编辑: 与 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
#

注意,没有 any-g (调试)标志,而-s 标志去除了不需要的符号。GCC 信息仍然可用,除非。注释部分被删除。如果需要保持这些信息的完整性,可能需要检查 makefile (或适用的构建脚本) ,以验证-fno-id 不在 $CFLAGS 中,并且 $STRIP 命令缺少-R。评论。- fno-id 防止 gcc 从注释部分开始生成这些符号。

还有另外两种方法(也许更简单一些) ,我刚刚在这里读到过: 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..
...

您可以使用 Elfinfo实用程序。这还支持检测 Go 和 FPC 的编译器版本,以及 GCC。