27++'s Report

東京大学で行われた「大規模ソフトウェアを手探る」実験においてgccコンパイラーに機能の追加を行った。その際の奮闘を描いた日記(風レポート)。


このブログには東京大学電子情報・電気電子工学科にて行われた「外規模ソフトウェアを手探る」実験において使用の変更、追加を行ったgccについて書かれています。実験日に沿った日記風レポートとなっていますが、実際の進捗とブログの進捗には多少の差があることをここに断らせていただきます。
行ったことは"-o"オプションなしでhoge.cをコンパイルしたときhoge.outとなる変更、及び文末の";"の抜けを自動で補填する変更である。

まとめ(変更箇所の紹介記事リンクとgccの仕組み)

手探るgccのソースコードのダウンロード方法(初日)



a.outってなんやねん(4)

gcc のオプションに"-v" なるものが存在するらしい。このコマンドはgccが実行したすべてのコマンドを見ることができるという。
$ ./gcc -v test.c

/home/denjo/gcc_install/libexec/gcc/x86_64-pc-linux-gnu/6.2.0/collect2 -plugin /home/denjo/gcc_install/libexec/gcc/x86_64-pc-linux-gnu/6.2.0/liblto_plugin.so -plugin-opt=/home/denjo/gcc_install/libexec/gcc/x86_64-pc-linux-gnu/6.2.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccLtFbvP.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /home/denjo/gcc_install/lib/gcc/x86_64-pc-linux-gnu/6.2.0/crtbegin.o -L/home/denjo/gcc_install/lib/gcc/x86_64-pc-linux-gnu/6.2.0 -L/home/denjo/gcc_install/lib/gcc/x86_64-pc-linux-gnu/6.2.0/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/home/denjo/gcc_install/lib/gcc/x86_64-pc-linux-gnu/6.2.0/../../.. /tmp/cc2jofoY.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /home/denjo/gcc_install/lib/gcc/x86_64-pc-linux-gnu/6.2.0/crtend.o /usr/lib/x86_64-linux-gnu/crtn.o COLLECT_GCC_OPTIONS='-v' '-mtune=generic' '-march=x86-64'

このコマンドによってgccが裏で何をやっているのかがわかってきた。赤文字で示しているように、collect2もgccから何かを渡されて動いていることもわかった。
調べてみると、collect2はリンカの役割を担っているが…実際にリンカをしているのは /usr/bin にあるldなる実行ファイルであった…

さて、本当に手探らなくてはいけないのはgccではなく外部のファイルであることがわかってしまった。ここで完全に手詰まりか…と思っていた僕達に一筋の光が!

続きを読む

a.outってなんやねん(3)

二日目に結局どこで"a.out"を決定していたのかわからなかった僕らは、直接"a.out"を出力ないし渡している関数があるのではないかと思い、grepコマンドに頼ることにした。

フォルダーを"/home/denjo/gcc-6.2.0/gcc"に指定して、ターミナルに
$ grep -r -I "a/.out"
と入力した結果、
collect2: output_file = "a.out"
なる一文を発見。そこでcollect2を覗いてみると…

f:id:bigsoftExp:20161129152855p:plain

あった!この"a.out"がデフォルトの名前を決めている!そうに違いない!

早速、この文を
output_file = "b.out"
い変更!これで標準の出力は"b.out"になってくれるはず!

〜Make中(wktk)〜

コンパイルしてみると…
$ ./gcc test.c
結果…

続きを読む

a.outってなんやねん(2)

さて、早速デバッグに取り掛かろう!
GNU Debuggerを用いてデバッグを行った。

デバッグを行う前に、gccと同じディレクトリ内(/home/denjo/gcc_install/bin)にc言語で書かれたプログラム、test.cを用意した。

test.c
#include <stdio.h>
int main(){
  printf("Hello World");
}

gdbを起動し、ブレイクポイントをmainに設定。test.cを引数にデバッグを開始。
最初に僕たちが取った手法は"フォルダ見比べ作戦"である。その手法とは、以下の画像のようにa.outが生成されるディレクトリ /home/denjo/gcc_install/bin を監視しながらデバッグを(コマンドnで)行い、生成された瞬間の前の関数を手探る、という手法である。

f:id:bigsoftExp:20161128171144p:plain

f:id:bigsoftExp:20161128171153p:plain

このようになった時にブレイクポイントをmaybe_run_linkerにおいて再びデバッグし、その関数内にコマンドsで入っていく

このようにしていくと、最終的に関数~~~でa.outを出力することがわかる…はずだったのだが、突然生成しており結局どこで生成しているのか特定することはできなかった。(実験二日目の不慣れや知識不足の点も多かったと思われるのでわかった人いたらこっそりコメントで教えてください;;)

a.outってなんやねん(1)

gccコンパイラーを用いたことがある人なら誰もが一度は

gcc ファイル名.c

コンパイルを行い、a.out(Cygwin環境ならばa.exe)という実行可能ファイルを生成したことがあるだろう。また、

gcc -o hoge hoge.c

コンパイルしてhoge(hoge.exe)という実行可能ファイルを作ったこともあるのではないだろうか?

しかし、この仕様不便に思わないだろうか?僕はオプションなしで実行した時にすべてがa.outになることに不便さを覚え、憤りさえしたことを今でも鮮明に思い出す。プログラミング初心者だった(今でも十分初心者なのだが)僕にとって、さっきまで自分が作っていたものが上書きされてもう一回コンパイルしなおしたりする羽目になることがしばしばでその都度「-oオプションなしで"ファイル名"で出力してくれればいいのに」と常々思っていた。

そのために初日である今日(10/25)にやったことをメモしていきたいと思う。

続きを読む