了解动态链接(六)—— 重定位表
柳條青青,南風(fēng)熏熏,幻化奇峰瑤島,一天的黃云白云,那邊麥浪中間,有農(nóng)婦笑語殷殷。問后園豌豆肥否,問楊梅可有鳥來偷;好幾天不下雨了,玫瑰花還未曾紅透;梅夫人今天進(jìn)城去,且看她有新聞無有。——?徐志摩·夏日田間即景
ilocker:關(guān)注 Android 安全(新入行,0基礎(chǔ)) QQ: 2597294287
無論是可執(zhí)行文件還是 so,只要它依賴于其他 so(.dynsym 動態(tài)符號表中有導(dǎo)入符號存在),那么在編譯鏈接階段,這些符號的地址未知,所以只能在動態(tài)鏈接階段對其進(jìn)行地址重定位。
注意:以 PIC 編譯的 so,雖然稱“地址無關(guān)代碼”,但也需要重定位。因?yàn)閷τ?PIC 的 so 來說,只不過是把代碼中的絕對地址提出來,放到了數(shù)據(jù)段的 GOT 表中。所以,雖然代碼段不需重定位,但數(shù)據(jù)段的 GOT 表需要重定位。(以 PIC 編譯 so,是為了復(fù)用 so 的代碼段)
以 android liblog.so 為例。在代碼中調(diào)用 memset 時,實(shí)際上會跳轉(zhuǎn)到標(biāo)號 memset_ptr 指向的內(nèi)存。
?
而標(biāo)號 memset_ptr 指向的內(nèi)存就定義在 GOT 表中:
?
那么如何為 GOT 表做重定位呢?GOT 表中的每一項應(yīng)該指向哪一個符號在內(nèi)存中的地址呢?這些信息就由重定位表來描述。具體到 android 來說,重定位表保存在 .rel.dyn 和 .rel.plt 中。
?
從表中可以看出,位于 .rel.dyn 中的主要是 R_ARM_GLOB_DAT 類型的重定位項,而位于 .rel.plt 中的主要是 R_ARM_JUMP_SLOT 類型的重定位項。前者用于對數(shù)據(jù)引用做重定位,而后者用于對函數(shù)引用做重定位。除此之外,還看到了 R_ARM_RELATIVE 類型的重定位。
在 android linker 的源碼中,調(diào)用了兩次 soinfo_relocate 函數(shù),分別為 .rel.dyn 和 .rel.plt 做重定位:
?
在 soinfo_relocate 函數(shù)的源碼中可以看到,對于不同類型的重定位,計算符號地址的方式也有所不同。
?
實(shí)際上對于 R_ARM_GLOB_DAT、R_ARM_JUMP_SLOT 這兩種重定位類型來說,只需將符號地址填入被修正的內(nèi)存即可。而 R_ARM_RELATIVE 類型看起來特殊些,它的作用是進(jìn)行基址重置 (Rebasing) 。
比如指針 p 指向靜態(tài)變量 a,而靜態(tài)變量 a 相對于 so 基址的偏移為 A。在編譯時,so 的基址為 0,此時 p 的值為 A。而當(dāng) so 被裝載到內(nèi)存中時,p 的值就需要加上一個 so 在內(nèi)存中的基址 base。R_ARM_RELATIVE 類型的重定位就是用來干這個的。
對于 android linker 的重定位細(xì)節(jié),以及其他重定位類型,在后面寫 android linker 源碼分析筆記時再描述。
學(xué)習(xí)資料: 《程序員的自我修養(yǎng)——鏈接、裝載和庫》
轉(zhuǎn)載于:https://www.cnblogs.com/ilocker/p/4641769.html
總結(jié)
以上是生活随笔為你收集整理的了解动态链接(六)—— 重定位表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php5.3连接sqlserver200
- 下一篇: NPOI封装