********
本文檔介紹GNU連接器ld的2.14版本.

本文檔在GNU自由文檔許可證下發行.在"GNU自由文檔許可證"一章中有關於本許可證的一份拷貝.

概述
********

'ld'把一定量的目標檔跟檔案檔連接起來,並重定位它們的資料,連接符號引用.一般,在編譯一個程式
時,最後一步就是運行'ld'.

'ld'能接受連接命令語言檔,這是一種用AT&T的連接編輯命令語言的超集合寫成的檔,用來在連接的整個
過程中提供顯式的,全局的控制.

本版本的'ld'使用通用BFD庫來操作目標檔.這就允許'ld'讀取,合併,寫入目標檔時,可以使用各種不同的格式,比如,COFF或'a.out'. 不同的格式可以被連接到一起產生一個有效的目標檔.

除了它的靈活性,GNU連接器比其他連接器更有用的地方在於它提供了診斷資訊. 許多連接器在碰到一個錯誤
的時候立即放棄執行;但'ld'卻能夠繼續執行,以讓你發現其他的錯誤(或者,在某些情況下,得到一個帶有錯誤
的輸出檔)

引用
**********

GNU連接器'ld'能夠處理大量的不同情況,並且跟其他的連接器保持盡可能的相容.這樣,你就擁有更多的選擇來
控制它的行為.

命令行選項
====================

連接器提供大量的命令行選項,但是,在實際使用中,只有少數被經常使用.比如,'ld'的一個經常的使用場合是在
一個標準的Unix系統上連接標準的Unix目標檔.在這樣的一個系統上,連接檔'hello.o'如下:

ld -o OUTPUT /lib/crt0.o hello.o -lc

這告訴'ld'產生一個叫OUTPUT的檔,作為連接檔'/lib/crt0.o'和'hello.o'和庫'libc.a'的結果.'libc.a'
來自標準的搜索路徑.(參閱下文的關於'-l'選項的討論).

有些命令行選項可以在命令行的任何位置出現.但是,那些帶有檔案名的選項,比如'-l'或者'-T',會讓檔在選
項出現的位置上被讀取. 對於非檔選項,以帶不同的參數重複它,不會有進一步的效果,或者覆蓋掉前面的相同
項.那些多次出現時具有特殊含義的選項會在下文的描述中指出.

無參數選項是那些被連接的目標檔和檔案檔.它們可能緊隨命令行選項,或在它們前面,或者跟它們夾雜在一
起,但是一個目標檔參數是不會出現在一個選項跟它的參數之間的.

通常,連接器至少引用一個目標檔,但是你可指定其他形式的二進位輸入檔,這可以通過'-l','-R'或者腳本
命令語言來實現.如果沒有任何二進位檔被指定,連接器不會產生任何輸出,並給出資訊:"缺少輸入檔."

如果連接器不能識別目標檔的格式,它會假設這些只是連接腳本.以這種方式指定的腳本增加了連接用的主連
接腳本的內容(主連接腳本即缺省連接腳本或使用'-T'指定的腳本). 這個特性可以允許連接器連接一些檔,
它們看上去既像目標檔,又像檔案檔,但實際上只是定義了一些符號值,或者使用'INPUT'或'GROUP'來載入其
它的目標檔.需要注意的是,用這種方式指定一個腳本只是增加了主連接腳本的內容;要完全替換掉主連接腳本
,需要使用'-T'.

對於名稱是單個字元的選項,選項參數必須緊跟在選項字母後面,中間不留空,或者也可留有一個空格.

