第一章 鏡像結構
注意:本文章只針對,裸機開發.至於SysV,BPABI,BP的鏈接模型請參考《armlink_user_guide》
1.1 重要的概念
1.1.1 鏡像的構成
編譯器將源文件編譯成中間文件。鏈接器將中間文件最終生成鏡像文件。
在中間文件中,邏輯最小單元稱爲section。鏈接器將所有中間文件的section收集起來,然後按照一定的規則,進行重新組織。將具有相同屬性的section,組織在一起,稱爲輸出section。相應的,中間文件的section稱爲輸入section。然後再將不同的輸出section組織在一起,起個名字叫做region。
他們之間的關係如下圖
下面分別介紹輸入section,輸出section,region和segment
-
輸入section:輸入section來自於中間文件。它含有代碼,初始化數據或者描述信息。描述信息用於表示未被初始化的段或者鏡像執行之前必須設置爲0的段。輸入section具有RO,RW,XO,ZI這樣的屬性。這些屬性被armlink用於組織成region或者輸出section
-
輸出section:輸出section其實是具有相同屬性的輸入section的集合,因此輸出section的屬性和輸入section的屬性相同。這些輸入section被連續的放置於內存中。
-
region:一個region最多包含四個不同屬性的輸出section。默認情況下,在region中的輸出section根據屬性進行排序。XO輸出section總是第一個,接着是RO輸出section,然後是RW輸出section,最後是ZI輸出section。通常一個region被映射成一個物理內存設備,例如ROM,RAM。可以使用scatter改變輸出section的順序。
-
segment:等同於region,之所以叫segment是因爲在arm elf標準中使用了這個術語。
注意:armlink的單個segment的最大值爲2GB
RO——read only
RW——read write
ZI——zero initialized
XO——execute only
1.1.2 鏡像的地址
在執行鏡像之前,可能必須要把部分region移動到它的執行地址處,或者創建ZI輸出section。例如,對於已經初始化的RW數據可能必須將其從ROM移動到RAM處。
這樣就會導致一個鏡像具有兩種不同的內存視圖:加載視圖,執行視圖
- 加載視圖:描述了鏡像執行之前的地址
- 執行視圖:描述了鏡像執行時的地址
當region的加載地址和執行地址一樣時,稱爲root region
下圖展示了這兩者的區別。
1.2 三種簡單的鏡像結構
爲了幫助理解上述概念,這裏介紹三種簡單鏡像。
1.2.1 類型1
類型1:一個加載region,三個執行region。如下圖所示:
爲了指定ro的地址,可以使用命令行選項–ro_base.命令如下:
armlink --ro_base 0x8000
注意:0x8000是默認地址,因此在這個例子中,也可以不用指定
加載視圖:這個唯一的加載region由RO和RW兩個輸出section組成。ZI輸出section在加載視圖中不存在,他是在執行之前創建的。
執行視圖:由三個連續的執行region組成,他們分別包含RO,RW和ZI輸出section。RO和RW的執行地址與加載地址一樣,因此無需做任何移動。但是,ZI執行region必須在運行時創建。
使用--ro_base address指定RO region的加載和執行地址。
使用--zi_base address指定ZI region的執行地址。
包含XO的加載視圖
如果一個鏡像包含XO section。那麼XO輸出section就被放置於--ro_base指定的位置處。RO和RW則連續排在其後
包含XO的執行視圖
如果一個鏡像包含XO section,那麼XO執行地址爲--ro_base指定的地址處,RO,RW和ZI緊隨其後
1.2.2 類型2
類型2:一個加載region,三個執行region。但是RW執行region的地址和RO的執行地址不連續。
如下圖:
使用下面的命令創建這種類型的鏡像:
armlink --ro_base 0x0 --rw_base 0xA000
加載視圖:一個加載region,包含RO和RW輸出section,且這兩者連續放置。
執行視圖:第一執行region包含RO輸出section。第二個執行region包含RW和ZI輸出section
第一個執行region和加載region地址相同,因此不需要移動。第二個執行regoin和加載region的地址不同,因此它需要進行搬運。ZI 執行region在運行時創建
使用--ro_base address指定RO輸出section加載和執行地址。
使用--rw_base address指定RW輸出section的執行地址。
使用--zi_base address指定ZI執行region的地址
含有XO region的加載視圖
如果一個鏡像含有XO section。那麼XO section被放置在--ro_base指定的地址處。RO和RW則緊隨其後
含有XO region的執行視圖
如果一個鏡像含有XO section。那麼XO section的執行region放置在--ro_base指定的地址處。RO則緊隨其後
如果使用了--xo_base address,那麼XO 執行region被放置在這個指定的地址處
1.2.3 類型3
類型3:該類型類似於類型2,但是跟類型2不同的是,類型3的加載視圖,被分隔成多個root region。如下圖:
使用下面的命令,生成這種類型的鏡像:
armlink --split --ro_base 0x8000 --rw_base 0xE000
加載視圖:第一個 加載region 包含 RO輸出section 。第二個 加載region 包含 RW輸出section。
執行視圖:第一個執行region包含RO 輸出section,第二個執行region包含RW輸出section。第三個執行region包含ZI輸出section。
RO和RW輸出section都是root region,因此不需要移動,只有ZI需要在運行時創建。
使用–split,將默認的單個加載region分隔開。
含有XO的加載視圖
如果一個鏡像含有XO section,則XO被放置在--ro_base 所在的地址處,RO和RW緊隨其後
含有XO的執行視圖
如果一個鏡像含有XO section,則放置在--ro_base 所指的地址處。
如果你指定了--split選項,XO和RO被放置在第一個加載regioin中,RW和ZI執行region放在第二個加載region中
如果你指定了--xo_base,XO的執行地址則是此處指定的地址。
本章完,下章,scatter文件語法