【问题标题】:How to retrieve the GCC version used to compile a given ELF executable?如何检索用于编译给定 ELF 可执行文件的 GCC 版本?
【发布时间】:2011-01-24 03:05:12
【问题描述】:

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

【问题讨论】:

    标签: gcc elf


    【解决方案1】:

    您可以使用elfinfo 实用程序。除了 GCC,它还支持检测 Go 和 FPC 的编译器版本。

    【讨论】:

      【解决方案2】:

      一般存放在评论区

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

      返回 GCC:(GNU)X.X.X

      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 在注释部分生成这些符号。

      【讨论】:

      • “通常”是什么意思?使用默认选项完成编译时,我的编译器/版本不存储此信息。
      • 我使用的是在 OS X 上编译的 GCC 4.6.2,但没有应用任何系统特定的补丁。这是一个普通的 GCC。
      • 什么都没有。如果我在源代码中包含文字字符串,strings 会正确找到这些字符串。
      • 您需要将-a 选项指定为strings,因为默认情况下该实用程序不会查看.comment 部分。
      • objdump -s --section .comment foo.o 将评论部分转储到屏幕上
      【解决方案3】:

      我刚刚在这里读到的另外两种方法(可能更简单):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..
       ...
      

      【讨论】:

      • 稍微扩展一下:-p 选项在我的旧版 readelf(来自 binutils 2.14)中不存在,所以我必须找到 .comment 部分的索引,然后像这样用十六进制转储它:readelf --hex-dump=$(readelf -S &lt;so_file&gt; | grep .comment | awk '{ print $1 }' | tr -d '[]') &lt;so_file&gt;
      【解决方案4】:

      补充其他人所说的:它不存储在对象(或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)

      【讨论】:

        【解决方案5】:

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

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

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

        但是,它不会显示您使用的 GCC 版本。它显示的是运行时提供给编译器的符号版本。通常运行时是编译器发货的,它的版本不低于上面命令显示的版本。

        【讨论】:

        • 好的,谢谢大家!无法弄清楚为什么如此重要的信息没有进入 ELF 标头。我的目标实际上是一个嵌入式 Linux 内核。
        猜你喜欢
        • 2012-01-26
        • 2012-09-02
        • 2020-10-06
        • 1970-01-01
        • 2011-04-17
        • 2012-03-31
        • 1970-01-01
        • 2015-11-23
        相关资源
        最近更新 更多