對於名稱是多個字元的選項,選項前可以有一個或兩個破折號;比如,'-trace-symbol'和`--trace-symbol'是等價
的. 注意,對於這條規則有一個例外.那些以小寫字母'o'開頭的多字元選項前面只能是兩個破折號,這是為了避免
跟選項'-o'混淆. 比如'-omagic'把輸出檔的名字定為'magic',而'--omagic'在輸出檔中設置NMAGIC標誌.

多字元選項的參數必須跟選項名間以一個等於號分開,或者以一個空格分開.比如:`--trace-symbol foo'和
`--trace-symbol=foo'是等價的. 多字元選項的名字唯一縮寫符也是可以被接受的.

注意,如果連接器通過被編譯器驅動來間接引用(比如gcc), 那所有的連接器命令行選項前必須加上首碼'-Wl'
(或者能被特定編譯器驅動接受的其他首碼),就像下面這樣:

gcc -Wl,--startgroup foo.o bar.o -Wl,--endgroup

這很重要,因為否則的話,編譯器驅動程式會默認丟掉這些連接選項,產生一個錯誤的連接.

下面是關於被GNU連接器接受的常用命令行開關的一個列表:

`-aKEYWORD'
這個選項在HP/UX相容系統上被支援. 參數KEYWORD必須是下面字串中的一個:`archive',
`shared', or `default'. `-aarchive'在功能上跟`-Bstatic'相同,而另外兩個關鍵字功能上跟
`-Bdynamic'相同. 這個選項可被多次使用.

`-AARCHITECTURE'
`--architecture=ARCHITECTURE'
在最近發行版本的'ld'中,這個選項只在Intel 960系列架構上有用. 在那種'ld'配置中,參數
ARCHITECTURE確定960系列的某一特定架構,啟用某些安全措施,並修改檔案庫的搜索路徑.

將來的'ld'發行版可能為其他架構系列支援相似的功能.

`-b INPUT-formAT'
`--format=INPUT-formAT'
'ld'可以被配置為支援多於一種的目標檔.如果你的'ld'以這種方式被配置,你可以使用'-b'選
項為輸入目標檔指定二進位格式. 就算'ld'被配置為支援可選目標格式,你不必經常指定這一項,
因為'ld'被配置為在每一台機子上把最常用的格式作為默認輸入格式. INPUT-formAT是一個字串,

你可能在連接一個不常用的二進位格式檔時需要這個參數.你也可使用'-b'來顯式切換格式(在連接
不同格式的目標檔時),方法是在每一組特定格式的目標前使用'-b INPUT-formAT'.

缺省的格式是從環境變數'GNUTARGET'中得到的.你也可以從一個腳本中定義輸入格式,使用的命令是
'TARGET'.

`-c MRI-COMMANDFILE'
`--mri-script=MRI-COMMANDFILE'
為了跟MRI生產的連接器相容,'ld'接受另一種用受限命令語言寫成的腳本檔,通過選項'-c'引入MRI
腳本文件;使用'-T'選項是運行用普通'ld'腳本語言寫的連接腳本.如果MRI-CMDFILE不存在,'ld'在'-L'
指定的目錄中尋找.

`-d'
`-dc'
`-dp'
這三個選項是等價的; 多字元形式是為了跟其他連接器相容才被支持的.它們給普通符號分配空間,即
使一個重定位輸出檔已經被指定(通過'-r'). 腳本命令`FORCE_COMMON_ALLOCATION'具有同樣的效果.

`-e ENTRY'
`--entry=ENTRY'
使用符號ENTRY作為你的程式的開始執行點,而不是使用缺省的進入點.如果沒有叫做ENTRY的符號,連接器
會企圖把ENTRY作為一個數字進行分析,並使用它作為入口位址(數位會被解釋為10進制的;你可以使用前
導的'0x'強制為16進制,或'0'作為8進制.)

`-E'
`--export-dynamic'
當創建一個動態連接的可執行程式時, 把所有的符號加到動態符號表中.動態符號表是一個符號集,這
些符號對於運行時的動態物件是可見的.

如果你不使用這個選項,動態符號表中就會只含有那些連接進來的動態物件中用到的符號

如果你使用'dlopen'來載入動態物件,它需要引用程式中的符號,那你可能需要在連接程式時用到這個
選項.

你也可以使用版本腳本來控制哪些符號應當被加到動態符號表中.

`-EB'
連接big-endian物件. 這會影響缺省輸出格式.

`-EL'
連接little-endian物件. 這會影響缺省輸出格式.

`-g'
忽略. 為了跟其他工具相容而提供.

`-i'
執行一個增量連接(跟'-r'等同)

`-init NAME'
當創建一個ELF可執行檔或共用物件時,當可執行檔或共用物件被載入時,調用NAME, 這是通過把
DT_INIT設置成函數的位址實現的. 缺省情況下,連接器使用'_init'作為調用的函數.

`-lARCHIVE'
`--library=ARCHIVE'
增加一個檔案檔ARCHIVE到連接的檔列表中.這個選項可以被多次使用. 'ld'會為每一個指定的
ARCHIVE搜索它的路徑列表,尋找`libARCHIVE.a'

對於支援共用庫的系統, 'ld'可能還會搜索副檔名不是'.a'庫.特別的,在ELF和SunOS系統上,'ld'會
在搜索帶有'.a'副檔名的庫前搜索帶'.so'副檔名的庫.

`-M'
`--print-map'
列印一個連接點陣圖到標準輸出.一個連接點陣圖提供的關於連接的資訊有如下一些:

* 目標檔和符號被映射到記憶體的哪些地方.

* 普通符號如何被分配空間.

* 所有被連接進來的檔案檔,還有導致檔案檔被包含進來的那個符號.

`-n'
`--nmagic'
關閉所有節的頁對齊,如果可能,把輸出格式標識為'NMAGIC'.

`-N'
`--omagic'
把text和data節設置為可讀寫.同時,取消資料節的頁對齊,同時,取消對共用庫的連接.如果輸出格式
支援Unix風格的magic number, 把輸出標誌為'OMAGIC'.

`--no-omagic'
這個選項執行的操作大部分正好跟'-N'相反.它設置text節唯讀,強制data節頁對齊. 但是,這個選項
並不開啟連接共用庫的功能. 使用'-Bdynamic'開啟這個功能.

`-o OUTPUT'
`--output=OUTPUT'
使用OUTPUT作為'ld'產生的程式的名字;如果這個選項沒有指定,缺省的輸出檔案名是'a.out'.腳本命
令'OUTPUT'也可以被用來指定輸出檔的檔案名.

