程式的鏈結 符號解析

2022-08-14 13:03:11 字數 2605 閱讀 9960

首先,從程式到可執行程式要經過如下幾個步驟:

在彙編結束之後,就已經生成了二進位制的可執行檔案。這次我們主要介紹符號解析這一步。

符號解析

符號解析將每個模組中引用的符號(符號引用)與某個目標模組的定義符號(符號定義)建立關聯

簡單理解就是比如在某處呼叫了乙個函式fun()。這個fun就可以看做是其符號引用,fun函式的定義可以看做是符號定義。然後符號解析就是把這個符號引用fun與他的函式定義(符號定義)連線起來,也就是建立起乙個對映關係,用符號表來記錄這個對映關係。

為什麼呢?因為每個定義符號在**段(函式)和資料段(變數)都分配了儲存空間,這樣經過符號解析之後

看乙個例子:

main.c

int a[3] = ;

void fun1()

int main()

gcc -c main.c -o main.o

生成可重定位檔案

然後用readelf -s main.o

看到符號表如下:

可以看到main函式的節數也就是ndx 就是1說明他是在可重定位檔案的第一節,以及fun1函式也是在1,這就是有符號定義的符號,對比來看fun符號ndx是und就是undefine,就是沒有定義的意思。fun1 fun main這幾個符號的作用域都是全域性作用域

強符號,弱符號

強符號:有函式的定義函式名和已初始化的全域性變數名

弱符號:沒有函式的定義的函式宣告以及未初始化的全域性變數名

很好理解:

test1.c

int a;//弱符號

int b = 1;//強符號

void p();//弱符號

void fun()

int main()

弱乙個符號被定義為一次強符號和多次若符號,則按強定義為準objcopy

有乙個objcopy命令就非常有意思了:

objcopy [option] [infile] [outfile]

他有乙個選項:-w

-w symbolname, --weaken-symbol=symbolname

將指定符號變為弱符號。該選項可以多次指定

-w能幹什麼呢?可以在不被別人發現的情況下(也就是不該別人的源**),將別人的函式偷換成你的實現。這種技術有時候在公司的專案會用到,這樣可以避免修改太多源**,要做的是寫乙個shell指令碼檔案就行了。

我們只要把函式原來的符號定義(原來的強符號)弱化即可,這樣這個函式的所有符號引用(弱符號)就會以我們自己寫的符號定義(強符號)為準。

舉個例子:

源** main.c

#include void f1()

int main()

我想講f1的函式實現給換掉,我就可以寫乙個swap.c

#include void f1()
然後操作他們的.o檔案 對符號引用做手腳

gcc -c main.c -o main.o

gcc -c swap.c -o swap.o

objcopy -w f1 main.o
gcc main.o swap.o  -o main
執行可執行檔案

會輸出this is my f1.

說明函式定義已經被替換.

他還有以下功能:

--redefine-sym old=new

變更符號名稱。當鏈結兩個目標檔案產生符號名稱衝突時,可以使用該選項來解決

可以直接修改符號引用,這個功能順路介紹一下,因為和符號相關。他可以將乙個函式的符號變更為另乙個符號。

例子:還是main.c,將f1符號定義刪除

int main()
修改swap.c,重新起乙個名字f2.

#include void f2()
直接編譯肯定會出錯,因為f1沒有對應的符號定義,這個時候我們可以在不改變main.c的源**的情況下修改f1的符號為f2

首先:

gcc -c main.c -o main.o

gcc -c swap.c -o swap.o

然後,讓f1符號引用變更為f2

objcopy --redefine-sym f1=f2 main.o
最後鏈結並執行

gcc main.o swap.o -o main

./main

輸出 this is my f

鏈結之符號解析

之前寫過一篇部落格講述了鏈結的來由 這篇部落格則打算講講鏈結的核心工作 符號解析和重定位。看這篇部落格之前可能需要一點基礎,大家可以先看看我上面的鏈結的文章,再來看這篇。什麼是符號解析?符號解析分為區域性符號解析和全域性符號解析,區域性的不用說。全域性符號解析因為多個目標檔案可能會定義相同的名字的全...

鏈結時出現無法解析的外部符號排錯

鏈結時出現 無法解析的外部符號,錯誤資訊 cpp編譯出的符號 batviewdlg.obj error lnk2001 unresolved external symbol unsigned char stdcall getpwrcapabilities struct system power ca...

鏈結器,符號解析與重定位 概念

符號解析。將每個符號引用剛好和乙個符號定義聯絡起來。符號分為四類 匯出符號 export,本地符號 匯入符號 import,外部符號 靜態符號 本地符號 區域性符號 本地符號,不出現在符號表中 匯出符號,在本模組定義,能夠被其他模組引用的符號。非static全域性函式,非static全域性變數。匯入...