連結定位是系統級軟體開發過程中必不可少的一部分,嵌入式軟體開發均屬
於系統級開發,絕大部分嵌入式軟體都涉及到連結定位指令檔;連結定位指令碼
使得我們的目標程式碼群組織更加靈活.
1)連結定位指令檔說明
連結定位過程一般由連結器根據連結定位指令碼完成,比較簡單的系統可以通
過設定連結器開關選項取代連結定位指令碼;連結定位的關鍵是連結定位指令碼的編
寫.我們從典型的目標檔案結構開始,來介紹連結定位指令檔的編寫.下面是
該系統一個目標檔案的典型組織:
其中第二欄開始分別展示了該檔案各個段(Sections)的屬性:名稱(Name),
類型(Type),地址(Addr),位移(Offs),大小(Size),固定單元大小(Es),
標誌(Flg),串連依賴(Lk),附加屬性(Inf),位元組對其寬度(Al).
地址部分(Addr)描述了這一段在目標系統中的地址,而位移(Offs)則記
載了該段在目標檔案中的位移,大小(size)表示該段的實際長度;比如
中.Text段的地址為0x0c700000,位移為0x008000,大小為0x00d950,說明該
段位於檔案的位移0x008000處,它將被下載到目標板0x0c700000處.
從段的分類來看,第7段以後的內容僅僅與調試有關,涉及到定位的也就是
前面幾段:.text,.data,.rodata,.bss,下面是一個具體的連結定位指令碼文
件:
SECTIONS
{
. = 0x0c200000; /*賦當前地址,後續的代碼將從該地址開始存放 */
.text : { (.text) } /*.text段表示程式碼片段,從0x0c200000開始放置代碼*/
Image_RW_Base = .; /* RW(可寫資料)基址,實際上是在這裡聲明了一個全域符號,我們可
以在程式中使用該符號,它等同於在代碼中聲明一個全域變數,但它的值由連結器指定,在這裡"=."表
示該符號的值等於當前地址;下面的定義類似*/
.data : { (.data) } /*資料區段, 儲存已經初始化的全域資料 */
.rodata : { *(.rodata) } /*唯讀資料區段, 儲存已經初始化的全域唯讀資料*/
Image_ZI_Base = .; /*ZI基地址, 需要清零的地區 zero init*/
.bss : { *(.bss) } /*堆棧段,未初始化的全域變數也儲存在此*/
__bss_start__ = .; /* bss的基地址*/
__bss_end__ = .; /* bss的結束位址*/
__EH_FRAME_BEGIN__ = .; /* FRAME開始地址(基地址)*/
__EH_FRAME_END__ = .; /* FRAME結束位址,gcc編譯器使用 */
武漢創維特 All rights reserved 9
FAQ
PROVIDE (__stack = .); /* 當前地址賦給棧,棧地址一般是可讀寫區最高處*/
end = .; /* 結束位址*/
_end = .; /* 結束位址*/
.debug_info 0 : { *(.debug_info) } /*調試資訊*/
.debug_line 0 : { *(.debug_line) } /*調試資訊*/
.debug_abbrev 0 : { *(.debug_abbrev)} /*調試資訊*/
.debug_frame 0 : { *(.debug_frame) } /*調試資訊*/
}
text段是程式碼段,緊隨其後的是幾個符號定義,它們是由編譯器在編譯
串連時自動計算的,當我們在連結定位檔案中申明這些符號後,編譯串連時,該
符號的值會自動代入到來源程式的引用中,如果你想進一步瞭解串連定位的一些含
義,可以參考編程手冊中的ld一章.
data段的起始位置也是由串連定位檔案所確定,大小在編譯串連時自動分
配,它和我們的程式大小沒有關係,但和程式使用到的全域變數,常量數量相關.
bss的初始值也是由我們自己定義的串連定位檔案所確定,我們應該將它定
義在可讀寫的RAM區內,stack的頂部在可讀寫的RAM區的最後,我們可以非常
靈活的定義其起點和大小,但對大部分情況來說,程式區在ROM或FLASH中,可
讀寫地區在SRAM或DRAM中,我們可以考慮一下自己程式規模,函數調用規模,
儲存空間組織,然後參照一個串連定位檔案稍加修改就可以了.
2)連結定位指令碼修改執行個體
SECTIONS
{
. = 0x00000000; /*將程式碼片段起始地址修改到0*/
.text : { *(.text) }
Image_RW_Base = .;
.=0xc0000000 /*設定資料區段從0xc0000000開始存放*/
.data : { *(.data) }
.=0xd0000000 /*設定唯讀資料區段從0xd0000000開始存放*/
.rodata : { *(.rodata) }
Image_ZI_Base = .;
.bss : { *(.bss) }
Image_ZI_Limit = .;
/*申明一個符號download_size */
download_size = SIZEOF(.text)+SIZEOF(.data)+SIZEOF(.rodata)+SIZEOF(.bss);
__bss_start__ = .;
__bss_end__ = .;