`-O LEVEL'
如果LEVEL是一個比0大的數值, 'ld'優化輸出.這可能會明顯多佔用時間,所以只有在生成最後的檔
時使用.

`-q'
`--emit-relocs'
把重定位節和內容留在完全連接後的可執行檔中. 連接分析和優化工具可能需要這些資訊用來進行
正確的修改與執行. 這在大的可執行檔中有用.

這個選項目前只支援ELF平臺.
`-r'
`--relocateable'
產生可重定位的輸出, 比如,產生一個輸出檔它可再次作為'ld'的輸入.這經常被叫做"部分連接".
作為一個副作用,在支持標準Unix魔數的環境中,這個選項會把輸出檔的魔數設置為'OMAGIC'. 如
果這個選項沒有被指定,一個絕對檔就會被產生.當連接C++程式時,這個選項就不會解析構造函數的
引用;要解析,必須使用'-Ur'

如果輸入檔跟輸出檔的格式不同,只有在輸入檔不含有重定位資訊的時候部分連接才被支援.輸
出格式不同的時候會有更多的限制.比如,有些'a.out'的格式在輸入檔是其他格式的時候完全不支
持部分連接.

這個選項跟'-i'等效.

`-R FILENAME'
`--just-symbols=FILENAME'
從FILENAME中讀取符號名跟它們的值,但不重位這個檔,或者根本不把它包含在輸出檔中.這就允
許你的輸出檔引用其他程式中定義的絕對記憶體位址.你可以多次使用這個選項.

為了跟其他ELF連接器相容,如果'-R'選項後面跟有一個目錄名,而不是一個檔案名,它會被處理成
'-rpath'選項.

`-s'
`--strip-all'
忽略輸出檔中所有的符號資訊.

`-S'
`--strip-debug'
忽略輸出檔中所有的調試符號資訊(但不是所有符號).

`-t'
`--trace'
列印'ld'處理的所有輸入檔的名字.

`-T SCRIPTFILE'
`--script=SCRIPTFILE'
把SCRIPTFILE作為連接腳本使用. 這個腳本會替代'ld'的缺省連接腳本(而不是增加它的內容),所以
命令檔必須指定所有需要的東西以精確描述輸出檔. 如果SCRIPTFILE在當前目錄下不存在,'ld'
會在'-L'選項指定的所有目錄下去尋找.多個'-T'選項會使內容累積.

`-u SYMBOL'
`--undefined=SYMBOL'
強制SYMBOL在輸出檔中作為一個無定義的符號被輸入.這樣做會有一些效果,比如,會引發從標準庫
中連接更多的模組. '-u'可以以不同的參數反復使用,以輸入多個無定義的符號.這個選項跟連接腳
本命令中的'EXTERN'是等效的.

`-Ur'
對於不是C++的程式,這個選項跟'-r'是等效的: 它產生可重定位的輸出,比如,一個輸出檔它可以再
次作為'ld'的輸入. 當連接C++程式時,'-Ur'解析構造函數的引用,跟'-r'不同. 但如果在一些用'-Ur'
連接過的文件上再次使用'-Ur',它不會工作,因為一旦構造函數表被建立,它不能被添加內容.請只在
最後一遍連接的時候使用'-Ur', 對其他的,只使用'-r'.

`--unique[=SECTION]'
對於所有匹配SECTION的輸入節,在輸出檔中都各自創建單獨的節,或者,如果可選的通配符SECTION
參數丟失了,為每一個孤兒輸入節創建一個輸出節. 一個孤兒節是一個連接腳本中沒有指定的節.你
可以在命令行上多次使用這個選項; 它阻止對同名輸入節的合併,在連接腳本中重載輸出節分配.

`-v'
`--version'
`-V'
顯示'ld'的版本. '-V'選項同時會列出支援的模擬器.

`-x'
`--discard-all'
刪除所有的本地符號.

`-X'
`--discard-locals'
刪除所有的臨時本地符號.對於大多數目標平臺,就是所有的名字以'L'開頭的本地符號.

`-y SYMBOL'
`--trace-symbol=SYMBOL'
列印出所有SYMBOL出現的被連接檔的名字. 這個選項可以被多次使用. 在很多系統中,這在預先確定底
線時很有必要.

當你擁有一個未定義的符號,但不知道這個引用出自哪里的時候,這個選項很有用.

`-Y PATH'
為缺省的庫搜索路徑增加一條路徑.這個選項是為了跟Solaris相容.

`-z KEYWORD'
能被識別的關鍵字包括'initfirst', 'interpose', 'loadfltr',`nodefaultlib', `nodelete',
`nodlopen', `nodump', `now', `origin',`combreloc', `nocombreloc' and `nocopyreloc'. 為了跟
Solaris相容,所有其他的關鍵字都被忽略. 'initfirst'標誌一個物件,使它在運行時,在所有其他物件之
前被初始化. 'interpose'標誌一個物件,使它的符號表放在所有其他符號之前,作為主要的執行者.
'loadfltr'標誌一個物件, 使它的篩檢程式在運行時立即被處理.'nodefaultlib'標誌一個物件,使在搜索
本物件所依賴的庫時,忽略所有缺省庫搜索路徑. 'nodelete'標誌一個物件,使它在運行時不會被從記憶體
中刪除.'nodlopen'標誌一個物件,使這個物件不可以通過'dlopen'載入.'nodump'標誌一個物件,使它不能
被'dldump'轉儲. 'now'標誌一個物件,使它成為非懶惰運行時綁定對象. 'origin'標誌一些可能含有
$ORIGIN的物件,'defs'不允許無定義符號. 'muldefs'允許重定義. 'comberloc'組合多個重定位節,重新
排布它們,讓動態符號可見. 'nocomberloc'使多個重定位節組合無效. 'nocopyreloc'使重定位拷貝後的
結果無效.

`-( ARCHIVES -)'
`--start-group ARCHIVES --end-group'
ARCHIVES應當是一個關於檔案檔的列表. 它們可以是顯式的檔案名,或者'-l'選項.

這些指定的檔案檔會被多遍搜索,直到沒有新的無定義引用被創建. 通常,一個檔案檔只會被搜索一
次. 但如果這個檔案檔中的一個符號需要被用來解析一個檔案中的目標引用到的無定義的符號,而這個
符號在命令行上的後面某個檔案檔中出現, 連接器不能解析這個引用. 把這些檔案檔分組後,它們都
可被反復搜索直到所有可能的引用都被解析了為止.

使用這個選項有一個很大的運行開銷. 只有在無法避免在多個檔案檔中使用迴圈引用時才用它.

`--accept-unknown-input-arch'
`--no-accept-unknown-input-arch'
告訴連接器接受那些架構不能被識別的輸入檔. 但前提假設是用戶知道他們在做什麼,並且是故意要連
接這些未知的輸入檔. 在版本2.14之前,這個是連接器的缺省行為. 從版本2.14以後的,缺省行為是拒
絕這類輸入檔, 所以`--accept-unknown-input-arch'選項被用來恢復舊的行為.

