プロフィール

kosaki

Author:kosaki
連絡先はコチラ

ブログ検索
最近の記事
最近のコメント
最近のトラックバック
リンク
カテゴリー
月別アーカイブ
RSSフィード
FC2ブログランキング

a.out からコンパイラバージョンを取得する方法 このエントリーをはてなブックマークに追加

忘れないうちにメモ
Linuxで普通に実行ファイルつくると.commentセクションとデバッグインフォメーションの
二箇所にコンパイラのバージョンが入ってる。これはobjdumpやreadelfで観測できる。

なぜこんなテクニックを知る必要があるかというとバグ報告で嘘のコンパイラバージョンを
報告してくる輩はけしてレアではないからである

1つめ。.comment セクションを objdumpで表示

% objdump -s -j .comment a.out

a.out: file format elf64-x86-64

Contents of section .comment:
0000 4743433a 2028474e 55292034 2e342e36 GCC: (GNU) 4.4.6
0010 20323031 32303330 35202852 65642048 20120305 (Red H
0020 61742034 2e342e36 2d342900 4743433a at 4.4.6-4).GCC:
0030 2028474e 55292034 2e342e37 20323031 (GNU) 4.4.7 201
0040 32303331 33202852 65642048 61742034 20313 (Red Hat 4
0050 2e342e37 2d332900 .4.7-3).


これはCentOS 6.4 でコンパイルした、ただの Hello World プログラム。
なんでバージョンが複数出てくるかというと、一般に実行ファイルには
コンパイル時にいくつかのcrtファイルが静的リンクされるのだが、
それらは、OSのマイナー版アップ時にgccバージョンが上がった時に、
リコンパイルされないことが多いので、a.outとずれちゃうんだね。

一般に一番新しいバージョンが a.out のコンパイルに使われたもので
それ以外はリンクされてるcrtをコンパイルしたときのもの。


つぎ、readelfでdebug info読んだもの。こっちのほうがストレートに
a.outの情報だけが出てきて便利。ただし、デバッグ情報必要なので
使えない時はつかえない。

% readelf -wi a.out | grep -i producer
< c> DW_AT_producer : (indirect string, offset: 0x0): GNU C 4.4.7 20120313 (Red Hat 4.4.7-3)




ところで、gccがどうやって .commentセクションに書き込んでいるか調べたのだが、これが結構面白い
gcc -s hello.c すると、以下の様なアセンブリソースが現れる。



.file "hello.c"
.section .rodata
.LC0:
.string "hello"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %edi
call puts
movl $0, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.7 20120313 (Red Hat 4.4.7-3)"
.section .note.GNU-stack,"",@progbits


ここで、 .identという pseudo assembler directiveを使っていることがわかった。
マニュアルを見ると

http://www.sourceware.org/binutils/docs-2.12/as.info/Ident.html#Ident

.ident

This directive is used by some assemblers to place tags in object files. as simply accepts the directive for source-file compatibility with such assemblers, but does not actually emit anything for it.



なんて書いてあるが、なに、うそっぱちである。信じてはいけない。
ためしに、ここに Gachapin here!! とか書くと


% objdump -s -j .comment a.out        

a.out: file format elf64-x86-64

Contents of section .comment:
0000 4743433a 2028474e 55292034 2e342e36 GCC: (GNU) 4.4.6
0010 20323031 32303330 35202852 65642048 20120305 (Red H
0020 61742034 2e342e36 2d342900 4743433a at 4.4.6-4).GCC:
0030 2028474e 55292034 2e342e37 20323031 (GNU) 4.4.7 201
0040 32303331 33202852 65642048 61742034 20313 (Red Hat 4
0050 2e342e37 2d332900 47616368 6170696e .4.7-3).Gachapin
0060 20686572 65212100 here!!.


のように、.commentセクションに文字列が増えたことが確認できる。
(gcc 4.4.7 の文字列が消えないのは 4.4.7でコンパイルされてるcrtも含んでいるため)

なお、リンクされてる crt一覧をとりたいときは以下のようにする

gcc hello.c -Wl,-t
/opt/rh/devtoolset-2/root/usr/libexec/gcc/x86_64-redhat-linux/4.8.0/ld:
mode elf_x86_64
/usr/lib/../lib64/crt1.o
/usr/lib/../lib64/crti.o
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.0/crtbegin.o
/tmp/ccfPagMG.o
/lib64/libgcc_s.so.1
/lib64/libc.so.6
(/usr/lib64/libc_nonshared.a)elf-init.oS
/lib64/ld-linux-x86-64.so.2
/lib64/libgcc_s.so.1
/opt/rh/devtoolset-2/root/usr/lib/gcc/x86_64-redhat-linux/4.8.0/crtend.o
/usr/lib/../lib64/crtn.o


備忘録なので特に結論はない


関連記事


linux | 【2013-11-26(Tue) 23:31:22】 | Trackback:(0) | Comments:(3)
コメント

ちょうど今日ヤボ用 .ident って実際なにするんだろーと思ってたんで大変タイムリーでした。うそっぱち、ってのは "does not actually emit anything for it" がということでしょうか。たしかに大変微妙な記述な気がしますけど、前文と矛盾しないように解釈すると、「現在指定されてるセクションには何も書かれないよ」って意味としか取れないような気がするので、最悪ではないような気もします。
2013-11-27 水 10:41:56 | URL | shinh #sqCyeZqA [ 編集]

あれ、そういう意味なのか。てっきり、どっかヨソのアセンブラは意味のあるtagをemitするけどgasは構文としては受け付けるけどなんもしねーよ。って主張してるのかと思ってました。
英語わからなくてすいません。
2013-11-27 水 17:06:43 | URL | kosaki #- [ 編集]

いややっぱりその文章は元の kosaki さんの解釈で正しいような気しかしませんね…こちらこそすいません。

最近の binutils だとずいぶん正しい記述になってるみたいです。

sourceware.org/binutils/docs-2.23.1/as/Ident.html#Ident
2013-11-28 木 12:25:23 | URL | shinh #sqCyeZqA [ 編集]
コメントの投稿(メールアドレスは公開されますのでMail欄は使わないことをオススメします)

  1. 無料アクセス解析