鏈接-靜態鏈接

前言

鏈接這個操作分爲兩個部分 :

  • 符號解析
  • 重定位
    簡單點說就是找到符號(如何找呢??通過符號表找到) ,然後將正確的地址填上

文章先從符號到符號解

回顧鏈接過程

img

img

符號的類型及相關的段

鏈接符號的類型

包括三種類型

  • 全局符號 ,裏面還分強弱
  • 外部定的全局符號
  • 本模塊的局部符號
    img

可以看一下下面的例子
img

目標文件中的符號表 (.symtab)

img

符號表是一個 section (段),我們在前面介紹 ELF 段結構的時候是有看到這個段的 , 符號表的結構包含了符號的各種屬性, 什麼類型的, 在哪個地方,多大, 叫什麼名字

img

全局符號分類

img
分強弱

符號解析

再介紹符號解析之前我們先介紹一下靜態庫 ,原因是我們現在寫的程序都會用到這東西

什麼是靜態庫

img

靜態庫的創建

img

常用的靜態庫
img

自定義靜態庫

img

符號解析-解析規則

最終的目標就是將代碼中的地址替換成正確的地址或是數值 ,根據以下的規則進行解析
img

這個規則有時候在一些複雜的場景會解析出"意想不到的結果" ,看下面的例子

img

符號解析-解析過程

img

目的這一行 , 這一步會將引用符號目標模塊的符號相關聯

下面是解析的過程 , 用了三個集合, 目的就是給引用找到對應的地址 , 注意我們用的實例是上面 自定義靜態庫章節裏的例子
img

img

需要注意的是符號解析還需要注意順序 ,例如 :

img

額 ,有點不智能吧

重定位

回顧

img

img

用到的例子代碼

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;
}

重定位表

重定位就是將那些符號定義和符號引用替代掉 ,那麼要去"去代替"這個動作需要知道 ,將要替代的符號在哪裏 ,應該替換成那種類型 ,替代成什麼這些信息 ,而
這些信息就記錄在重定位表中

img

重定位過程

img

從上面這張圖我們可以知道 main 長度佔了12個字節.
根據前面的重定位表我們可以看到, 這個地方重定位的類型是相對定位 , 需要替代的符號是 swap , 相對指的是相對於當前之前的偏移量 . 我們給出一個假設然後推理出一個相對定位的過程

img

img

而絕對位置定位就簡單多了, 說白了就是那個符號的地址在哪裏就是那裏

img

img

總結

該篇介紹了符號表和符號解析 ,以及重定位相關的知識 ,主要是學習的課件 .

參考

  • <<程序員的自我修改--鏈接,裝載與庫>> 書
  • mooc上袁春風老師的課
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章