`-assert KEYWORD'
這個選項被忽略,只是用來跟SunOS保持相容.

`-Bdynamic'
`-dy'
`-call_shared'
連接動態連結程式庫. 這個僅僅在支持共用庫的平臺上有用.在這些平臺上,這個選項通常是默認行為. 這個選
項的不同形式是為了跟不同的系統保持相容. 你可以在命令行上多次使用這個選項:它影響緊隨其後的'-l'
選項的庫搜索.

`-Bgroup'
在動態節的'DT_FLAGS_1'入口上設置'DF_1_GROUP'標誌.這會讓運行時連接器在處理在這個物件和它的相
關部分搜索時只在組中. '--no-undefined'是隱式的. 這個選項只在支援共用庫的ELF平臺上有用.

`-Bstatic'
`-dn'
`-non_shared'
`-static'
不連接共用庫. 這個僅僅在支持共用庫的平臺上有用. 這個選項的不同形式是為了跟不同的系統保持兼
容. 你可以在命令行上多次使用這個選項:它影響緊隨其後的'-l'選項的庫搜索.

`-Bsymbolic'
當創建一個共用庫時, 把對全局符號的引用綁定到共用庫中的定義(如果有), 通常, 一個連接共用庫的程
序重載共用庫中的定義是可能的. 這個選項只在支援共用庫的ELF平臺上有用.

`--check-sections'
`--no-check-sections'
讓連接器在節位址被分配後不要去檢查節地址是否重疊.通常,連接器會執行這種檢查,如果它發現了任何
重疊,它會產生相應的錯誤資訊. 連接器知道也允許節的重疊. 缺省的行為可以使用命令行開關
`--check-sections'來恢復.

`--cref'
輸出一個交叉引用表. 如果一個連接器點陣圖檔被產生, 交叉引用表被列印到點陣圖檔. 否則, 它被列印
到標準輸出.

表的格式相當的簡單, 所以,如果需要,可以通過一個腳本很輕易地處理它. 符號是以名字被列印輸出,存
儲. 對於每一個符號,給出一個檔案名列表. 如果符號被定義了, 列出的第一個檔是符號定義的所在.
接下來的檔包含符號的引用.

`--no-define-common'
這個選項限制對普通符號的位址分配. 腳本命令`INHIBIT_COMMON_ALLOCATION'具有同等的效果.

`--no-define-common'選項允許從輸出檔的類型選擇中確定對普通符號的位址分配; 否則, 一個非重定
位元輸出類型強制為普通符號分配位址. 使用'--no-define-common'允許那些從共用庫中引用的普通符號只
在主程序中被分配地址. 這會消除在共用庫中的無用的副本的空間, 同時,也防止了在有多個指定了搜索
路徑的動態模組在進行運行時符號解析時引起的混亂.

`--defsym SYMBOL=EXPRESSION'
在輸出檔中建立一個全局符號,這個符號擁有一個EXPRESSION指定的絕對位址. 你可以多次使用這個選
項定義多個符號. EXPRESSION支持一個受限形式的算術運算:你可以給出一個十六進位常數或者一個已存
在符號的名字,或者使用'+'和'-'來加或減十六進位常數或符號. 如果你需要更多的運算式,可以考慮在腳
本中使用連接器命令語言, 注意在SYMBOL,=和EXPRESSION之間不允許有空格.

`--demangle[=style]'
`--no-demangle'
這些選項控制是否在錯誤資訊和其他的輸出中重組符號名. 當連接器被告知要重組, 它會試圖把符號名以
一種可讀的形式的展現: 如果符號被以目標檔格式使用,它剝去前導的下劃線,並且把C++形式的符號名
轉換成用戶可讀的名字. 不同的編譯器有不同的重組形式. 可選的重組形式參數可以被用來為你的編譯器
選擇一個相應的重組形式. 連接器會以缺省形式重組直至環境變數`COLLECT_NO_DEMANGLE'被設置. 這些
選項可以被用來重載缺省的設置.

`--dynamic-linker FILE'
設置動態連接器的名字. 這個只在產生動態連接的ELF可執行檔時有效. 缺省的動態連接器通常是正確
的; 除非你知道你在幹什麼,不要使用這個選項.

`--embedded-relocs'
這個選項只在連接MIPS嵌入式PIC代碼時有效, 這些代碼必須是由GNU的編譯器跟彙編器通過-membedded-pic
選項生成的. 它導致連接器產生一個表,這個表被用來在運行時重定位所有的被靜態初始化為指標值的數
據.

`--fatal-warnings'
把所有的警告視為錯誤.

`--force-exe-suffix'
確保輸出檔有一個.exe尾碼.

如果一個被成功完整連接的輸出檔不帶有一個'.exe'或'.dll'尾碼, 這個選項確保連接器把輸出檔
拷貝成帶有'.exe'尾碼的同名檔. 這個選項在使用微軟系統來編譯未經修改的Unix的makefile時很有
用, 因為有些版本的windows不會運行一個不帶有'.exe'尾碼的映射.

`--no-gc-sections'
`--gc-sections'
允許對未使用的輸入節的碎片收集. 在不支援這個選項的平臺上,被忽略. 這個選項不能跟 '-r'選項共存
也不能被用來進行動態連接. 缺省行為可以用`--no-gc-sections'進行恢復.

`--help'
在標準輸出上列印一個命令行選項概要,然後退出.

`--target-help'
列印一個所有目標平臺相關的選項的概要,然後退出.

