1. 程式人生 > >GCC原始碼分析(一)——介紹與安裝

GCC原始碼分析(一)——介紹與安裝

原文連結:http://blog.csdn.net/sonicling/article/details/6702031

    上半年一直在做有關GCC和LD的專案,到現在還沒做完。最近幾天程式設計的那臺電腦壞了,所以趁此間隙寫一點相關的分析和經驗之類的跟大家共享。


一、GCC的作用和執行機制
    GCC是Linux下重要的編譯工具,用法這裡就不說了,滿大街都找得到。這裡我重點介紹GCC的運作機制,作為程式碼分析的鋪墊。全篇使用C語言子部件來作分析,因為我對其他語言的編譯沒有研究。
     根據編譯原理,語言的編譯分為這麼幾個步驟:詞法分析、語法分析、語義分析、中間語言生成、優化、目的碼生成等。然而從編譯器使用的角度來看,要把原始碼翻譯為可執行檔案要經過編譯和連線兩步,與此對應,一個完整的編譯系統一定包含編譯器和聯結器兩大功能部件。編譯器要完成編譯原理中提到的那些任務;聯結器要把編譯器生成的程式碼片段拼接成一個完整的可執行程式。之所以需要聯結器,是因為一般的程式都是多原始檔的,而編譯器一次只編譯一個原始檔(稱之為翻譯單元translation unit),因此需要聯結器把所有翻譯單元對應的輸出合併成一個可執行檔案。

如果一切順利,可執行程式就可以正確的生成出來。但是一旦原始碼存在某些問題,錯誤就會被報告出來。編譯器報告的錯誤一般都是區域性錯誤,它會指明錯誤在哪個檔案第幾行;聯結器報告的錯誤一般都是全域性錯誤,而且絕大多數都是多胳膊少腿的問題,比如函式重定義,無法解決的外部符號等,這些錯誤無法定位到某一行。
     GCC就是這裡的編譯器。準確來說,GCC是一個編譯驅動器,驅動cc1、as和ld三個部件完成編譯、彙編和連線的工作。cc1將C語言原始檔編譯為彙編檔案(.s)。而將彙編程式碼轉換為二進位制指令的工作由AS完成,生成大家都很熟悉的物件檔案(.o);生成的這些物件檔案再由AR程式打包成靜態庫(.a),或者由LD程式連線成可執行程式(elf、.so或其他格式)。而LD就是所謂的聯結器。AS、AR、LD是屬於另外一個叫做binutils的軟體包的程式,所以要讓GCC能夠有效運作起來,除了在系統中安裝GCC外,還要安裝binutils才行。
     以下是cc1、as、ld各司其責的配合完成一個編譯過程。

gcc test.c -S -o test.S  
as test.S -o test.o  
ld test.o -o test

    通常所用的“gcc -c”就相當於“gcc -S” + as,而對於編譯單個原始檔一步到位生成可執行“gcc test.c -o test”相當於上面三個步驟的組合,中間檔案被放置在臨時目錄下。從這一點看來,GCC除去編譯的功能外,更像是個driver,它可以驅動as和ld完成整個的編譯,特別是gcc也接受物件檔案(.o)和靜態庫(.a)作為引數用於生成可執行程式,其實背後就是呼叫的LD,還可以用“-Wl,”選項給LD傳遞自定義引數。所以在大多數軟體的Makefile裡,你很難找到AS和LD的字眼,gcc已經給你包辦了。

    GCC原始碼裡包含的主要就是cc1這部分(還包括一些其他的輔助工具,比如collect2等)。


二、GCC的安裝
    要學習和修改GCC原始碼,首先第一步是在自己的機器上用GCC原始碼編譯出一個選定版本的GCC(這裡以gcc-4.5.2.tar.bz2為例,原始碼可以從http://gcc.gnu.org去下載)。除此之外,GCC依賴於gmp、mpfr、mpc三個庫,如果你機器上沒有,或者版本太老以至於無法支援新的GCC,那麼你還得去把這三個庫下載下來。
    一般來說,下載GCC是從GNU的FTP映象網站去下載,gcc的程式碼包一般放置在/release/gcc-x.y目錄下,而那三個依賴庫一般放置在/infrastructure/目錄下。

1、把依賴庫和GCC解包

tar -vjxf gmp-4.3.2.tar.bz2 -C /usr/src/  
tar -vjxf mpfr-2.4.2.tar.bz2 -C /usr/src/  
tar -vxf mpc-0.8.1.tar.gz -C /usr/src/  
tar -vjxf gcc-4.5.2.tar.bz2 -C /usr/src/

2、到自己的home目錄下編譯依賴庫

cd ~  
mkdir gmp-build  
cd gmp-build  
/usr/src/gmp-4.3.2/configure --prefix=/usr/local/gmp-4.3.2 #指定安裝位置  
make  
make check  
make install  

cd ~  
mkdir mpfr-build  
cd mpfr-build  
/usr/src/mpfr-2.4.2/configure --prefix=/usr/local/mpfr-2.4.2 --with-gmp=/usr/local/gmp-4.3.2  
make  
make check  
make install  

cd ~  
mkdir mpc-build  
cd mpfr-build  
/usr/src/mpc-0.8.1/configure --prefix=/usr/local/mpc-0.8.1 --with-mpfr=/usr/local/mpfr-2.4.2 --with-gmp=/usr/local/gmp-4.3.2  
make  
make check  
make install

3、編譯GCC

cd ~  
mkdir gcc-build  
cd gcc-build  
/usr/src/gcc-4.5.2/configure --prefix=/usr/local/gcc-4.5.2 --with-mpc=/usr/local/mpc-0.8.1 --with-mpfr=/usr/local/mpfr-2.4.2 --with-gmp=/usr/local/gmp-4.3.2 --enable-languages=c,c++  
make  
make install

    漫長等待過後GCC就被安裝到/usr/local/gcc-4.5.2目錄下了,然後ln -s /usr/local/gcc-4.5.2/bin/gcc /usr/local/bin/gcc,最後gcc -v看看,版本號是不是換了?