web-dev-qa-db-ja.com

特定のELF実行可能ファイルのコンパイルに使用されるGCCバージョンを取得する方法は?

特定の実行可能ファイルのコンパイルに使用されたGCCバージョンを取得したいと思います。 readelfを試しましたが、情報を取得できませんでした。何かご意見は?

65
Ilyes Gouta

通常、コメントセクションに保存されます

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情報は引き続き利用可能です。この情報をそのまま保持する必要がある場合は、メイクファイル(または適用可能なビルドスクリプト)をチェックして、-fno-identが$ CFLAGSになく、$ STRIPコマンドに-R .commentがないことを確認する必要があります。 -fno-identは、gccがコメントセクションでこれらのシンボルを最初から生成しないようにします。

72
technosaurus

他の人が言ったことを完了するために:オブジェクト(または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)の説明を参照してください。

20
Berendra Tusla

私がここで読んだことのあるさらにもう2つの方法(少し簡単かもしれません): 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..
 ...
8
marcin

この情報は、コンパイルされたオブジェクト(c)には保存されません。

実際、Cコードではまったく運がありません。ただし、C++コードの場合、シンボルバージョンからいくつかの情報を見つけることができます。 C++ランタイムライブラリの一部の関数はバージョン固有であり、オブジェクトファイルでそのようにマークされています。これを試して:

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

ただし、使用されているGCCのバージョンは表示されません。表示されるのは、コンパイラに提供されるランタイムのシンボルのバージョンです。通常、ランタイムはコンパイラーの出荷時のものであり、そのバージョンはnot not less上記のコマンドで表示されるものよりも大きいです。

2
P Shved

この情報は、コンパイルされたオブジェクトには保存されません。

0
kennytm

elfinfo ユーティリティを使用できます。これは、GCCに加えて、GoおよびFPCのコンパイラバージョンの検出もサポートします。

0
Alexander