《程序員的自我修養》--靜態鏈接

空間分配

例子

/*a.c*/
extern int shared;
int main()
{
    int a = 100;
    swap(&a,&shared);
    return 0;
}
/*b.c*/
int shared = 1;
void swap(int *a,int *b)
{
    int temp;
    temp = (*a);
    (*a) = (*b);
    (*b) = temp;
}
/*編譯步驟*/
gcc -c a.c b.c

下面進行空間分配

A 按序疊加
這裏寫圖片描述

B 相似段合併

這裏寫圖片描述

兩步鏈接法
1 掃描輸入文件,得到段屬性,收集符號定義和引用,放到全局符號表,鏈接器得到每一個目標文件的段長,計算輸出文件的合併段長和位置,建立映射關係。
2 讀取文件中段數據和重定位信息,進行符號解析,重定位,和調整代碼中地址。

重定位和符號解析

在其他目標文件中定義的變量或者函數(通稱符號),編譯器會把他們的地址暫時以0x00000000和0xFFFFFFFC代替,真正的計算過程則交給了鏈接器。鏈接器完成空間和地址的分配之後可以確定所有符號的虛擬地址,根據虛擬地址,對每一個需要重定位的指令修改。
需要重定位的指令: 這裏會有一個重定位表,或稱重定位段,加入代碼段有序喲重定位的指令,則會有相應的.rel.data段。
重定位表的結構:

typedef struct {
    Elf32_Addr r_offset;//修正位置第一個字節相對於段的偏移
    Elf32_Word r_info;//重定位入口符號和類型
}Elf32_Rel; 

靜態庫簡述

出現原因:零散的目標文件提供給使用者,會有文件傳輸管理等不便,把這些目標文件壓縮在一起,便於查找,形成libc.a靜態庫文件。
比如:
這裏寫圖片描述

以下是通過解壓printf.o得來的編譯過程:
這裏寫圖片描述
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章