基本內容 在keil的help中都有, 不過經作者梳理後, 看起來更清晰些; 感謝! (轉載記錄)
原文鏈接:https://blog.csdn.net/suxiang198/article/details/70786574
查看原鏈接地址, 文檔結構更好;
簡述
早前Keil被ARM收購,而目前比較主流的嵌入式系統的IC都是ARM架構的,因此許多嵌入式工程開發環境是Keil,一些比較複雜的情況下需要根據自己的需要劃分memory空間,因此對Keil中鏈接腳本的內容值得學習一番。下面的介紹都是基於ARM Compiler armlink v6.4 Release(2016.2.24更新版本)進行的。
armlink相關介紹
基本特性
Linker的功能就是將編譯生成的各個中間文件作爲輸入,產生鏈接後的可執行文件。
1. 支持多種格式的可執行文件輸出(比如binary, hex, axf等);
2. 可以鏈接A32, T32或A64代碼;
3. 自動選擇合適的C或C++庫進行鏈接;
4. 可以自定義將code和data放在memory map的對應位置,通過鏈接時輸入命令或者使用scatter file的形式進行;
5. RW data壓縮佔用最小的ROM size;
6. 優化未用的sections;
7. 在鏈接輸出文件中置入調試信息;
8. 產生靜態的調用圖,並列出stack的用量;
9. 輸出文件中置入symbol table;
10. 輸出文件中顯示code和data size;
link command
armlink options input-file-list
1
輸入項 說明
options Linker command-line options
input-file-list A space-separated list of objects, libraries, or symbol definitions (symdefs) files
關於options輸入項,Keil列出了上百種,方便配置各項link參數。
link過程
* 從輸入文件解析符號;
* 從庫中抽取對象模塊,以滿足一些符號需求;
* 移除未使用到的sections;
* 將重複的共用的代碼,數據,調試sections進行優化;
* 將輸入sections進行分類,將相似屬性與名字的sections進行整合成爲連續的塊;
* 根據分組和提供的劃分信息組織對象放入memory區域;
* 分配地址給可重定位的值;
* 產生可執行image。
鏈接模式
鏈接模式(Linking Model)是因命令參數和memory map不同而使用的鏈接器的不同行爲模式。
鏈接模式 說明
Bare-metal 目標無關,可以使用自己的OS, memory map, app code創建image,一些有限制性的動態鏈接也支持。可以指定額外的選項
Bare-metal Position Independent Executables(PIE) 不需要指定地址,可以在任何適合的地址執行,所有對象和庫都必須是位置無關的
Partial linking 已經鏈接過的部分ELF文件作爲輸入,繼續進行鏈接
BPABI 支持類似DLL方式
Base Platform 爲BPABI的支持scatter-loading的擴展
Image的結構
ARM ELF image由sections, regions, segments組成。
ELF object file view(linker input)
從鏈接輸入文件的角度看,ELF object file可以是如下類型:
ELF object file 說明
可重定位文件 應當就是編譯後的文件,可以重定位
共享對象文件 包含了code和data的共享對象文件
Linker View
從鏈接器的角度看,有兩種類別的地址:
地址類別 說明
Load Address Linker期望外部加載器之類的從ELF文件拷貝fragment的位置/地址, 可能和fragment實際執行的地址並不一樣
Execution Address Linker期望fragment程序執行期間的實際地址
如果一個fragment是位置獨立的或可重定位的,那執行期間它的執行地址可以變化。
ELF image file view(linker output)
ELF image file view由程序segment和output sections組成:
組成部分 說明
Load region 一個Load region對應一個程序片段(program segment)
Execution region 包含了RO, RW, XO, ZI其中一個或以上的output sections
一個或多個execution regions組成一個Load region。
各個部分進一步說明
部分 說明
Input section 從鏈接輸入文件中解析出的獨立section,包含code(RO),初始化了的data(RW),未初始化但描述了一段memory(XO),在image能執行前必須設置爲0的部分,一般是在該output section給出描述,實際空間是在執行時分配的(ZI)
Output section 將有相同RO,RW,XO,ZI屬性的input sections組成起來,被linker整合爲連續的內存空間
Region 一個region可包含多達4個output sections,output sections在region中的位置爲XO–>RO–>RW–>ZI,一個region一般映射到物理memory設備(ROM,RAM,Peripheral),也可能通過scatter-loading改變output sections的順序
Program segment 一個程序片段對應一個load region(包含execution regions),程序片段包含text和data信息
注:XO memory只支持ARMv7-M和ARMv8-M架構。
image結構的加載時視圖以及運行時視圖
爲何之前提到的Load Address和Execution Address可能會不同呢,因爲在load(bootloader)時是將image regions放到系統的memory map,但是在程序執行時,memory中region的位置可能發生改變。
在執行image前,有時候可能需要將一些regions移到memory的可執行地址,並創建ZI output sections。例如RW data可能需要從其處於ROM的load address拷貝到處於RAM中的execution address。
視圖 說明
Load view 程序下載到memory,但程序尚未運行
Execution view 程序開始運行後
所以Load Address和Execution Address的不同就是因爲在程序啓動時,會有memory搬移的動作而導致地址發生變化。
常見image視圖示例
OS bootloader或桌面系統:
對應鏈接command:
armlink --cpu=8-A.32 --ro_base 0x8000
1
一般沒有特別通過armlink指定,regions中output sections的排序是XO–>RO–>RW–>ZI的,這裏只指定了ro_base,即RO地址指定了,RW,ZI會自動鏈接到其後面。
上面這裏沒有XO section,如果有的話,ro_base是指定的XO section的地址,RO,RW,ZI會連續接在其後面。
Embedded系統
對應的鏈接command:
armlink --cpu=8-A.32 --ro_base 0x0 --rw_base 0xA000
1
注意,如果有XO section的話,和上圖一樣的處理。另外,execution address和load address不同的話,搬移時原則是execution region不能和load region有重合。
更加複雜點的情況
對應的鏈接command:
armlink --cpu=8-A.32 --split --ro_base 0x8000 --rw_base 0xE000
1
————————————————
版權聲明:本文爲CSDN博主「suxiang198」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/suxiang198/article/details/70786574