符號分為四類: 匯出符號(export,本地符號), 匯入符號(import,外部符號), 靜態符號(本地符號), 區域性符號(本地符號,不出現在符號表中)。
匯出符號, 在本模組定義, 能夠被其他模組引用的符號。 非static全域性函式, 非static全域性變數。
匯入符號, 在其他模組定義,被本模組引用的符號。 extern 修飾的全域性非static變數宣告(extern int a), 其他模組的函式引用
靜態符號, 在本模組定義, 只能被本模組引用的符號。 static函式, static全域性變數。
區域性符號, 在函式內部定義的非static變數。不出現在符號表,由棧管理。鏈結器不care這類符號
外部符號(匯入符號): 本模組未定義卻被本模組引用的符號。
彙編器生成可重定位目標檔案後, 內部符號都已被正確地符號解析, 外部符號可能會引用了非本模組的符號定義,彙編器無法找到符號定義, 因此無法解析。 彙編器把外部符號放入」符號表「.symtab,同時把如何解析該符號的方法放入」重定位表「。
使用的表: 符號表
強符號,若符號: 函式和初始化的全域性變數叫強符號, 未初始化的全域性變數叫弱符號。(extern int a是乙個弱符號定義, int a 也是弱符號)
符號解析規則:
1, (定義多個強符號) 當引用符號時,該符號的符號定義有不止乙個強符號定義時,會出現符號重定義錯誤。
2, (定義乙個強符號和乙個或者多個軟符號)當引用符號時, 該符號的符號定義有個強符號定義和乙個和多個弱符號定義, 使用強符號定義。
3, (定義多個弱符號)當引用符號時, 該符號的符號定義都是弱符號時, 選擇任意乙個定義。
使用的表: 重定位表,符號表
重定位表記錄要修改的符號引用的位置,以及如何修改。
一旦鏈結器完成了符號解析這一步,它就把**中的每個符號引用和確定的乙個符號定義聯絡起來。此時,鏈結器就知道了每個模組(檔案)**節和資料節的大小,就可以開始重定位了。
重定位由三步組成:
簡述為, 合併節, 重定位符號定義(修改符號表),重定位符號引用(修改資料段**段)
彙編器遇到對儲存位置未知(在可重定位目標檔案中,彙編器都不知道資料和**會存放在儲存器的什麼位置)的符號引用時,它也會將這些符號的資訊存於.rel.text和.rel.data表中。告訴鏈結器將可重定位目標檔案合併成可執行目標檔案時如何修改符號引用。
鏈結器,符號解析與重定位 概念
符號解析。將每個符號引用剛好和乙個符號定義聯絡起來。符號分為四類 匯出符號 export,本地符號 匯入符號 import,外部符號 靜態符號 本地符號 區域性符號 本地符號,不出現在符號表中 匯出符號,在本模組定義,能夠被其他模組引用的符號。非static全域性函式,非static全域性變數。匯入...
符號解析與重定位
在完成空間與位址的分配步驟之後,鏈結器就進入了符號解析與重定位的步驟,這也就是靜態鏈結的核心作用 在分析符號解析和重定位之前,首先讓我們來看看 a.o 裡面是怎麼使用這兩個外部符號,也就是說我們在 a.c 源程式裡面使用了 shared 變數和 swap 函式,那麼編譯器在將 a.c 編譯成指令時,...
重定位 與 鏈結
動態重定向 現代技術機基本都用這種技術。裝入程式把裝入模組裝入記憶體後,並不會立即把邏輯位址轉換為實體地址,而是把位址轉換推遲到程式真正執行時才發生。這種方式需要乙個重定位暫存器的支援。並且支援換入換出 每次位址會不同 靜態鏈結 將幾個目標模組鏈結裝配成乙個裝入模組時,即將每個模組中所用的外部呼叫符...