對岸的 Eric Fisher 做了一個很棒的工具 [
gcc-vcg-plugin ],本質上是個 GCC Plugin,可輸出 VCG 格式的圖例,作為分析 GCC 內部架構使用。筆者在 Ubuntu Maverick (10.10 開發中版本) 測試過,配合 gcc-4.5 作驗證,先寫一個測試小程式: (test.c)
原本 cc1 處理的方式為: (路徑依據 Ubuntu Maverick)
即顯示 test.c 的 top-level function。
void second() { } void top() { second(); }這的確沒什麼特別之處,只是想驗證 CFG (Call Flow Graph) 的樣貌。筆者安裝 [ gcc-vcg-plugin ] 時,指定 --prefix=/tmp/gcc-vcg-plugin 並預先安裝好 [ vcgviewer],注意,依據 README 應安裝 Gtk+ 2.x 的版本。GCC 一開始是 GNU C Compiler,但後來陸續追加若干 Language front-end,發展為完整的 compiler driver,那我們就來看實際處理語意分析、生成組合語言的 'cc1' (在 'cc1' ˊ之前的 'cpp` 負責作 preprocessor,處理巨集替換)。
原本 cc1 處理的方式為: (路徑依據 Ubuntu Maverick)
$ /usr/lib/gcc/i486-linux-gnu/4.5/cc1 test.c second top Analyzing compilation unit Performing interprocedural optimizations <visibility> <*free_lang_data> <early_local_cleanups> <whole-program> <inline>Assembling functions: second top Execution times (seconds) TOTAL : 0.00 0.01 0.02 599 kB Extra diagnostic checks enabled; compiler may run slowly. Configure with --enable-checking=release to disable checks.GCC 4.4 以來引入 Plugin 的機制,就可在不修改編譯器的情況下,覆蓋編譯器的行為,而 [ gcc-vcg-plugin ] 就提供分析 GCC 內部結構的機制,於是我們配合 GDB 與 [ gcc-vcg-plugin ] 提供的 vcg.gdbinit 巨集指令:
$ gdb -x src/vcg.gdbinit -tty /dev/null -q \ -args /usr/lib/gcc/i486-linux-gnu/4.5/cc1 test.c \ -fplugin=/tmp/gcc-vcg-plugin/lib/gcc-vcg-plugin/vcg.so -O2注意到 "-fplugin=/tmp/gcc-vcg-plugin/lib/gcc-vcg-plugin/vcg.so" 這個選項,即告知 GCC 預先載入此特製的 Plugin,去改變原有編譯器行為。接著就會取得 "(gdb) " 的命令提示,比方說筆者想分析 GCC 的 "execute_one_pass",只要設定中斷點,並稍候呼叫 [ vcgviewer] 顯示即可,流程如下:
(gdb) break execute_one_pass Breakpoint 1 at 0x8521c96 (gdb) run Starting program: /usr/lib/gcc/i486-linux-gnu/4.5/cc1 test.c \ -fplugin=/tmp/gcc-vcg-plugin/lib/gcc-vcg-plugin/vcg.so -O2 Breakpoint 1, 0x08521c96 in execute_one_pass () (gdb) view_cfg輸出的參考畫面:
即顯示 test.c 的 top-level function。