前言
鏈接這個操作分爲兩個部分 :
- 符號解析
- 重定位
簡單點說就是找到符號(如何找呢??通過符號表找到) ,然後將正確的地址填上
文章先從符號到符號解
回顧鏈接過程
符號的類型及相關的段
鏈接符號的類型
包括三種類型
- 全局符號 ,裏面還分強弱
- 外部定的全局符號
- 本模塊的局部符號
可以看一下下面的例子
目標文件中的符號表 (.symtab)
符號表是一個 section (段),我們在前面介紹 ELF 段結構的時候是有看到這個段的 , 符號表的結構包含了符號的各種屬性, 什麼類型的, 在哪個地方,多大, 叫什麼名字
全局符號分類
分強弱
符號解析
再介紹符號解析之前我們先介紹一下靜態庫 ,原因是我們現在寫的程序都會用到這東西
什麼是靜態庫
靜態庫的創建
常用的靜態庫
自定義靜態庫
符號解析-解析規則
最終的目標就是將代碼中的地址替換成正確的地址或是數值 ,根據以下的規則進行解析
這個規則有時候在一些複雜的場景會解析出"意想不到的結果" ,看下面的例子
符號解析-解析過程
看目的這一行 , 這一步會將引用符號
和目標模塊的符號
相關聯
下面是解析的過程 , 用了三個集合, 目的就是給引用找到對應的地址 , 注意我們用的實例是上面 自定義靜態庫章節
裏的例子
需要注意的是符號解析還需要注意順序 ,例如 :
額 ,有點不智能吧
重定位
回顧
用到的例子代碼
main.c
int buf[2] = {1, 2};
void swap();
int main()
{
swap();
return 0;
}
swap.c
extern int buf[];
int *bufp0 = &buf[0];
static int *bufp1;
void swap()
{
int temp;
bufp1 = &buf[1];
temp = *bufp0;
*bufp0 = *bufp1;
*bufp1 = temp;
}
重定位表
重定位就是將那些符號定義和符號引用替代掉 ,那麼要去"去代替"這個動作需要知道 ,將要替代的符號在哪裏 ,應該替換成那種類型 ,替代成什麼這些信息 ,而
這些信息就記錄在重定位表中
重定位過程
從上面這張圖我們可以知道 main 長度佔了12個字節.
根據前面的重定位表我們可以看到, 這個地方重定位的類型是相對定位
, 需要替代的符號是 swap
, 相對指的是相對於當前之前的偏移量 . 我們給出一個假設然後推理出一個相對定位的過程
而絕對位置定位就簡單多了, 說白了就是那個符號的地址在哪裏就是那裏
總結
該篇介紹了符號表和符號解析 ,以及重定位相關的知識 ,主要是學習的課件 .
參考
- <<程序員的自我修改--鏈接,裝載與庫>> 書
- mooc上袁春風老師的課