我們在需要編譯出運(yùn)行在ARM平臺(tái)上的代碼,所使用的交叉編譯器為arm-linux-gcc。
基本概念
首先介紹下編譯器的工作過程诗赌,在使用GCC編譯程序時(shí),編譯過程分為四個(gè)階段:
- 預(yù)處理(Pre-processing)
- 編譯(Compiling)
- 匯編(Assembling)
- 鏈接(Linking)
程序員可以根據(jù)自己的需要讓GCC在編譯的任何階段結(jié)束秸弛,以便檢查或使用編譯器在該階段的輸出信息铭若,或者對最后生成的二進(jìn)制文件進(jìn)行控制,以便通過加入不同數(shù)量和種類的調(diào)試代碼來為 今后的調(diào)試做好準(zhǔn)備胆屿。和其它常用的編譯器一樣奥喻,GCC也提供了靈活而強(qiáng)大的代碼優(yōu)化功能,利用它可以生成執(zhí)行效率更高的代碼非迹。
arm-linux-gcc 用法說明
arm-linux-gcc命令主要是編譯不鏈接
以文件example.c為例說明它的用法
arm-linux-gcc -o example example.c
不加-c环鲤、-S、-E參數(shù)憎兽,編譯器將執(zhí)行預(yù)處理冷离、編譯、匯編纯命、鏈接操作直接生成可執(zhí)行代碼西剥。
-o:用于指定輸出的文件,輸出文件名為example亿汞,如果不指定輸出文件瞭空,則默認(rèn)輸出a.outarm-linux-gcc -c -o example.o example.c
-c:對源程序example.c進(jìn)行預(yù)處理、編譯疗我、匯編操作咆畏,生成example.o文件
注:去除輸出選項(xiàng)-o example.o 自動(dòng)輸出為example.o,所以此處加不加-o都可以arm-linux-gcc - S -o example.s example.c
-S:對源文件example.c進(jìn)行預(yù)處理吴裤、編譯旧找,生成example.s文件arm-linux-gcc -E -o example.i example.c
-E:將對源程序example.c進(jìn)行預(yù)處理,生成example.i文件
就是將#include, #define 等進(jìn)行文件插入及宏擴(kuò)展等操作arm-linux-gcc -v -o example example.c
-v:顯示編譯時(shí)的詳細(xì)信息麦牺,編譯器的版本钮蛛,編譯過程等arm-linux-gcc -g -o example example.c
-g:假如GDB能夠使用的調(diào)試信息,使用GDB調(diào)試時(shí)比較方便arm-linux-gcc -Wall -o example example.c
-Wall:打開所有需要注意的警告信息剖膳,像再生命之錢就使用的函數(shù)魏颓,聲明后卻沒有使用的變量等arm-linux-gcc -0x -o example example.c
-0x:使用優(yōu)化選項(xiàng),x的值可為空吱晒、0甸饱、1、2枕荞、3
0為不優(yōu)化柜候,優(yōu)化的目的是減少代碼空間和提高執(zhí)行效率等,但相應(yīng)的編譯過程時(shí)間較長并占用較大的內(nèi)存空間躏精。arm-linux-gcc -I /home/include -o example example.c
-I dirname:將dirname所指出的目錄加入到程序頭文件目錄列表中渣刷。如果在預(yù)設(shè)系統(tǒng)及當(dāng)前目錄中沒有找到需要文件,就到指定的dirname目錄中去尋找矗烛。arm-linux-gcc -L /home/lib -o example example.c
-L dirname:將dirname所指出的目錄加入到庫文件的目錄列表中辅柴。在默認(rèn)狀態(tài)下,連接程序ld在系統(tǒng)的預(yù)設(shè)路徑中(如/usr/lib)尋找所需要的庫文件瞭吃,這個(gè)選項(xiàng)告訴連接程序碌嘀,首先到-L指定的目錄中去尋找,然后再到系統(tǒng)預(yù)設(shè)路徑中尋找歪架。arm-linux-gcc -static -o libexample.a example.c
靜態(tài)鏈接庫文件
arm-linux-ld 鏈接器用法說明
arm-linux-ld主要是鏈接
-
arm-linux-ld -Ttext 0x00000000 -g led_on.o -o led_on_elf
用Ttext指明我們程序存儲(chǔ)的地方股冗,這里生成的是elf文件,還不是我們真正的bin和蚪,但是可以借助一些工具可以進(jìn)行調(diào)試止状。然后: -
arm-linux-objcopy -O binary -S led_on_elf led_on.bin **
生成bin文件。
-T選項(xiàng)是ld命令中比較重要的一個(gè)選項(xiàng)攒霹,可以用它直接指明代碼的代碼段怯疤、數(shù)據(jù)段、bbs段催束,對于復(fù)雜的連接集峦,可以專門寫一個(gè)腳本來告訴編譯器如何連接。
-Ttext addr
-Tdata addr
-Tbss addr
arm-linux-ld -Ttext 0x00000000 -g led_On.o -o led_on_elf 抠刺,運(yùn)行地址為0x00000000塔淤,由于沒有指明數(shù)據(jù)段和bss,他們會(huì)默認(rèn)的依次放在后面**矫付。相同的代碼 不同的Ttext凯沪,你可以對比一下他們之間會(huì)變的差異,ld會(huì)自動(dòng)調(diào)整跳轉(zhuǎn)的地址买优。
arm-linux-objcopy生成bin文件
把一種目標(biāo)文件中的內(nèi)容復(fù)制到另一種類型的目標(biāo)文件中妨马。
**arm-linux-objcopy -O binary -S led_on_elf led_on.bin **
arm-linux-objdump 生成匯編文件
顯示一個(gè)或者更多目標(biāo)文件的信息。使用選項(xiàng)來控制其顯示的信息杀赢,它所顯示的信息通常只有編寫編譯工具的人才感興趣烘跺。
arm-linux-objdump -D -m arm led_on_c_elf > led_on_c.dis
arm-linux工具的功能如下:
arm-linux-addr2line 把程序地址轉(zhuǎn)換為文件名和行號(hào)。在命令行中給它一個(gè)地址和一個(gè)可執(zhí)行文件名脂崔,它就會(huì)使用這個(gè)可執(zhí)行文件的調(diào)試信息指出在給出的地址上是哪個(gè)文件以及行號(hào)滤淳。
arm-linux-ar 建立、修改砌左、提取歸檔文件脖咐。歸檔文件是包含多個(gè)文件內(nèi)容的一個(gè)大文件铺敌,其結(jié)構(gòu)保證了可以恢復(fù)原始文件內(nèi)容。
arm-linux-c++flit 連接器使用它來過濾 C++ 和 Java 符號(hào)屁擅,防止重載函數(shù)沖突偿凭。
arm-linux-gprof 顯示程序調(diào)用段的各種數(shù)據(jù)。
arm-linux-ld 是連接器派歌,它把一些目標(biāo)和歸檔文件結(jié)合在一起弯囊,重定位數(shù)據(jù),并連接符號(hào)引用胶果。通常匾嘱,建立一個(gè)新編譯程序的最后一步就是調(diào)用ld。
arm-linux-nm 列出目標(biāo)文件中的符號(hào)早抠。
arm-linux-objcopy 把一種目標(biāo)文件中的內(nèi)容復(fù)制到另一種類型的目標(biāo)文件中霎烙。
arm-linux-ranlib 產(chǎn)生歸檔文件索引,并將其保存到這個(gè)歸檔文件中贝或。在索引中列出了歸檔文件各成員所定義的可重分配目標(biāo)文件吼过。
arm-linux-readelf 顯示elf格式可執(zhí)行文件的信息。
arm-linux-size 列出目標(biāo)文件每一段的大小以及總體的大小咪奖。默認(rèn)情況下盗忱,對于每個(gè)目標(biāo)文件或者一個(gè)歸檔文件中的每個(gè)模塊只產(chǎn)生一行輸出。
arm-linux-string 打印某個(gè)文件的可打印字符串羊赵,這些字符串最少4個(gè)字符長趟佃,也可以使用選項(xiàng)-n設(shè)置字符串的最小長度。默認(rèn)情況下昧捷,它只打印目標(biāo)文件初始化和可加載段中的可打印字符闲昭;對于其他類型的文件它打印整個(gè)文件的可打印字符。這個(gè)程序?qū)τ诹私夥俏谋疚募膬?nèi)容很有幫助靡挥。
arm-linux-strip 丟棄目標(biāo)文件中的全部或者特定符號(hào)序矩。
arm-linux-gcc -wall -O2 -c -o $@ $<
-o 只激活預(yù)處理,編譯,和匯編,也就是他只把程序做成obj文件
-Wall 指定產(chǎn)生全部的警告信息
-O2 編譯器對程序提供的編譯優(yōu)化選項(xiàng),在編譯的時(shí)候使用該選項(xiàng)跋破,可以使生成的執(zhí)行文件的執(zhí)行效率提高
-c 表示只要求編譯器進(jìn)行編譯簸淀,而不要進(jìn)行鏈接,生成以源文件的文件名命名但把其后綴由 .c 或 .cc 變成 .o 的目標(biāo)文件
-S 只激活預(yù)處理和編譯毒返,就是指把文件編譯成為匯編代碼
arm-linux-ld 直接指定代碼段,數(shù)據(jù)段,BSS段的起始地址
-Tbss ADDRESS Set address of .bss section
-Tdata ADDRESS Set address of .data section
-Ttext ADDRESS Set address of .text section
示例:
${CROSS}ld -Ttext=0x33000000 led.o -o led.elf
使用連接腳本設(shè)置地址:
arm-linux-ld -T beep.lds start.o beep.o -o beep.elf
其中beep.lds 為連接腳本如下:
arm-linux-objcopy被用來復(fù)制一個(gè)目標(biāo)文件的內(nèi)容到另一個(gè)文件中,可用于不同源文件的之間的格式轉(zhuǎn)換
示例:
arm-linux-objcopy –o binary –S elf_file bin_file
常用的選項(xiàng):
input-file , outflie
輸入和輸出文件,如果沒有outfile,則輸出文件名為輸入文件名
2.-l bfdname或—input-target=bfdname
用來指明源文件的格式,bfdname是BFD庫中描述的標(biāo)準(zhǔn)格式名,如果沒指明,則arm-linux-objcopy自己分析
3.-O bfdname 輸出的格式
4.-F bfdname 同時(shí)指明源文件,目的文件的格式
5.-R sectionname 從輸出文件中刪除掉所有名為sectionname的段
6.-S 不從源文件中復(fù)制重定位信息和符號(hào)信息到目標(biāo)文件中
7.-g 不從源文件中復(fù)制調(diào)試符號(hào)到目標(biāo)文件中
arm-linux-objdump
查看目標(biāo)文件(.o文件)和庫文件(.a文件)信息
arm-linux-objdump -D -m arm beep.elf > beep.dis
-D 顯示文件中所有匯編信息
-m machine
指定反匯編目標(biāo)文件時(shí)使用的架構(gòu)租幕,當(dāng)待反匯編文件本身沒有描述架構(gòu)信息的時(shí)候(比如S-records),這個(gè)選項(xiàng)很有用拧簸【⑿鳎可以用-i選項(xiàng)列出這里能夠指定的架構(gòu).