`-Map MAPFILE'
列印一個連接點陣圖到檔MAPFILE中. 參閱上面關於'-M'選項的描述.

`--no-keep-memory'
'ld'通常會以速度優先於記憶體使用的方式優化程式,這是通過把輸入檔的符號表放在記憶體緩衝中實現的,
這個選項告訴'ld'以記憶體使用優先來優化, 盡可能的減小符號表的重讀. 這在'ld'在連接一個大檔時
超出記憶體限制時有用.

`--no-undefined'
`-z defs'
通常,當創建一個非符號共用庫時, 無定義的符號允許出現,並留待運行時連接器去解決. 這個選項關閉這
樣的無定義符號的使用. 開關`--no-allow-shlib-undefined'控制共用物件被連接進共用庫時的行為.

`--allow-multiple-definition'
`-z muldefs'
通常,當一個符號被定義多次時, 連接器會報告一個致命錯誤. 這些選項允許重定義並且第一個定義被使



`--allow-shlib-undefined'
`--no-allow-shlib-undefined'
允許(缺省)或不允許無定義符號存在於共用物件中. 這個開關的設置會重載'--no-undefined',這裏只關
注共用物件. 這樣,如果'--no-undefined'被設置,但'--no-allow-shlib-undefined'未被設置, 連鎖反應
是存在於規則物件檔中的無定義的符號會引起一個錯誤,但是在共用物件中的未定義的符號會被忽略.

把`--allow-shlib-undefined'設置為缺省的原因是在連接時指定的共用物件並不一定是載入時可載入的
那個,所以,符號可能要到載入時間才被解析.

`--no-undefined-version'
通常當一個符號有一個未定義的版本時,連接器會忽略它. 這個選項不允許符號有未定義的版本,並且碰
到這種情況,會報告一個嚴重錯誤.

`--no-warn-mismatch'
通常, 如果你因為一些原因,企圖把一些不匹配的輸入文件連接起來的時候,'ld'會給出一個錯誤,可能這
些檔是因為由不同的處理器編譯. 這個選項告訴'ld'應當對這樣的錯誤默認允許. 這個選項必須小心
使用.

`--no-whole-archive'
為後面的檔案檔關閉'--whole-archive'選項的影響.

`--noinhibit-exec'
當一個可執行檔還可以使用時,就保留它. 通常,連接器如果在連接過程中遇到了錯誤,就不會產生輸出
文件;當它遇上錯誤時,它會退出而不寫輸出檔.

`-nostdlib'
僅搜索那些在命令行上顯式指定的庫路徑. 在連接腳本中(包含在命令行上指定的連接腳本)指定的庫路
徑都被忽略.

`--oformat OUTPUT-formAT'
'ld'可以被配置為支援多於一種的目標檔. 如果你的'ld'以這種方式被配置,你可以使用'--oformat'
選項來指定輸出目標檔的二進位格式.就算'ld'被配置為支援多種目標格式,你也不必指定這個項,因
為'ld'應當被配置為把最常用的輸出格式作為默認格式. OUTPUT-formAT是一個文本串,是被BFD庫支持
的一個特定格式的名字.腳本命令'OUTPUT_formAT'也可以指定輸出格式,但這個選項可以覆蓋它.

`-qmagic'
這個選項被忽略,只是為了跟Linux保持相容.

`-Qy'
這個選項被忽略,只是為了跟SVR4保持相容.

`--relax'
一個機器相關的選項. 只有在少數平臺上,這個選項被支援.

在某些平臺上,'--relax'選項在連接器解析程式中的位址時執行可能的全局優化, 比如鬆散位址模式和在輸出檔
中合成新的指令.

在某些平臺上,連接時全局優化會進行符號調試導致程式不能運行.

在不支援這個選項的平臺上,'--relax'被接受,但被忽略.

`--retain-symbols-file FILENAME'
只保留在FILENAME中列出的那些符號,丟棄所有其他的. FILENAME是一個簡單地平坦模式檔, 一個符號占一行.
這個選項在那些會逐步積累起一個大的全局符號表的系統中(比如 VxWorks)會很有用,它能有效地節約記憶體空間.

'--retain-symbols-file'不丟棄未定義的符號,和需要重定位的符號.

你可能在命令行上只指定'--retain-symbol-file'一次, 它覆蓋'-s'和'-S'的功能.

`-rpath DIR'
為運行時庫的搜索路徑增加一個目錄. 這個在連接帶有共用庫的ELF可執行檔時有用. '-rpath'的所有參數會被
連接起來傳遞給運行時連接器, 運行時連接器在運行時用它們定位共用物件. '-rpath'選項在定位那些在連接參數
指定的共用物件需要的共用物件時也很有用; 參閱關於'-rpath-link'選項的描述, 如果在連接一個ELF可執行檔
時不使用'-rpath'選項,那些環境變數'LD_RUN_PATH'選項就會被使用.

'-rptah'選項也可以使用在SunOS上. 缺省地,在SunOS上,連接器會從所有的'-L'選項中形成一個運行時搜索路徑.
如果使用了'-rpath'選項, 那運行時搜索路徑就只從'-rpath'選項中得到, 忽略'-L'選項. 這在使用GCC時非常有
用, 它會用上很多的'-L'選項,而這些路徑很可能就是NFS掛上去的檔系統中.

為了同ELF的連接器相容, 如果'-R'選面後面跟有一個目錄名, 而不是一個檔案名,那它也會被處理成'-rpath'選
項.

`-rpath-link DIR'
當在SunOS上使用ELF時,一個共用庫可能會用到另一個共用庫. 當'ld -share'把一個共用庫作為一個輸入檔連接
時就有可能發生這種情況.

