空間分配
例子:
/*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得來的編譯過程: