GNU的編譯器和調(diào)試工具
一. 編譯工具
1.編輯工具介紹
GNU 提供的編譯工具包括匯編器as、C編譯器gcc、C++編譯器g++、連接器ld和二進制轉(zhuǎn)換工具objcopy?;?/span>ARM平臺的工具分別為arm- linux-as、arm-linux-gcc、arm-linux-g++、arm-linux-ld和arm-linux- objcopy。GNU的編譯器功能非常強大,共有上百個操作選項,這也是這類工具讓初學者頭痛的原因。不過,實際開發(fā)中只需要用到有限的幾個,大部分可以采用缺省選項。GNU工具的開發(fā)流程如下:編寫C、C++語言或匯編源程序,用gcc或g++生成目標文件,編寫連接腳本文件,用連接器生成最終目標文件(elf格式),用二進制轉(zhuǎn)換工具生成可下載的二進制代碼。
(1)編寫C、C++語言或匯編源程序
通常匯編源程序用于系統(tǒng)最基本的初始化,如初始化堆棧指針、設置頁表、操作ARM的協(xié)處理器等。初始化完成后就可以跳轉(zhuǎn)到C代碼執(zhí)行。需要注意的是,GNU的匯編器遵循AT&T的匯編語法,讀者可以從GNU的站點(www.gnu.org)上下載有關規(guī)范。匯編程序的缺省入口是 start標號,用戶也可以在連接腳本文件中用ENTRY標志指明其它入口點(見下文關于連接腳本的說明)。
(2)用gcc或g++生成目標文件
如果應用程序包括多個文件,就需要進行分別編譯,最后用連接器連接起來。如筆者的引導程序包括3個文件:init.s(匯編代碼、初始化硬件)xmrecever.c(通信模塊,采用Xmode協(xié)議)和flash.c(Flash擦寫模塊)。
分別用如下命令生成目標文件: arm-linux-gcc-c-O2-oinit.oinit.s
arm-linux-gcc-c-O2-oxmrecever.oxmrecever.c
arm-linux-gcc-c-O2-oflash.oflash.c 其中-c命令表示只生成目標代碼,不進行連接;-o命令指明目標文件的名稱;-O2表示采用二級優(yōu)化,采用優(yōu)化后可使生成的代碼更短,運行速度更快。如果項目包含很多文件,則需要編寫makefile文件。關于makefile的內(nèi)容,請感興趣的讀者參考相關資料。
(3)*編寫連接腳本文件
gcc 等編譯器內(nèi)置有缺省的連接腳本。如果采用缺省腳本,則生成的目標代碼需要操作系統(tǒng)才能加載運行。為了能在嵌入式系統(tǒng)上直接運行,需要編寫自己的連接腳本文件。編寫連接腳本,首先要對目標文件的格式有一定了解。GNU編譯器生成的目標文件缺省為elf格式。elf文件由若干段(section)組成,如不特殊指明,由C源程序生成的目標代碼中包含如下段:.text(正文段)包含程序的指令代碼;.data(數(shù)據(jù)段)包含固定的數(shù)據(jù),如常量、字符串;.bss(未初始化數(shù)據(jù)段)包含未初始化的變量、數(shù)組等。C++源程序生成的目標代碼中還包括.fini(析構函數(shù)代碼)和. init(構造函數(shù)代碼)等。連接器的任務就是將多個目標文件的.text、.data和.bss等段連接在一起,而連接腳本文件是告訴連接器從什么地址開始放置這些段。例如連接文件link.lds為:
ENTRY(begin) ;指明程序的入口點為begin標號
SECTION ;段
{
.=0x30000000; ;指明目標代碼的起始地址為0x30000000,這一段地址為片內(nèi)RAM
.text:{*(.text)} ;表示從0x30000000開始放置所有的目標文件的代碼段
.data:{*(.data)} ;數(shù)據(jù)段從代碼段的末尾開始
.bss:{*(.bss)} ;bss段從數(shù)據(jù)段的末尾開始
}
其中,ENTRY(begin)指明程序的入口點為begin標號;.=0x00300000指明目標代碼的起始地址為0x30000000,這一段地址為 MX1的片內(nèi)RAM;.text:{*(.text)}表示從0x30000000開始放置所有目標文件的代碼段,隨后的.data:{*
(.data)}表示數(shù)據(jù)段從代碼段的末尾開始,再后是.bss段。
(4)用連接器生成最終目標文件
有了連接腳本文件,如下命令可生成最終的目標文件:
arm-linux-ld –no stadlib –o bootstrap.elf -Tlink.lds init.o xmrecever.o flash.o
其中,ostadlib表示不連接系統(tǒng)的運行庫,而是直接從begin入口;-o指明目標文件的名稱;-T指明采用的連接腳本文件(也可以使用-Ttext
address,address表示執(zhí)行區(qū)地址);最后是需要連接的目標文件列表。
(5)生成二進制代碼
連接生成的elf文件還不能直接下載執(zhí)行,通過objcopy工具可生成最終的二進制文件:
arm-linux-objcopy –O binary bootstrap.elf bootstrap.bin
其中-O binary指定生成為二進制格式文件。Objcopy還可以生成S格式的文件,只需將參數(shù)換成-O srec。還可以使用-S選項,移除所有的符號信息及重定位信息。如果想將生成的目標代碼反匯編,還可以用objdump工具:
arm-linux-objdump -D bootstrap.elf
至此,所生成的目標文件就可以直接寫入Flash中運行了。
2.Makefile實例
example: head.s main.c
arm-linux-gcc -c -o head.o head.s
arm-linux-gcc -c -o main.o main.c
arm-linux-ld -Tlink.lds head.o ain.o -o example.elf
arm-linux-objcopy -O binary -S example_tmp.o example
arm-linux-objdump -D -b binary -m arm example >ttt.s
二. 調(diào)試工具
Linux 下的GNU調(diào)試工具主要是gdb、gdbserver和kgdb。其中gdb和gdbserver可完成對目標板上Linux下應用程序的遠程調(diào)試。 gdbserver是一個很小的應用程序,運行于目標板上,可監(jiān)控被調(diào)試進程的運行,并通過串口與上位機上的gdb通信。開發(fā)者可以通過上位機的gdb輸入命令,控制目標板上進程的運行,查看內(nèi)存和寄存器的內(nèi)容。gdb5.1.1以后的版本加入了對ARM處理器的支持,在初始化時加入- target==arm參數(shù)可直接生成基于ARM平臺的gdbserver。gdb工具可以從ftp: //ftp.gnu.org/pub/gnu/gdb/上下載。
對于Linux內(nèi)核的調(diào)試,可以采用kgdb工具,同樣需要通過串口與上位機上的gdb通信,對目標板的Linux內(nèi)核進行調(diào)試??梢詮?/span>http://oss./projects/kgdb/上了解具體的使用方法。
參考資料:
1. Richard Blum,Professional Assembly Language
2. GNU ARM 匯編快速入門,http://blog./u/31996/showart.php?id=326146
3. ARM GNU 匯編偽指令簡介,http://www./jb8164/archive/2008/01/22/41661.aspx
4. GNU匯編使用經(jīng)驗,http://blog./u1/37614/showart_390095.html
5. GNU的編譯器和開發(fā)工具,http://blog./blog-htm-do-showone-uid-34335-itemid-81387-type-blog.html
6. 用GNU工具開發(fā)基于ARM的嵌入式系統(tǒng),http://blog.163.com/liren0@126/blog/static/32897598200821211144696/
7. objcopy命令介紹,http://blog.csdn.net/junhua198310/archive/2007/06/27/1669545.aspx