當一個連接器在作非共用,不可重定位連接時,如果遇上這種依賴情況,它會自動定位需要的共用庫,然後把它包含在
連接中, 如果在這種情況中,它沒有被顯式包含, 那'-rpath-link'選項指定優先搜索的一組路徑名.

這個選項必須小心使用,因為它會覆蓋那些可能已經被編譯進共用庫中的搜索路徑. 在這種情況下,它就有可能使用
一個非內部的不同的搜索路徑.

連接器使用下面的搜索路徑來定位需要的共用庫:

1. 所有由'-rpath-link'選項指定的搜索路徑.

2. 所有由'-rpath'指定的搜索路徑. '-rpath'跟'-rpath_link'的不同之處在於,由'-rpath'指定的路徑被包含在可
執行檔中,並在運行時使用, 而'-rpath-link'選項僅僅在連接時起作用. 它只用於本地連接器.

3. 在一個ELF系統中, 如果'-rpath'和'rpath-link'選項沒有被使用, 會搜索環境變數'LD_RUN_PATH'的內容.它也只
對本地連接器起作用.

4. 在SunOS上, '-rpath'選項不使用, 只搜索所有由'-L'指定的目錄.

5. 對於一個本地連接器,環境變數'LD_LIBRARY_PATH'的內容被搜索.

6. 對於一個本地ELF連接器,共用庫中的`DT_RUNPATH'和`DT_RPATH'操作符會被需要它的共用庫搜索. 如果'DT_RUNPATH'
存在了, 那'DT_RPATH'就會被忽略.

7. 缺省目錄, 常規的,如'/lib'和'/usr/lib'.

8. 對於ELF系統上的本地連接器, 如果檔'/etc/ld.so.conf'存在, 這個檔中有的目錄會被搜索.

如果需要的共用庫沒有被找到, 那連接器會發出一條警告資訊,並繼續執行連接.

`-shared'
`-Bshareable'
創建一個共用庫. 這個選項只在ELF, XCOFF和SunOS平臺上有用。 在SunOS上,如果'-e'選項沒有被使用,並在連接
中有未定義的符號,連接器會自動創建一個共用庫,

`--sort-common'
這個選項告訴'ld'當它把普通符號放到相應的輸出節中時按大小進行排序。排在最前面的是所有的一位元組符號,然
後是所有的二位元組,然後是所有的四位元組, 然後是其他的。 這是為了避免因為對齊約束而在符號間產生的斷裂

`--split-by-file [SIZE]'
跟'--split-by-reloc'相似,但在SIZE達到時,為每一個輸入檔創建一個新的輸出節。如果沒有給出,SIZE缺省
地設置為1

`--split-by-reloc [COUNT]'
試圖在輸出檔中創建節外的節,這樣就沒有單個的輸出節含有多於COUNT個重定位符。這在產生巨大的用於COFF格
式的即時內核的可重定位檔時非常有用;因為COFF不能在一個節中表示多於65535個重定位。 注意,這在不支持
專有節的目標檔格式中會失敗,連接器不會把單個輸入節分割進行重分配, 所以,如果單個輸入節含有多於COUNT
個重定位符, 那一個輸出節會含有同樣多的可重定位符。COUNT缺省被設為32768.

`--stats'
計算並顯示關於連接器操作的統計資訊, 比如執行時間,記憶體佔用等.

`--traditional-format'
對於某些目標平臺, 'ld'的輸出會跟某些面有的連接器的輸出有所不同. 這個開關要求'ld'使用傳
統的格式.

比如, 在SunOS上, 'ld'會把符號串表中的兩上完全相同的入口合併起來. 這可以把一個帶有調試資訊
的輸出檔的大小減小百發之三十. 不幸地是, SunOS的'dbx'程式不能讀取這個輸出的程式(gdb就沒
有問題).'--trafitinal-format'開關告訴'ld'不要把相同的入口合併起來.

`--section-start SECTIONNAME=ORG'
通過指定ORG, 指定節在輸出檔中的絕對位址. 你可以多次使用這個選項來定位多個節. ORG必須是
一個十六進位整數; 為了跟基他的連接器相容,你可以忽略前導'0x'. 注意,在SECTIONNAME,等號,ORG
之間不允許有空格出現.

`-Tbss ORG'
`-Tdata ORG'
`-Ttext ORG'
跟-section-start同義, 不過把SECTIONNAME替換為'.bss', '.data'或'.text'.

`--dll-verbose'
`--verbose'
顯示'ld'的版本號,並列出支援的連接器模擬. 顯示哪些輸入檔能被打開,而哪些不能. 顯示連接器
使用的連接腳本.

`--version-script=VERSION-SCRIPTFILE'
指定連接器的腳本的版本名. 這個常在創建一個需要指定附加的關於版本層次的資訊的共用庫時使用,
這個選項只有支援共用庫的ELF平臺上有效.

`--warn-common'
當一個普通符號跟另一個普通符號或會號定義合併起來時,警告. 類Unix連接器允許這個選項,有時比
較實用, 但是在其他的作業系統上的連接器不允許這個. 這個選項可以讓你在合併全局符號時發現某
些潛在的問題. 不幸的是,有些C庫使用這項特性,所以你可能會像在你的程式中一樣,在庫中得到一些
警告資訊.

這裏給出三種類型的全局符號的解釋(用C語言):

`int i = 1;'
一個定義, 它會存在於輸出檔中的已初始化資料節.

