符號引用重定位 重定位PC相對引用 簡單講解

鏈接符號引用重定位

簡介

我們知道一個.c文件可以被編譯爲.o文件,即目標文件,而假如一個.c中引用了別的.c中的函數或者是變量,這時候的.o其實是不知道引用函數實際的內存位置的,也就無法跳轉,這就需要【重定位】的操作了,而針對函數名(也是符號)的重定位

例子

我們編寫兩個.c文件,分別是main.c和func.c,main.c引用了func.c中的func函數

// main.c
int func(int x, int y);

int main()
{
	int c = func(1, 2);
	return 0;
}
// func.c
int func(int x, int y)
{
	return 2*x + y;
}

我們使用gcc來編譯出兩個.o文件,使用如下命令將會生成main.o與func.o

gcc -c main.c func.c

然後我們對main.o與func.o反彙編,使用如下命令可以生成main_dump.txt與func_dump.txt的反彙編文件

objdump -d main.o > main_dump.txt
objdump -d func.o > func_dump.txt

因爲main.c調用func.c而func.c並未調用其他函數,所以我們查看main.o反彙編結果,如下圖藍色區域,因爲在鏈接之前每個.c相對是獨立的,並不知道如何跳轉到其他文件的函數,所以無法正確的寫成跳轉指令
在這裏插入圖片描述
但是我們將兩個.o文件進一步編譯成可執行文件,並查看其反彙編。執行以下命令做進一步的編譯,將main.o和func.o鏈接進而生成exe可執行的二進制文件

gcc -o exe main.o func.o

如圖
在這裏插入圖片描述
我們對exe反彙編,得到exe的彙編代碼

objdump -d exe > exe_dump.txt

發現可以正確的跳轉到func所指定的地址,這是我們想要的,也是鏈接中重定位所做的功勞
在這裏插入圖片描述

重定位條目

簡介

在這裏插入圖片描述
----引用自《深入理解計算機系統》

但是書上講的很抽象,而且沒有例子,接下來簡單解釋以下這些條目中各個符號的意義

offset

因爲在鏈接之前,每個.c相當於一個獨立的部分,我們稱之爲【節】,而offset表明這個符號引用相對於【節】起始處的偏移(其實就是相對地址)

值得注意的是,這個offset指向的是callq指令中需要被修改的操作數,而不是callq指令本身

如圖 main.c 的節
在這裏插入圖片描述

type

是何種重定位方式,因爲編譯的時候可以有很多種重定位方式,但是接下來只討論書上描述的比較難懂的【重定位PC相對引用】

symbol

即這個引用指向的是哪個符號,比如main.c引用func函數那麼就指向func函數

addend

在PC+偏移跳轉計算實際地址時用到的計算偏移,待會會講解

重定位PC相對引用

這裏是書上講的比較晦澀的地方,書上直接給出了公式
在這裏插入圖片描述
這個公式很難懂,但是我們可以翻譯一下。仍然以main.c引用func.c爲例子

符號 意義
ADDR(s) main節在實際的可執行文件中,位於內存的實際地址
ADDR(r.symbol) func函數在實際可執行文件中,位於內存的實際地址
r.offset 上文提到的offset,計算出需要修改的引用的操作數相對main節的偏移
r.addend 上文提到的addend,計算實際callq語句操作數時需要用到的計算偏移

結合exe可執行文件的反彙編代碼,我們進一步理解:
在這裏插入圖片描述
現在再來看這個公式,其中offset爲0x13,根據上面offset定義推得

refaddr            	= ADDR(s)        + r.offset
要修改的引用的實際地址 	= main函數實際地址 + 要修改的引用的相對地址
0x60d				= 0x5fa			 + 0x13

addend是由命令查看精靈 ELF readelf -r main.o查詢得的
在這裏插入圖片描述

*refptr 	= ADDR(r.symbol) + r.addend - refaddr
修改後的內容x	= func函數實際地址 + 計算偏移 	- 要修改的引用的實際地址
0xa			= 0x61b			 + -0x4		- 0x60d

注:
因爲是【PC+偏移】尋址,修改後的內容x就是call的操作數
要想使跳轉到func函數,就需要【PC+x = func函數實際地址】
PC + 0xa = 0x611 + 0xa = 0x61b 確實是func函數的地址,達到效果

可以看到編譯後的結果,也就是鏈接的時候修改後的結果,確實是0xa(小端表示牢記於心)
在這裏插入圖片描述
現在再看書上的公式是否變簡單了?
在這裏插入圖片描述
在這裏插入圖片描述

重定位PC絕對引用

這個簡單,沒有那麼多做差和偏移,直接將實際的func函數的地址賦值給操作數,但是一般用於外部變量數據的引用中

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