理解鏈結時要注意的問題

2021-10-12 10:27:13 字數 1977 閱讀 7418

引言

連線就是將各種**和資料片段收集並組合成為乙個單一檔案的過程,這個檔案可以被載入到記憶體中執行。

編譯器驅動程式

gcc-e可以進行預處理,gcc-c編譯,gcc-s可以產生彙編**。

靜態鏈結與動態鏈結的區別

注意:無論是靜態庫還是動態庫都要把所需的**段載入到記憶體方可執行。

可重定位目標檔案

這裡要注意:.real.text節計入了重定位資訊,一般情況下任何呼叫外部函式或者引用全域性變數的指令都需要計入下來,在重定位之後進行修改;.real.data節任何已初始化的全域性變數或初始值是乙個全域性變數位址或者外部定義函式的位址,都需要先被記錄下來,等到重定位之後修改,這是非常重要的重定位資訊。

符號

這裡根據個人經驗簡單總結一下:由此模組定義並能被其他模組引用的符號就是全域性符號,而由此模組定義並已經被其他模組引用的全域性符號就是外部符號,由此模組定義並只能被此模組引用的符號就是區域性符號,他一般對應於靜態屬性的函式或全域性變數。

如何計算重定位

這裡是本模組的乙個難點,考察的方式有很多,下面我們就來看一下如何來看重定位的組合語言

從此彙編中不難看出有兩種重定位方法:pc相對定位的sum的offset是oxf,addend是-4,array的絕對定位offset是0xa,addend是0。要注意的是絕對引用的offset在絕對引用中是用不到的。

可執行目標檔案

可執行目標檔案的格式類似於可重定位目標檔案,但不完全相同。elf頭包含了檔案的總體格式,程式在執行時要執行的第一條指令的位址。.text、.rodata、.data節已經被重定位到他們最終的執行時的記憶體位址。函式的初始化**會呼叫.init節中的_init。

如何載入可執行目標檔案

程式會通過呼叫execve函式來呼叫載入器,載入器將可執行目標檔案中的**和資料從磁碟中載入到記憶體中,然後跳轉到程式的第一條指令位址來執行該程式。這裡注意:在linux x86-64系統中,**段是從0x400000處開始,接下來是資料段,一直是由下向上增長的。

如何動態來連線共享庫

靜態庫雖好,但有乙個致命的缺陷:隨著功能的擴充套件需要定期維護和更新。二共享庫就可以結束這個缺陷。在執行或載入時,共享庫可以載入到任意記憶體位址,並和乙個在記憶體中的程式連線起來。如上圖,乙個庫只有乙個.so檔案。所有引用該庫的可執行目標檔案共享這個。

我們需要呼叫編譯器驅動程式給編譯器和聯結器指令:linux>gcc -shared -fpic -o libvector.so addvec.c multvec.c

-fpic命令就生成了乙個與位置無關的**,-shared選項指示聯結器建立乙個共享目標檔案,而後給出指令:linux> gcc -o -prog21 main2.c ./libvector.so

這樣就可以建立乙個可執行目標檔案prog21,此檔案就可以使得它在執行時可以和libvector.so連線。此外要注意:

還有特別重要的一點與靜態連線所不同的是當聯結器將控制傳遞給應用程式時,共享庫的位置就固定了,並在此後的程式執行的任何時刻絕不會改變。

企業建站時需要注意的問題

先說一下企業站註冊網域名稱和空間的問題。這方面的問題我遇到過兩個問題。前幾天乙個企業站交給我們團隊進行seo優化,我們在向他們要ftp帳號的時候,他卻告訴我們不知道什麼是ftp帳號。在我們解釋清楚了什麼是ftp帳號之後,他告訴了我乙個非常鬱悶的答案,他的ftp帳號在為他們建站的那個團隊手裡,並且他們...

CString比較時要注意的

最近上班的時候接到乙個需求 1 使用者給定了乙個列表,裡面是一些中英文混雜的字串,標點符號也是混的 比如 序號 名稱 1 1號和a去圖書館 有英文數字 中文 英文小寫 2 和同學b聚會定在 日 有全形數字 中文 英文小寫 3 c的書名是 數學 有中文標點符號 中文 英文大寫 4 jack 是他的名字...

學C 時要注意的

對c 學習的一點感想,希望對初學者能有些幫助 1.如果你以前從來沒有接觸過c 那麼選擇的第一本c 教程就顯得尤為重要,我認為你可以參照以下的標準進行選擇 a.對標準c 進行講解,畢竟c 比從前發生了很大的變化。b.要求全面,但不要很深,這要有助於你對於c 有乙個全面的認識,打好基礎,並且易懂的教材還...