`extern int i;'
一個未定義符號,它不佔用空間. 必須在另外某一處對它有一個定義,或一個普通符號

`int i;'
一個普通符號.如果對於一個變數只有(一個或多個)普通符號, 它進入輸出檔的未初始化資料欄. 連
接器會把同一變數的多個普通符號合併成一個單一的符號. 如果他們有不同的大小, 它採用最大的一
個. 如果是對同一變數的定義,連接器把一個普通符號轉化為一個聲明.

'--warn-common'選項可以產生五種類型的警告. 每種警告由兩行組成: 第一行描述遇到的符號, 第二
行描述遇到的前一個具有相同名字的符號. 一個或兩個都可能成為普通符號.

1. 把一個普通符號轉化為一個引用, 因為這個符號已經有一個定義了.
FILE(SECTION): warning: common of `SYMBOL'
overridden by definition
FILE(SECTION): warning: defined here

2. 把一個普通符號轉化為一個引用,因為遇到了第二個關於符號的定義. 這跟前一種情況相同,除了符
號遇到的順序相反.
FILE(SECTION): warning: definition of `SYMBOL'
overriding common
FILE(SECTION): warning: common is here

3. 把一個普通符號跟前一個相同大小的普通符號合併.
FILE(SECTION): warning: multiple common
of `SYMBOL'
FILE(SECTION): warning: previous common is here

4. 把一個普通符號跟前一個更大的普通符號合併.
FILE(SECTION): warning: common of `SYMBOL'
overridden by larger common
FILE(SECTION): warning: larger common is here

5. 把一個普通符號跟前一個更小的普通符號合併. 這跟前一種情況相同, 除了遇到的符號的順序不同.
FILE(SECTION): warning: common of `SYMBOL'
overriding smaller common
FILE(SECTION): warning: smaller common is here

`--warn-constructors'
如果有全局結構體被使用到了,警告. 這只對很少的一些目標檔格式有用. 對於COFF或ELF格式, 連
接器不同探測到全局結構體的使用.

`--warn-multiple-gp'
如果在輸出檔中,需要多個全局指標值,警告. 這只對特定的處理器有意義, 比如Alpha. 特別的,有
些處理器在特定的節中放入很大的常數值. 一個特殊的寄存器(全局指標)指向這個節的中間部分, 所
以通過一個基底位址寄存器相關的位址模式,這個常數可以很容易地被載入. 因為這個基寄存器相關模式
的偏移值是固定的而且很小(比如,16位), 這會限制常量池的最大尺寸. 所以,一個很大的問題是,為了
能夠定位所有可能的常數,經常需要使用多個全局指標值. 這個選項在這種情況發生時產生一條警告.

`--warn-once'
對於每一個未定義符號只警告一次, 而不是在每一個用到它的模組中警告一次.

`--warn-section-align'
如果輸出節的位址因為對齊被改變了,警告. 通常, 對齊會被輸入節設置. 如果'SECTION'命令沒有指
定節的起始位址, 位址就會被隱式改變.

`--whole-archive'
對於每一個在命令行中'--whole-archive'選項後面出現的檔案檔, 在連接中包含檔案檔中的所有
目標檔, 而不是為需要的目標檔搜索檔案檔. 這在把一個檔案檔轉化為一個共用庫時使用, 把
所有的目標放到最終的共用庫中. 這個選項可以被多次使用.

在GCC中使用這個選項需要注意兩點: 首先,GCC不知道這個選項, 所以,你必須使用'-Wl, -whole-archive'.
第二, 不要忘了在你的檔案檔列表的後面使用'-Wl, -no-whole-archive',因為GCC會把它自己的檔
案列表加到你的連接後面, 而這可能並不是你所預期的.

`--wrap SYMBOL'
對SYMBOL符號使用包裝函數. 任何未定義的對SYMBOL符號的引用會被解析成'_wrap_SYMBOL'. 而任何
未定義的對'_real_SYMBOL'的引用會被解析成SYMBOL.

這可以用來為系統函靈敏提供一個包裝. 包裝函靈敏應當被叫做'__wrap_SYMBOL'. 如果需要調用這個
函數, 那就應該調用'__real_SYMBOL'

這裏是一個沒什麼實用價值的例子:

void *
__wrap_malloc (int c)
{
printf ("malloc called with %ld\n", c);
return __real_malloc ©;
}

如果你使用'--wrap malloc'把這節代碼跟其他的代碼連接, 那所有的對'malloc'的調用都會調用
'__wrap_malloc'函數. 而在'__wrap_malloc'中的'__real_malloc'會調用真正的'malloc'函數.

你有可能也希望提供一個'__real_malloc'函數, 這樣,不帶有'--wrap'的連接器也會成功連接.如果
你這樣做了, 你不能把'__real_malloc'的定義跟'__wrap_malloc'放到同一個檔中;如果放在一起
彙編器會在連接器之前把調用解析成真正的'malloc'.

`--enable-new-dtags'
`--disable-new-dtags'
連接器可以在ELF中創建一個新的動態標籤. 但是舊的ELF系統可能不理解這個. 如果你指定了
'--enable-new-dtags',動態標籤會按需要被創建. 如果你指定了'--disable-new-dtags',那不會有
新的動態標籤被創建. 缺省地,新的動態標籤不會被創建. 注意這些選項只在ELF系統中有效.

i386 PE平臺的特定選項.
-----------------------------------

i386 PE連接器支援'-shared'選項, 它使輸出檔為一個動態連結程式庫(DLL),而不是一個普通的可執行檔. 在
使用這個選項的時候,你應當為輸出檔取名'*.dll',另外, 連接器完全支持標準的'*.def'文件, 這類文件可
以在連接器命令行上象一個目標檔一樣被指定(實際上, 它應當被放在它從中導出符號的那個檔案檔前面,
以保證它們象一個普通的目標檔一樣被連接進去.)

除了對所有平臺通用的那些選項外,i386 PE連接器支持一些隻對i386平臺專有的命令行選面. 帶有值的選項應
當用空格或等號把它跟值分隔開.

`--add-stdcall-alias'
如果給出這個選項, 帶有標準調用尾碼(@NN)的符號會被剝掉尾碼後導出.

