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