開啟地址無關(guān)后的重定位地址操作
在由save_boot_params跳轉(zhuǎn)回save_boot_params_ret后啟動流程繼續(xù)往下執(zhí)行來到下面代碼段:
save_boot_params_ret:
#if CONFIG_POSITION_INDEPENDENT
/* Verify that we're 4K aligned. */
adr x0, _start
ands x0, x0, #0xfff --------------------------------------------------------- (1)
b.eq 1f
0:
/*
* FATAL, can't continue.
* U-Boot needs to be loaded at a 4K aligned address.
*
* We use ADRP and ADD to load some symbol addresses during startup.
* The ADD uses an absolute (non pc-relative) lo12 relocation
* thus requiring 4K alignment.
*/
wfi
b 0b
1:
/*
* Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
* executed at a different address than it was linked at.
*/
pie_fixup:
adr x0, _start /* x0 < - Runtime value of _start */
ldr x1, _TEXT_BASE /* x1 < - Linked value of _start */
subs x9, x0, x1 /* x9 < - Run-vs-link offset */
beq pie_fixup_done ------------------------------------------------------------- (2)
adrp x2, __rel_dyn_start /* x2 < - Runtime &__rel_dyn_start */ ----------- (3)
add x2, x2, #:lo12:__rel_dyn_start
adrp x3, __rel_dyn_end /* x3 < - Runtime &__rel_dyn_end */
add x3, x3, #:lo12:__rel_dyn_end
pie_fix_loop: ---------------------------------------------------------------------- (4)
ldp x0, x1, [x2], #16 /* (x0, x1) < - (Link location, fixup) */
ldr x4, [x2], #8 /* x4 < - addend */
cmp w1, #1027 /* relative fixup? */
bne pie_skip_reloc
/* relative fix: store addend plus offset at dest location */
add x0, x0, x9
add x4, x4, x9
str x4, [x0]
pie_skip_reloc:
cmp x2, x3
b.lo pie_fix_loop
pie_fixup_done:
#endif
此部分的功能主要是在定義POSITION_INDEPENDENT后,進(jìn)行地址無關(guān)的相對地址修復(fù),以此保證后續(xù)在跳入c語言部分時可正常執(zhí)行,一般不定義此配置則是繼續(xù)往下執(zhí)行boot流程。
- ? (1)正如在鏈接腳本中說的,地址無關(guān)功能最基本需要保證加載地址是4K對齊的,經(jīng)過一些測試發(fā)現(xiàn)某些情況需要64K對齊,這里不展開說明。此處使用adr指令獲取_start的運(yùn)行時地址并檢驗(yàn)是否是4K對齊,如果是則繼續(xù)往下執(zhí)行,如果不是則調(diào)用wfi指令掛死在此處。wfi為等待中斷指令,只有在接收到中斷事件是才會喚醒cpu繼續(xù)往下執(zhí)行。(補(bǔ)充一個知識點(diǎn):wfi指令只能被中斷喚醒,wfe指令可以被sev指令喚醒也可以被中斷喚醒)
- ? (2)通過對運(yùn)行時地址和加載地址相減得到一個地址偏移值,如果偏移值等于0,說明加載地址和運(yùn)行時地址是一致的不需要進(jìn)行地址修復(fù),則直接跳pie_fixup_done繼續(xù)下面流程初始化,否則就進(jìn)入地址修復(fù)邏輯。
- ? (3)首先需要說明為什么不使用adr指令而是adrp指令,adr指令是一個小范圍讀相對pc指針地址內(nèi)存的指令,可以使用adr說明讀取的地址一定是離pc指針很近的位置,而當(dāng)讀取__rel_dyn_start這種并不能確定實(shí)際地址在哪里的地址時則只能使用大范圍讀地址指令的adrp指令,不過adrp指令是以頁為單位進(jìn)行讀取的,所以add x2, x2, #:lo12:__rel_dyn_start的作用就是將__rel_dyn_start地址的頁內(nèi)偏移讀取出來并與頁對齊的運(yùn)行地址相加得到實(shí)際的運(yùn)行地址。(此操作指令在Linux上被封裝為adr_l指令)
- ? (4)在對地址修復(fù)分析時,首先需要了解一個elf動態(tài)庫重定位的知識點(diǎn),先來看一個結(jié)構(gòu)體定義:
typedef struct {
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
當(dāng)對動態(tài)庫進(jìn)行地址重定向時首先會去查找rela.dyn段中的信息,此段中每一組信息就是上面結(jié)構(gòu)體定義的信息,對于64為系統(tǒng)的elf則是24字節(jié)為一個表,r_offset保存需要重定位作用的地址位置,r_info描述此表重定位類型此類型特定于處理器,如arm64位則是:
/* AArch64 relocs */
#define R_AARCH64_NONE 0 /* No relocation */
#define R_AARCH64_RELATIVE 1027 /* Adjust by program base */
r_addend是一個常量加數(shù),用于計(jì)算存儲在可重定位字段中的值。 對表進(jìn)行重定位有以下公式:
重定位為值 = *(r_offset + 實(shí)際偏移值) = 實(shí)際偏移值 + r_addend。
根據(jù)此公式則可以重定向每一個需要重定向的地址值。
因此在此處同樣是如此,x0保存r_offset值,x1保存r_info值,x4保存r_addend,并通過x1與R_AARCH64_RELATIVE比較看是否屬于aarch64相對地址類型,如果不是則不是需要重定向的一組表則跳到pie_skip_reloc判斷是否完成所有rela.dyn段重定向,如果是則繼續(xù)往下執(zhí)行啟動流程初始化,如果不是則跳回pie_fix_loop繼續(xù)下一組表的重定向。
當(dāng)判斷屬于aarch64相對地址類型時進(jìn)入重定向邏輯,首先需要知道x9是運(yùn)行地址減去鏈接地址得到的偏移地址,那么實(shí)際運(yùn)行地址也等于鏈接地址加上x9,所以add x0, x0, x9,add x4, x4, x9,x0是需要修復(fù)的重定位運(yùn)行地址,x4是實(shí)際運(yùn)行時需要附加的常量值,根據(jù)上面的公式,將x4這個由附加常量值加偏移值得到的運(yùn)行時附加常量值寫入到x0這個運(yùn)行時重定向地址即可完成整個重定向修復(fù)功能。
此處沒有實(shí)際代碼或者流程圖展示,邏輯比較繞,大致邏輯就是根據(jù)重定向段中每24個字節(jié)組成的一個表讀取出實(shí)際需要進(jìn)行重定向的地址,將這個地址的運(yùn)行地址找出來并往這個地址寫入附加常量值加偏移值即可完成一次重定向。在完成段中所有重定向后此時地址已經(jīng)被修復(fù)好了,后續(xù)調(diào)用任何絕對地址引用的指令也不會出問題了。當(dāng)然這個操作是耗時的,一般也不會有board會開啟此功能。
-
ARM
+關(guān)注
關(guān)注
134文章
9169瀏覽量
369247 -
Uboot
+關(guān)注
關(guān)注
4文章
125瀏覽量
28350 -
ARMv8
+關(guān)注
關(guān)注
1文章
35瀏覽量
14195
發(fā)布評論請先 登錄
相關(guān)推薦
操作系統(tǒng)中的邏輯地址和物理地址
uboot的重定位與搬移地址沖突
重定位與鏈接腳本的使用方法
ARM裸機(jī)篇(三)——重定位和地址無關(guān)碼
ARM裸機(jī)重定位的目的是什么?如何實(shí)現(xiàn)
ARM為什么需要重定位?如何去實(shí)現(xiàn)呢
IP地址及網(wǎng)卡MAC地址操作指南
IP地址,IP地址是什么意思
ATM地址,ATM地址是什么意思
虛擬地址翻譯物理地址的流程有哪些呢?
![虛擬<b class='flag-5'>地址</b>翻譯物理<b class='flag-5'>地址</b>的流程有哪些呢?](https://file1.elecfans.com/web2/M00/90/66/wKgaomTZkmaAE7HrAAApSCM4cBA292.png)
IP地址定位與GPS定位:技術(shù)解析與應(yīng)用比較
MAC地址的作用范圍,MAC地址怎么申請?
![MAC<b class='flag-5'>地址</b>的作用范圍,MAC<b class='flag-5'>地址</b>怎么申請?](https://file1.elecfans.com/web2/M00/C6/E0/wKgaomYD42aAX09IAAAbd7WOV8g618.png)
評論