`--base-file FILE'
使用FILE作為檔案名,該檔是存放用'dlltool'產生 DLL檔時所需的所有重定位符的基底位址的.(這
個選面是i386 PE平臺所專有的]

`--dll'
創建一個DLL檔而不是一個常規可執行檔. 你可能在一個給出的'.def'檔中使用'-shared'或指
定'LIBRARY'.

`--enable-stdcall-fixup'
`--disable-stdcall-fixup'
如果連接器發現有符號不能解析, 它會試圖進行'失真連接',即尋找另一個定義的符號,它們只是在
符號名的格式上不同(cdecl vs stdcall),並把符號解析為找到的這個符號. 比如, 一個未定義的符
號'_foo'可能被連接到函數'_foo@12', 或者一個未定義的符號'_bar@16'可能被連接到函數'_bar'.
如果連接器這麼做了, 它會列印出一條警告資訊, 因為在正常情況下,這會連接失敗, 但有時,由第三
方庫產生的導入庫可能需要這個特性. 如果你指定了'--enable-stdcall-fixup', 這個特性會被完全
開啟,警告資訊也不會列印出來. 如果你指定了'--disable-stdcall-fixup',這個特性被關閉,而且這
樣的錯誤匹配會被認為是個錯誤.

`--export-all-symbols'
如果給出這個選項,目標中所有由DLL建立的全局符號會被DLL導出. 注意這是缺省情況,否則沒有任何
符號被導出. 如果符號由DEF檔顯式地導出,或由函數本身的屬性隱式地導出, 缺省情況是除非選項
給出,否則不導出任何其他的符號. 注意符號`DllMain@12',`DllEntryPoint@0',
`DllMainCRTStartup@12'和`impure_ptr'不會自動被導出.而且,由其他的DLL導入的符號也不會被再
次導出, 還有指定DLL內部佈局的符號,比如那些以'_head_'開頭,或者以'_iname'結尾的符號也不會
被導出.還有,'libgcc','libstd++','libmingw32'或'crtX.o'中的符號也不會被導出. ......

環境變數
=====================

你可以通過環境變數`GNUTARGET', `LDEMULATION'和`COLLECT_NO_DEMANGLE'改變'ld'的行為.

`GNUTARGET'在你沒有使用'-b'(或者它的同義詞'--format')的時候,決定輸入檔的格式. 它的值應當是BFD
中關於輸入格式的一個名字. 如果環境中沒有'GNUTARGET'變數, 'ld'使用目標平臺的缺省格式. 如果
'GNUTARGET'被設為'default', 那BFD就會通過檢查二進位的輸入檔來找到輸入格式; 這個方法通常會成功,
但會有潛在的不明確性, 因為沒有辦法保證指定一個目標檔格式的魔數總是唯一的. 但是, 在每一個系統上
的BFD配置程式會把這個系統的常規格式放在搜索列表的首位, 所以不明確性可以通過這種慣列來解決.

`LDEMULATION'在你沒有使用'-m'選項的時候決定缺省的模擬器. 模擬器可以影響到連接器行為的很多方面,
特別是連接器的缺省連接腳本. 你可以通過'--verbose'或'-V'選項列出所有可用的模擬器. 如果'-m'選項沒
有使用, 而且`LDEMULATION'環境變數沒有定義, 缺省的模擬器跟連接器如何被配置有關.

一般地,連接器缺省狀況下會重構符號.但是,如果在環境中設置了`COLLECT_NO_DEMANGLE', 那缺省狀態下就不
會重構符號.這個環境變數在GCC的連接包裝程式中會以相似的方式被使用. 這個缺省的行為可以被'--demangle'
或'--no-demangle'選項覆蓋.

連接腳本
**************

每個連接都被一個'連接腳本'所控制. 這個腳本是用連接命令語言書寫的.

連接腳本的一個主要目的是描述輸入檔中的節如何被映射到輸出檔中,並控制輸出檔的記憶體排布. 幾乎
所有的連接腳本只做這兩件事情. 但是,在需要的時候,連接器腳本還可以指示連接器執行很多其他的操作.這
通過下面描述的命令實現.

連接器總是使用連接器腳本的.如果你自己不提供, 連接器會使用一個缺省的腳本,這個腳本是被編譯進連接器
可執行檔的. 你可以使用'--verbose'命令行選項來顯示缺省的連接器腳本的內容. 某些命令行選項,比如
'-r'或'-N', 會影響缺省的連接腳本.

你可以過使用'-T'命令行選項來提供你自己的連接腳本. 當你這麼做的時候, 你的連接腳本會替換缺省的連
接腳本.

你也可以通過把連接腳本作為一個連接器的輸入檔來隱式地使用它,就象它們是一個被連接的檔一樣.

基本的連接腳本的概念
============================

我們需要定義一些基本的概念與辭彙以描述連接腳本語言.

連接器把多個輸入檔合併成單個輸出檔. 輸出檔和輸入檔都以一種叫做'目標檔格式'的資料格式形
式存在. 每一個檔被叫做'目標檔'. 輸出檔經常被叫做'可執行檔',但是由於需要,我們也把它叫做目
標文件.



arrow
arrow
    全站熱搜

    BB 發表在 痞客邦 留言(0) 人氣()