亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 1528 | 回復(fù): 0
打印 上一主題 下一主題

LD中文使用手冊(cè) [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2007-08-06 11:50 |只看該作者 |倒序?yàn)g覽
摘自“中國(guó)龍”
http://www.cnblogs.com/huqingyu/

使用ld
********
本文檔介紹GNU連接器ld的2.14版本.
本文檔在GNU自由文檔許可證下發(fā)行.在"GNU自由文檔許可證"一章中有關(guān)于本許可證的一份拷貝.
概述
********
'ld'把一定量的目標(biāo)文件跟檔案文件連接起來(lái),并重定位它們的數(shù)據(jù),連接符號(hào)引用.一般,在編譯一個(gè)程序
時(shí),最后一步就是運(yùn)行'ld'.
'ld'能接受連接命令語(yǔ)言文件,這是一種用AT&T的連接編輯命令語(yǔ)言的超集寫(xiě)成的文件,用來(lái)在連接的整個(gè)過(guò)程中提供顯式的,全局的控制.
本版本的'ld'使用通用BFD庫(kù)來(lái)操作目標(biāo)文件.這就允許'ld'讀取,合并,寫(xiě)入目標(biāo)文件時(shí),可以使用各種不同
的格式,比如,COFF或'a.out'. 不同的格式可以被連接到一起產(chǎn)生一個(gè)有效的目標(biāo)文件.
除了它的靈活性,GNU連接器比其它連接器更有用的地方在于它提供了診斷信息. 許多連接器在碰到一個(gè)錯(cuò)誤的時(shí)候立即放棄執(zhí)行;但'ld'卻能夠繼續(xù)執(zhí)行,以讓你發(fā)現(xiàn)其他的錯(cuò)誤(或者,在某些情況下,得到一個(gè)帶有錯(cuò)誤
的輸出文件)
引用
**********
GNU連接器'ld'能夠處理大量的不同情況,并且跟其他的連接器保持盡可能的兼容.這樣,你就擁有更多的選擇來(lái)控制它的行為.
命令行選項(xiàng)
====================
連接器提供大量的命令行選項(xiàng),但是,在實(shí)際使用中,只有少數(shù)被經(jīng)常使用.比如,'ld'的一個(gè)經(jīng)常的使用場(chǎng)合是在
一個(gè)標(biāo)準(zhǔn)的Unix系統(tǒng)上連接標(biāo)準(zhǔn)的Unix目標(biāo)文件.在這樣的一個(gè)系統(tǒng)上,連接文件'hello.o'如下:
ld -o OUTPUT /lib/crt0.o hello.o -lc
這告訴'ld'產(chǎn)生一個(gè)叫OUTPUT的文件,作為連接文件'/lib/crt0.o'和'hello.o'和庫(kù)'libc.a'的結(jié)果.'libc.a'
來(lái)自標(biāo)準(zhǔn)的搜索路徑.(參閱下文的關(guān)于'-l'選項(xiàng)的討論).
有些命令行選項(xiàng)可以在命令行的任何位置出現(xiàn).但是,那些帶有文件名的選項(xiàng),比如'-l'或者'-T',會(huì)讓文件在選項(xiàng)出現(xiàn)的位置上被讀取. 對(duì)于非文件選項(xiàng),以帶不同的參數(shù)重復(fù)它,不會(huì)有進(jìn)一步的效果,或者覆蓋掉前面的相同項(xiàng).那些多次出現(xiàn)時(shí)具有特殊含義的選項(xiàng)會(huì)在下文的描述中指出.
無(wú)參數(shù)選項(xiàng)是那些被連接的目標(biāo)文件和檔案文件.它們可能緊隨命令行選項(xiàng),或在它們前面,或者跟它們夾雜在一起,但是一個(gè)目標(biāo)文件參數(shù)是不會(huì)出現(xiàn)在一個(gè)選項(xiàng)跟它的參數(shù)之間的.
通常,連接器至少引用一個(gè)目標(biāo)文件,但是你可指定其它形式的二進(jìn)制輸入文件,這可以通過(guò)'-l','-R'或者腳本命令語(yǔ)言來(lái)實(shí)現(xiàn).如果沒(méi)有任何二進(jìn)制文件被指定,連接器不會(huì)產(chǎn)生任何輸出,并給出信息:"缺少輸入文件."
如果連接器不能識(shí)別目標(biāo)文件的格式,它會(huì)假設(shè)這些只是連接腳本.以這種方式指定的腳本增加了連接用的主連接腳本的內(nèi)容(主連接腳本即缺省連接腳本或使用'-T'指定的腳本). 這個(gè)特性可以允許連接器連接一些文件,它們看上去既像目標(biāo)文件,又像檔案文件,但實(shí)際上只是定義了一些符號(hào)值,或者使用'INPUT'或'GROUP'來(lái)載入其它的目標(biāo)文件.需要注意的是,用這種方式指定一個(gè)腳本只是增加了主連接腳本的內(nèi)容;要完全替換掉主連接腳本,需要使用'-T'.
對(duì)于名稱(chēng)是單個(gè)字符的選項(xiàng),選項(xiàng)參數(shù)必須緊跟在選項(xiàng)字母后面,中間不留空,或者也可留有一個(gè)空格.
對(duì)于名稱(chēng)是多個(gè)字符的選項(xiàng),選項(xiàng)前可以有一個(gè)或兩個(gè)破折號(hào);比如,'-trace-symbol'和`--trace-symbol'是等價(jià)的. 注意,對(duì)于這條規(guī)則有一個(gè)例外.那些以小寫(xiě)字母'o'開(kāi)頭的多字符選項(xiàng)前面只能是兩個(gè)破折號(hào),這是為了避免跟選項(xiàng)'-o'混淆. 比如'-omagic'把輸出文件的名字定為'magic',而'--omagic'在輸出文件中設(shè)置NMAGIC標(biāo)志.
多字符選項(xiàng)的參數(shù)必須跟選項(xiàng)名間以一個(gè)等于號(hào)分開(kāi),或者以一個(gè)空格分開(kāi).比如:`--trace-symbol foo'和`--trace-symbol=foo'是等價(jià)的. 多字符選項(xiàng)的名字唯一縮寫(xiě)符也是可以被接受的.
注意,如果連接器通過(guò)被編譯器驅(qū)動(dòng)來(lái)間接引用(比如gcc), 那所有的連接器命令行選項(xiàng)前必須加上前綴'-Wl'(或者能被特定編譯器驅(qū)動(dòng)接受的其他前綴),就像下面這樣:
gcc -Wl,--startgroup foo.o bar.o -Wl,--endgroup
這很重要,因?yàn)榉駝t的話,編譯器驅(qū)動(dòng)程序會(huì)默認(rèn)丟掉這些連接選項(xiàng),產(chǎn)生一個(gè)錯(cuò)誤的連接.
下面是關(guān)于被GNU連接器接受的常用命令行開(kāi)關(guān)的一個(gè)列表:
`-aKEYWORD'
這個(gè)選項(xiàng)在HP/UX兼容系統(tǒng)上被支持. 參數(shù)KEYWORD必須是下面字符串中的一個(gè):`archive',
`shared', or `default'. `-aarchive'在功能上跟`-Bstatic'相同,而另外兩個(gè)關(guān)鍵字功能上跟
`-Bdynamic'相同. 這個(gè)選項(xiàng)可被多次使用.
`-AARCHITECTURE'
`--architecture=ARCHITECTURE'
在最近發(fā)行版本的'ld'中,這個(gè)選項(xiàng)只在Intel 960系列架構(gòu)上有用. 在那種'ld'配置中,參數(shù)
ARCHITECTURE確定960系列的某一特定架構(gòu),啟用某些安全措施,并修改檔案庫(kù)的搜索路徑.
將來(lái)的'ld'發(fā)行版可能為其它架構(gòu)系列支持相似的功能.
`-b INPUT-formAT'
`--format=INPUT-formAT'
'ld'可以被配置為支持多于一種的目標(biāo)文件.如果你的'ld'以這種方式被配置,你可以使用'-b'選
項(xiàng)為輸入目標(biāo)文件指定二進(jìn)制格式. 就算'ld'被配置為支持可選目標(biāo)格式,你不必經(jīng)常指定這一項(xiàng),
因?yàn)?ld'被配置為在每一臺(tái)機(jī)子上把最常用的格式作為默認(rèn)輸入格式. INPUT-formAT是一個(gè)字符串,
你可能在連接一個(gè)不常用的二進(jìn)制格式文件時(shí)需要這個(gè)參數(shù).你也可使用'-b'來(lái)顯式切換格式(在連接
不同格式的目標(biāo)文件時(shí)),方法是在每一組特定格式的目標(biāo)前使用'-b INPUT-formAT'.
缺省的格式是從環(huán)境變量'GNUTARGET'中得到的.你也可以從一個(gè)腳本中定義輸入格式,使用的命令是
'TARGET'.
`-c MRI-COMMANDFILE'
`--mri-script=MRI-COMMANDFILE'
為了跟MRI生產(chǎn)的連接器兼容,'ld'接受另一種用受限命令語(yǔ)言寫(xiě)成的腳本文件,通過(guò)選項(xiàng)'-c'引入MRI
腳本文件;使用'-T'選項(xiàng)是運(yùn)行用普通'ld'腳本語(yǔ)言寫(xiě)的連接腳本.如果MRI-CMDFILE不存在,'ld'在'-L'
指定的目錄中尋找.
`-d'
`-dc'
`-dp'
這三個(gè)選項(xiàng)是等價(jià)的; 多字符形式是為了跟其他連接器兼容才被支持的.它們給普通符號(hào)分配空間,即
使一個(gè)重定位輸出文件已經(jīng)被指定(通過(guò)'-r'). 腳本命令`FORCE_COMMON_ALLOCATION'具有同樣的效果.
`-e ENTRY'
`--entry=ENTRY'
使用符號(hào)ENTRY作為你的程序的開(kāi)始執(zhí)行點(diǎn),而不是使用缺省的進(jìn)入點(diǎn).如果沒(méi)有叫做ENTRY的符號(hào),連接器會(huì)企圖把ENTRY作為一個(gè)數(shù)字進(jìn)行分析,并使用它作為入口地址(數(shù)字會(huì)被解釋為10進(jìn)制的;你可以使用前導(dǎo)的'0x'強(qiáng)制為16進(jìn)制,或'0'作為8進(jìn)制.)
`-E'
`--export-dynamic'
當(dāng)創(chuàng)建一個(gè)動(dòng)態(tài)連接的可執(zhí)行程序時(shí), 把所有的符號(hào)加到動(dòng)態(tài)符號(hào)表中.動(dòng)態(tài)符號(hào)表是一個(gè)符號(hào)集,這
些符號(hào)對(duì)于運(yùn)行時(shí)的動(dòng)態(tài)對(duì)象是可見(jiàn)的.
如果你不使用這個(gè)選項(xiàng),動(dòng)態(tài)符號(hào)表中就會(huì)只含有那些連接進(jìn)來(lái)的動(dòng)態(tài)對(duì)象中用到的符號(hào)
如果你使用'dlopen'來(lái)載入動(dòng)態(tài)對(duì)象,它需要引用程序中的符號(hào),那你可能需要在連接程序時(shí)用到這個(gè)
選項(xiàng).
你也可以使用版本腳本來(lái)控制哪些符號(hào)應(yīng)當(dāng)被加到動(dòng)態(tài)符號(hào)表中.
`-EB'
連接big-endian對(duì)象. 這會(huì)影響缺省輸出格式.
`-EL'
連接little-endian對(duì)象. 這會(huì)影響缺省輸出格式.
`-g'
忽略. 為了跟其它工具兼容而提供.
`-i'
執(zhí)行一個(gè)增量連接(跟'-r'等同)
`-init NAME'
當(dāng)創(chuàng)建一個(gè)ELF可執(zhí)行文件或共享對(duì)象時(shí),當(dāng)可執(zhí)行文件或共享對(duì)象被加載時(shí),調(diào)用NAME, 這是通過(guò)把
DT_INIT設(shè)置成函數(shù)的地址實(shí)現(xiàn)的. 缺省情況下,連接器使用'_init'作為調(diào)用的函數(shù).
`-lARCHIVE'
`--library=ARCHIVE'
增加一個(gè)檔案文件ARCHIVE到連接的文件列表中.這個(gè)選項(xiàng)可以被多次使用. 'ld'會(huì)為每一個(gè)指定的
ARCHIVE搜索它的路徑列表,尋找`libARCHIVE.a'
對(duì)于支持共享庫(kù)的系統(tǒng), 'ld'可能還會(huì)搜索擴(kuò)展名不是'.a'庫(kù).特別的,在ELF和SunOS系統(tǒng)上,'ld'會(huì)
在搜索帶有'.a'擴(kuò)展名的庫(kù)前搜索帶'.so'擴(kuò)展名的庫(kù).
`-M'
`--print-map'
打印一個(gè)連接位圖到標(biāo)準(zhǔn)輸出.一個(gè)連接位圖提供的關(guān)于連接的信息有如下一些:
* 目標(biāo)文件和符號(hào)被映射到內(nèi)存的哪些地方.
* 普通符號(hào)如何被分配空間.
* 所有被連接進(jìn)來(lái)的檔案文件,還有導(dǎo)致檔案文件被包含進(jìn)來(lái)的那個(gè)符號(hào).
`-n'
`--nmagic'
關(guān)閉所有節(jié)的頁(yè)對(duì)齊,如果可能,把輸出格式標(biāo)識(shí)為'NMAGIC'.
`-N'
`--omagic'
把text和data節(jié)設(shè)置為可讀寫(xiě).同時(shí),取消數(shù)據(jù)節(jié)的頁(yè)對(duì)齊,同時(shí),取消對(duì)共享庫(kù)的連接.如果輸出格式支持Unix風(fēng)格的magic number, 把輸出標(biāo)志為'OMAGIC'.
`--no-omagic'
這個(gè)選項(xiàng)執(zhí)行的操作大部分正好跟'-N'相反.它設(shè)置text節(jié)只讀,強(qiáng)制data節(jié)頁(yè)對(duì)齊. 但是,這個(gè)選項(xiàng)并不開(kāi)啟連接共享庫(kù)的功能. 使用'-Bdynamic'開(kāi)啟這個(gè)功能.
`-o OUTPUT'
`--output=OUTPUT'
使用OUTPUT作為'ld'產(chǎn)生的程序的名字;如果這個(gè)選項(xiàng)沒(méi)有指定,缺省的輸出文件名是'a.out'.腳本命令'OUTPUT'也可以被用來(lái)指定輸出文件的文件名.
`-O LEVEL'
如果LEVEL是一個(gè)比0大的數(shù)值, 'ld'優(yōu)化輸出.這可能會(huì)明顯多占用時(shí)間,所以只有在生成最后的文件
時(shí)使用.
`-q'
`--emit-relocs'
把重定位節(jié)和內(nèi)容留在完全連接后的可執(zhí)行文件中. 連接分析和優(yōu)化工具可能需要這些信息用來(lái)進(jìn)行
正確的修改與執(zhí)行. 這在大的可執(zhí)行文件中有用.
這個(gè)選項(xiàng)目前只支持ELF平臺(tái).
`-r'
`--relocateable'
產(chǎn)生可重定位的輸出, 比如,產(chǎn)生一個(gè)輸出文件它可再次作為'ld'的輸入.這經(jīng)常被叫做"部分連接".
作為一個(gè)副作用,在支持標(biāo)準(zhǔn)Unix魔數(shù)的環(huán)境中,這個(gè)選項(xiàng)會(huì)把輸出文件的魔數(shù)設(shè)置為'OMAGIC'. 如果這個(gè)選項(xiàng)沒(méi)有被指定,一個(gè)絕對(duì)文件就會(huì)被產(chǎn)生.當(dāng)連接C++程序時(shí),這個(gè)選項(xiàng)就不會(huì)解析構(gòu)造函數(shù)的
引用;要解析,必須使用'-Ur'
如果輸入文件跟輸出文件的格式不同,只有在輸入文件不含有重定位信息的時(shí)候部分連接才被支持.輸出格式不同的時(shí)候會(huì)有更多的限制.比如,有些'a.out'的格式在輸入文件是其他格式的時(shí)候完全不支持部分連接.
這個(gè)選項(xiàng)跟'-i'等效.
`-R FILENAME'
`--just-symbols=FILENAME'
從FILENAME中讀取符號(hào)名跟它們的值,但不重位這個(gè)文件,或者根本不把它包含在輸出文件中.這就允
許你的輸出文件引用其它程序中定義的絕對(duì)內(nèi)存地址.你可以多次使用這個(gè)選項(xiàng).
為了跟其他ELF連接器兼容,如果'-R'選項(xiàng)后面跟有一個(gè)目錄名,而不是一個(gè)文件名,它會(huì)被處理成
'-rpath'選項(xiàng).
`-s'
`--strip-all'
忽略輸出文件中所有的符號(hào)信息.
`-S'
`--strip-debug'
忽略輸出文件中所有的調(diào)試符號(hào)信息(但不是所有符號(hào)).
`-t'
`--trace'
打印'ld'處理的所有輸入文件的名字.
`-T SCRIPTFILE'
`--script=SCRIPTFILE'
把SCRIPTFILE作為連接腳本使用. 這個(gè)腳本會(huì)替代'ld'的缺省連接腳本(而不是增加它的內(nèi)容),所以
命令文件必須指定所有需要的東西以精確描述輸出文件. 如果SCRIPTFILE在當(dāng)前目錄下不存在,'ld'
會(huì)在'-L'選項(xiàng)指定的所有目錄下去尋找.多個(gè)'-T'選項(xiàng)會(huì)使內(nèi)容累積.
`-u SYMBOL'
`--undefined=SYMBOL'
強(qiáng)制SYMBOL在輸出文件中作為一個(gè)無(wú)定義的符號(hào)被輸入.這樣做會(huì)有一些效果,比如,會(huì)引發(fā)從標(biāo)準(zhǔn)庫(kù)
中連接更多的模塊. '-u'可以以不同的參數(shù)反復(fù)使用,以輸入多個(gè)無(wú)定義的符號(hào).這個(gè)選項(xiàng)跟連接腳本命令中的'EXTERN'是等效的.
`-Ur'
對(duì)于不是C++的程序,這個(gè)選項(xiàng)跟'-r'是等效的: 它產(chǎn)生可重定位的輸出,比如,一個(gè)輸出文件它可以再
次作為'ld'的輸入. 當(dāng)連接C++程序時(shí),'-Ur'解析構(gòu)造函數(shù)的引用,跟'-r'不同. 但如果在一些用'-Ur'
連接過(guò)的文件上再次使用'-Ur',它不會(huì)工作,因?yàn)橐坏?gòu)造函數(shù)表被建立,它不能被添加內(nèi)容.請(qǐng)只在
最后一遍連接的時(shí)候使用'-Ur', 對(duì)其它的,只使用'-r'.
`--unique[=SECTION]'
對(duì)于所有匹配SECTION的輸入節(jié),在輸出文件中都各自創(chuàng)建單獨(dú)的節(jié),或者,如果可選的通配符SECTION
參數(shù)丟失了,為每一個(gè)孤兒輸入節(jié)創(chuàng)建一個(gè)輸出節(jié). 一個(gè)孤兒節(jié)是一個(gè)連接腳本中沒(méi)有指定的節(jié).你
可以在命令行上多次使用這個(gè)選項(xiàng); 它阻止對(duì)同名輸入節(jié)的合并,在連接腳本中重載輸出節(jié)分配.
`-v'
`--version'
`-V'
顯示'ld'的版本. '-V'選項(xiàng)同時(shí)會(huì)列出支持的模擬器.
`-x'
`--discard-all'
刪除所有的本地符號(hào).
`-X'
`--discard-locals'
刪除所有的臨時(shí)本地符號(hào).對(duì)于大多數(shù)目標(biāo)平臺(tái),就是所有的名字以'L'開(kāi)頭的本地符號(hào).
`-y SYMBOL'
`--trace-symbol=SYMBOL'
打印出所有SYMBOL出現(xiàn)的被連接文件的名字. 這個(gè)選項(xiàng)可以被多次使用. 在很多系統(tǒng)中,這在預(yù)先確定底線時(shí)很有必要.
當(dāng)你擁有一個(gè)未定義的符號(hào),但不知道這個(gè)引用出自哪里的時(shí)候,這個(gè)選項(xiàng)很有用.
`-Y PATH'
為缺省的庫(kù)搜索路徑增加一條路徑.這個(gè)選項(xiàng)是為了跟Solaris兼容.
`-z KEYWORD'
能被識(shí)別的關(guān)鍵字包括'initfirst', 'interpose', 'loadfltr',`nodefaultlib', `nodelete',
`nodlopen', `nodump', `now', `origin',`combreloc', `nocombreloc' and `nocopyreloc'. 為了跟Solaris兼容,所有其它的關(guān)鍵字都被忽略. 'initfirst'標(biāo)志一個(gè)對(duì)象,使它在運(yùn)行時(shí),在所有其他對(duì)象之前被初始化. 'interpose'標(biāo)志一個(gè)對(duì)象,使它的符號(hào)表放在所有其他符號(hào)之前,作為主要的執(zhí)行者.
'loadfltr'標(biāo)志一個(gè)對(duì)象, 使它的過(guò)濾器在運(yùn)行時(shí)立即被處理.'nodefaultlib'標(biāo)志一個(gè)對(duì)象,使在搜索
本對(duì)象所依賴(lài)的庫(kù)時(shí),忽略所有缺省庫(kù)搜索路徑. 'nodelete'標(biāo)志一個(gè)對(duì)象,使它在運(yùn)行時(shí)不會(huì)被從內(nèi)存
中刪除.'nodlopen'標(biāo)志一個(gè)對(duì)象,使這個(gè)對(duì)象不可以通過(guò)'dlopen'載入.'nodump'標(biāo)志一個(gè)對(duì)象,使它不能被'dldump'轉(zhuǎn)儲(chǔ). 'now'標(biāo)志一個(gè)對(duì)象,使它成為非懶惰運(yùn)行時(shí)綁定對(duì)象. 'origin'標(biāo)志一些可能含有 $ORIGIN的對(duì)象,'defs'不允許無(wú)定義符號(hào). 'muldefs'允許重定義. 'comberloc'組合多個(gè)重定位節(jié),重新排布它們,讓動(dòng)態(tài)符號(hào)可見(jiàn). 'nocomberloc'使多個(gè)重定位節(jié)組合無(wú)效. 'nocopyreloc'使重定位拷貝后的結(jié)果無(wú)效.
`-( ARCHIVES -)'
`--start-group ARCHIVES --end-group'
ARCHIVES應(yīng)當(dāng)是一個(gè)關(guān)于檔案文件的列表. 它們可以是顯式的文件名,或者'-l'選項(xiàng).
這些指定的檔案文件會(huì)被多遍搜索,直到?jīng)]有新的無(wú)定義引用被創(chuàng)建. 通常,一個(gè)檔案文件只會(huì)被搜索一
次. 但如果這個(gè)檔案文件中的一個(gè)符號(hào)需要被用來(lái)解析一個(gè)檔案中的目標(biāo)引用到的無(wú)定義的符號(hào),而這個(gè)
符號(hào)在命令行上的后面某個(gè)檔案文件中出現(xiàn), 連接器不能解析這個(gè)引用. 把這些檔案文件分組后,它們都
可被反復(fù)搜索直到所有可能的引用都被解析了為止.
使用這個(gè)選項(xiàng)有一個(gè)很大的運(yùn)行開(kāi)銷(xiāo). 只有在無(wú)法避免在多個(gè)檔案文件中使用循環(huán)引用時(shí)才用它.
`--accept-unknown-input-arch'
`--no-accept-unknown-input-arch'
告訴連接器接受那些架構(gòu)不能被識(shí)別的輸入文件. 但前提假設(shè)是用戶知道他們?cè)谧鍪裁?并且是故意要連 接這些未知的輸入文件. 在版本2.14之前,這個(gè)是連接器的缺省行為. 從版本2.14以后的,缺省行為是拒
絕這類(lèi)輸入文件, 所以`--accept-unknown-input-arch'選項(xiàng)被用來(lái)恢復(fù)舊的行為.
`-assert KEYWORD'
這個(gè)選項(xiàng)被忽略,只是用來(lái)跟SunOS保持兼容.
`-Bdynamic'
`-dy'
`-call_shared'
連接動(dòng)態(tài)鏈接庫(kù). 這個(gè)僅僅在支持共享庫(kù)的平臺(tái)上有用.在這些平臺(tái)上,這個(gè)選項(xiàng)通常是默認(rèn)行為. 這個(gè)選
項(xiàng)的不同形式是為了跟不同的系統(tǒng)保持兼容. 你可以在命令行上多次使用這個(gè)選項(xiàng):它影響緊隨其后的'-l'選項(xiàng)的庫(kù)搜索.
`-Bgroup'
在動(dòng)態(tài)節(jié)的'DT_FLAGS_1'入口上設(shè)置'DF_1_GROUP'標(biāo)志.這會(huì)讓運(yùn)行時(shí)連接器在處理在這個(gè)對(duì)象和它的相關(guān)部分搜索時(shí)只在組中. '--no-undefined'是隱式的. 這個(gè)選項(xiàng)只在支持共享庫(kù)的ELF平臺(tái)上有用.
`-Bstatic'
`-dn'
`-non_shared'
`-static'
不連接共享庫(kù). 這個(gè)僅僅在支持共享庫(kù)的平臺(tái)上有用. 這個(gè)選項(xiàng)的不同形式是為了跟不同的系統(tǒng)保持兼
容. 你可以在命令行上多次使用這個(gè)選項(xiàng):它影響緊隨其后的'-l'選項(xiàng)的庫(kù)搜索.
`-Bsymbolic'
當(dāng)創(chuàng)建一個(gè)共享庫(kù)時(shí), 把對(duì)全局符號(hào)的引用綁定到共享庫(kù)中的定義(如果有), 通常, 一個(gè)連接共享庫(kù)的程 序重載共享庫(kù)中的定義是可能的. 這個(gè)選項(xiàng)只在支持共享庫(kù)的ELF平臺(tái)上有用.
`--check-sections'
`--no-check-sections'
讓連接器在節(jié)地址被分配后不要去檢查節(jié)地址是否重疊.通常,連接器會(huì)執(zhí)行這種檢查,如果它發(fā)現(xiàn)了任何 重疊,它會(huì)產(chǎn)生相應(yīng)的錯(cuò)誤信息. 連接器知道也允許節(jié)的重疊. 缺省的行為可以使用命令行開(kāi)關(guān)
`--check-sections'來(lái)恢復(fù).
`--cref'
輸出一個(gè)交叉引用表. 如果一個(gè)連接器位圖文件被產(chǎn)生, 交叉引用表被打印到位圖文件. 否則, 它被打印
到標(biāo)準(zhǔn)輸出.
表的格式相當(dāng)?shù)暮?jiǎn)單, 所以,如果需要,可以通過(guò)一個(gè)腳本很輕易地處理它. 符號(hào)是以名字被打印輸出,存
儲(chǔ). 對(duì)于每一個(gè)符號(hào),給出一個(gè)文件名列表. 如果符號(hào)被定義了, 列出的第一個(gè)文件是符號(hào)定義的所在.
接下來(lái)的文件包含符號(hào)的引用.
`--no-define-common'
這個(gè)選項(xiàng)限制對(duì)普通符號(hào)的地址分配. 腳本命令`INHIBIT_COMMON_ALLOCATION'具有同等的效果.
`--no-define-common'選項(xiàng)允許從輸出文件的類(lèi)型選擇中確定對(duì)普通符號(hào)的地址分配; 否則, 一個(gè)非重定
位輸出類(lèi)型強(qiáng)制為普通符號(hào)分配地址. 使用'--no-define-common'允許那些從共享庫(kù)中引用的普通符號(hào)只
在主程序中被分配地址. 這會(huì)消除在共享庫(kù)中的無(wú)用的副本的空間, 同時(shí),也防止了在有多個(gè)指定了搜索
路徑的動(dòng)態(tài)模塊在進(jìn)行運(yùn)行時(shí)符號(hào)解析時(shí)引起的混亂.
`--defsym SYMBOL=EXPRESSION'
在輸出文件中建立一個(gè)全局符號(hào),這個(gè)符號(hào)擁有一個(gè)EXPRESSION指定的絕對(duì)地址. 你可以多次使用這個(gè)選
項(xiàng)定義多個(gè)符號(hào). EXPRESSION支持一個(gè)受限形式的算術(shù)運(yùn)算:你可以給出一個(gè)十六進(jìn)制常數(shù)或者一個(gè)已存
在符號(hào)的名字,或者使用'+'和'-'來(lái)加或減十六進(jìn)制常數(shù)或符號(hào). 如果你需要更多的表達(dá)式,可以考慮在腳
本中使用連接器命令語(yǔ)言, 注意在SYMBOL,=和EXPRESSION之間不允許有空格.
`--demangle[=style]'
`--no-demangle'
這些選項(xiàng)控制是否在錯(cuò)誤信息和其它的輸出中重組符號(hào)名. 當(dāng)連接器被告知要重組, 它會(huì)試圖把符號(hào)名以一種可讀的形式的展現(xiàn): 如果符號(hào)被以目標(biāo)文件格式使用,它剝?nèi)デ皩?dǎo)的下劃線,并且把C++形式的符號(hào)名轉(zhuǎn)換成用戶可讀的名字. 不同的編譯器有不同的重組形式. 可選的重組形式參數(shù)可以被用來(lái)為你的編譯器選擇一個(gè)相應(yīng)的重組形式. 連接器會(huì)以缺省形式重組直至環(huán)境變量`COLLECT_NO_DEMANGLE'被設(shè)置. 這些
選項(xiàng)可以被用來(lái)重載缺省的設(shè)置.
`--dynamic-linker FILE'
設(shè)置動(dòng)態(tài)連接器的名字. 這個(gè)只在產(chǎn)生動(dòng)態(tài)連接的ELF可執(zhí)行文件時(shí)有效. 缺省的動(dòng)態(tài)連接器通常是正確 的; 除非你知道你在干什么,不要使用這個(gè)選項(xiàng).
`--embedded-relocs'
這個(gè)選項(xiàng)只在連接MIPS嵌入式PIC代碼時(shí)有效, 這些代碼必須是由GNU的編譯器跟匯編器通過(guò)-membedded-pic
選項(xiàng)生成的. 它導(dǎo)致連接器產(chǎn)生一個(gè)表,這個(gè)表被用來(lái)在運(yùn)行時(shí)重定位所有的被靜態(tài)初始化為指針值的數(shù) 據(jù).
`--fatal-warnings'
把所有的警告視為錯(cuò)誤.
`--force-exe-suffix'
確保輸出文件有一個(gè).exe后綴.
如果一個(gè)被成功完整連接的輸出文件不帶有一個(gè)'.exe'或'.dll'后綴, 這個(gè)選項(xiàng)確保連接器把輸出文件
拷貝成帶有'.exe'后綴的同名文件. 這個(gè)選項(xiàng)在使用微軟系統(tǒng)來(lái)編譯未經(jīng)修改的Unix的makefile時(shí)很有 用, 因?yàn)橛行┌姹镜膚indows不會(huì)運(yùn)行一個(gè)不帶有'.exe'后綴的映像.
`--no-gc-sections'
`--gc-sections'
允許對(duì)未使用的輸入節(jié)的碎片收集. 在不支持這個(gè)選項(xiàng)的平臺(tái)上,被忽略. 這個(gè)選項(xiàng)不能跟 '-r'選項(xiàng)共存
也不能被用來(lái)進(jìn)行動(dòng)態(tài)連接. 缺省行為可以用`--no-gc-sections'進(jìn)行恢復(fù).
`--help'
在標(biāo)準(zhǔn)輸出上打印一個(gè)命令行選項(xiàng)概要,然后退出.
`--target-help'
打印一個(gè)所有目標(biāo)平臺(tái)相關(guān)的選項(xiàng)的概要,然后退出.
`-Map MAPFILE'
打印一個(gè)連接位圖到文件MAPFILE中. 參閱上面關(guān)于'-M'選項(xiàng)的描述.
`--no-keep-memory'
'ld'通常會(huì)以速度優(yōu)先于內(nèi)存使用的方式優(yōu)化程序,這是通過(guò)把輸入文件的符號(hào)表放在內(nèi)存緩沖中實(shí)現(xiàn)的,
這個(gè)選項(xiàng)告訴'ld'以?xún)?nèi)存使用優(yōu)先來(lái)優(yōu)化, 盡可能的減小符號(hào)表的重讀. 這在'ld'在連接一個(gè)大文件時(shí)
超出內(nèi)存限制時(shí)有用.
`--no-undefined'
`-z defs'
通常,當(dāng)創(chuàng)建一個(gè)非符號(hào)共享庫(kù)時(shí), 無(wú)定義的符號(hào)允許出現(xiàn),并留待運(yùn)行時(shí)連接器去解決. 這個(gè)選項(xiàng)關(guān)閉這
樣的無(wú)定義符號(hào)的使用. 開(kāi)關(guān)`--no-allow-shlib-undefined'控制共享對(duì)象被連接進(jìn)共享庫(kù)時(shí)的行為.
`--allow-multiple-definition'
`-z muldefs'
通常,當(dāng)一個(gè)符號(hào)被定義多次時(shí), 連接器會(huì)報(bào)告一個(gè)致命錯(cuò)誤. 這些選項(xiàng)允許重定義并且第一個(gè)定義被使

`--allow-shlib-undefined'
`--no-allow-shlib-undefined'
允許(缺省)或不允許無(wú)定義符號(hào)存在于共享對(duì)象中. 這個(gè)開(kāi)關(guān)的設(shè)置會(huì)重載'--no-undefined',這里只關(guān)
注共享對(duì)象. 這樣,如果'--no-undefined'被設(shè)置,但'--no-allow-shlib-undefined'未被設(shè)置, 連鎖反應(yīng)
是存在于規(guī)則對(duì)象文件中的無(wú)定義的符號(hào)會(huì)引起一個(gè)錯(cuò)誤,但是在共享對(duì)象中的未定義的符號(hào)會(huì)被忽略.
把`--allow-shlib-undefined'設(shè)置為缺省的原因是在連接時(shí)指定的共享對(duì)象并不一定是載入時(shí)可載入的
那個(gè),所以,符號(hào)可能要到載入時(shí)間才被解析.
`--no-undefined-version'
通常當(dāng)一個(gè)符號(hào)有一個(gè)未定義的版本時(shí),連接器會(huì)忽略它. 這個(gè)選項(xiàng)不允許符號(hào)有未定義的版本,并且碰
到這種情況,會(huì)報(bào)告一個(gè)嚴(yán)重錯(cuò)誤.
`--no-warn-mismatch'
通常, 如果你因?yàn)橐恍┰?企圖把一些不匹配的輸入文件連接起來(lái)的時(shí)候,'ld'會(huì)給出一個(gè)錯(cuò)誤,可能這
些文件是因?yàn)橛刹煌奶幚砥骶幾g. 這個(gè)選項(xiàng)告訴'ld'應(yīng)當(dāng)對(duì)這樣的錯(cuò)誤默認(rèn)允許. 這個(gè)選項(xiàng)必須小心
使用.
`--no-whole-archive'
為后面的檔案文件關(guān)閉'--whole-archive'選項(xiàng)的影響.
`--noinhibit-exec'
當(dāng)一個(gè)可執(zhí)行文件還可以使用時(shí),就保留它. 通常,連接器如果在連接過(guò)程中遇到了錯(cuò)誤,就不會(huì)產(chǎn)生輸出
文件;當(dāng)它遇上錯(cuò)誤時(shí),它會(huì)退出而不寫(xiě)輸出文件.
`-nostdlib'
僅搜索那些在命令行上顯式指定的庫(kù)路徑. 在連接腳本中(包含在命令行上指定的連接腳本)指定的庫(kù)路
徑都被忽略.
`--oformat OUTPUT-formAT'
'ld'可以被配置為支持多于一種的目標(biāo)文件. 如果你的'ld'以這種方式被配置,你可以使用'--oformat'
選項(xiàng)來(lái)指定輸出目標(biāo)文件的二進(jìn)制格式.就算'ld'被配置為支持多種目標(biāo)格式,你也不必指定這個(gè)項(xiàng),因
為'ld'應(yīng)當(dāng)被配置為把最常用的輸出格式作為默認(rèn)格式. OUTPUT-formAT是一個(gè)文本串,是被BFD庫(kù)支持的一個(gè)特定格式的名字.腳本命令'OUTPUT_formAT'也可以指定輸出格式,但這個(gè)選項(xiàng)可以覆蓋它.
`-qmagic'
這個(gè)選項(xiàng)被忽略,只是為了跟Linux保持兼容.
`-Qy'
這個(gè)選項(xiàng)被忽略,只是為了跟SVR4保持兼容.
`--relax'
一個(gè)機(jī)器相關(guān)的選項(xiàng). 只有在少數(shù)平臺(tái)上,這個(gè)選項(xiàng)被支持.
在某些平臺(tái)上,'--relax'選項(xiàng)在連接器解析程序中的地址時(shí)執(zhí)行可能的全局優(yōu)化, 比如松散地址模式和在輸出文件中合成新的指令.
在某些平臺(tái)上,連接時(shí)全局優(yōu)化會(huì)進(jìn)行符號(hào)調(diào)試導(dǎo)致程序不能運(yùn)行.
在不支持這個(gè)選項(xiàng)的平臺(tái)上,'--relax'被接受,但被忽略.
`--retain-symbols-file FILENAME'
只保留在FILENAME中列出的那些符號(hào),丟棄所有其他的. FILENAME是一個(gè)簡(jiǎn)單地平坦模式文件, 一個(gè)符號(hào)占一行. 這個(gè)選項(xiàng)在那些會(huì)逐步積累起一個(gè)大的全局符號(hào)表的系統(tǒng)中(比如 VxWorks)會(huì)很有用,它能有效地節(jié)約內(nèi)存空間.
'--retain-symbols-file'不丟棄未定義的符號(hào),和需要重定位的符號(hào).
你可能在命令行上只指定'--retain-symbol-file'一次, 它覆蓋'-s'和'-S'的功能.
`-rpath DIR'
為運(yùn)行時(shí)庫(kù)的搜索路徑增加一個(gè)目錄. 這個(gè)在連接帶有共享庫(kù)的ELF可執(zhí)行文件時(shí)有用. '-rpath'的所有參數(shù)會(huì)被
連接起來(lái)傳遞給運(yùn)行時(shí)連接器, 運(yùn)行時(shí)連接器在運(yùn)行時(shí)用它們定位共享對(duì)象. '-rpath'選項(xiàng)在定位那些在連接參數(shù)
指定的共享對(duì)象需要的共享對(duì)象時(shí)也很有用; 參閱關(guān)于'-rpath-link'選項(xiàng)的描述, 如果在連接一個(gè)ELF可執(zhí)行文件
時(shí)不使用'-rpath'選項(xiàng),那些環(huán)境變量'LD_RUN_PATH'選項(xiàng)就會(huì)被使用.
'-rptah'選項(xiàng)也可以使用在SunOS上. 缺省地,在SunOS上,連接器會(huì)從所有的'-L'選項(xiàng)中形成一個(gè)運(yùn)行時(shí)搜索路徑.
如果使用了'-rpath'選項(xiàng), 那運(yùn)行時(shí)搜索路徑就只從'-rpath'選項(xiàng)中得到, 忽略'-L'選項(xiàng). 這在使用GCC時(shí)非常有用, 它會(huì)用上很多的'-L'選項(xiàng),而這些路徑很可能就是NFS掛上去的文件系統(tǒng)中.
為了同ELF的連接器兼容, 如果'-R'選面后面跟有一個(gè)目錄名, 而不是一個(gè)文件名,那它也會(huì)被處理成'-rpath'選項(xiàng).
`-rpath-link DIR'
當(dāng)在SunOS上使用ELF時(shí),一個(gè)共享庫(kù)可能會(huì)用到另一個(gè)共享庫(kù). 當(dāng)'ld -share'把一個(gè)共享庫(kù)作為一個(gè)輸入文件連接時(shí)就有可能發(fā)生這種情況.
當(dāng)一個(gè)連接器在作非共享,不可重定位連接時(shí),如果遇上這種依賴(lài)情況,它會(huì)自動(dòng)定位需要的共享庫(kù),然后把它包含在
連接中, 如果在這種情況中,它沒(méi)有被顯式包含, 那'-rpath-link'選項(xiàng)指定優(yōu)先搜索的一組路徑名.
這個(gè)選項(xiàng)必須小心使用,因?yàn)樗鼤?huì)覆蓋那些可能已經(jīng)被編譯進(jìn)共享庫(kù)中的搜索路徑. 在這種情況下,它就有可能使用一個(gè)非內(nèi)部的不同的搜索路徑.
連接器使用下面的搜索路徑來(lái)定位需要的共享庫(kù):
1. 所有由'-rpath-link'選項(xiàng)指定的搜索路徑.
2. 所有由'-rpath'指定的搜索路徑. '-rpath'跟'-rpath_link'的不同之處在于,由'-rpath'指定的路徑被包含在可執(zhí)行文件中,并在運(yùn)行時(shí)使用, 而'-rpath-link'選項(xiàng)僅僅在連接時(shí)起作用. 它只用于本地連接器.
3. 在一個(gè)ELF系統(tǒng)中, 如果'-rpath'和'rpath-link'選項(xiàng)沒(méi)有被使用, 會(huì)搜索環(huán)境變量'LD_RUN_PATH'的內(nèi)容.它也只對(duì)本地連接器起作用.
4. 在SunOS上, '-rpath'選項(xiàng)不使用, 只搜索所有由'-L'指定的目錄.
5. 對(duì)于一個(gè)本地連接器,環(huán)境變量'LD_LIBRARY_PATH'的內(nèi)容被搜索.
6. 對(duì)于一個(gè)本地ELF連接器,共享庫(kù)中的`DT_RUNPATH'和`DT_RPATH'操作符會(huì)被需要它的共享庫(kù)搜索. 如果'DT_RUNPATH'存在了, 那'DT_RPATH'就會(huì)被忽略.
7. 缺省目錄, 常規(guī)的,如'/lib'和'/usr/lib'.
8. 對(duì)于ELF系統(tǒng)上的本地連接器, 如果文件'/etc/ld.so.conf'存在, 這個(gè)文件中有的目錄會(huì)被搜索.
如果需要的共享庫(kù)沒(méi)有被找到, 那連接器會(huì)發(fā)出一條警告信息,并繼續(xù)執(zhí)行連接.
`-shared'
`-Bshareable'
創(chuàng)建一個(gè)共享庫(kù). 這個(gè)選項(xiàng)只在ELF, XCOFF和SunOS平臺(tái)上有用。 在SunOS上,如果'-e'選項(xiàng)沒(méi)有被使用,并在連接中有未定義的符號(hào),連接器會(huì)自動(dòng)創(chuàng)建一個(gè)共享庫(kù),
`--sort-common'
這個(gè)選項(xiàng)告訴'ld'當(dāng)它把普通符號(hào)放到相應(yīng)的輸出節(jié)中時(shí)按大小進(jìn)行排序。排在最前面的是所有的一字節(jié)符號(hào),然后是所有的二字節(jié),然后是所有的四字節(jié), 然后是其它的。 這是為了避免因?yàn)閷?duì)齊約束而在符號(hào)間產(chǎn)生的斷裂
`--split-by-file [SIZE]'
跟'--split-by-reloc'相似,但在SIZE達(dá)到時(shí),為每一個(gè)輸入文件創(chuàng)建一個(gè)新的輸出節(jié)。如果沒(méi)有給出,SIZE缺省地設(shè)置為1
`--split-by-reloc [COUNT]'
試圖在輸出文件中創(chuàng)建節(jié)外的節(jié),這樣就沒(méi)有單個(gè)的輸出節(jié)含有多于COUNT個(gè)重定位符。這在產(chǎn)生巨大的用于COFF格
式的實(shí)時(shí)內(nèi)核的可重定位文件時(shí)非常有用;因?yàn)镃OFF不能在一個(gè)節(jié)中表示多于65535個(gè)重定位。 注意,這在不支持專(zhuān)有節(jié)的目標(biāo)文件格式中會(huì)失敗,連接器不會(huì)把單個(gè)輸入節(jié)分割進(jìn)行重分配, 所以,如果單個(gè)輸入節(jié)含有多于COUNT個(gè)重定位符, 那一個(gè)輸出節(jié)會(huì)含有同樣多的可重定位符。COUNT缺省被設(shè)為32768.
`--stats'
計(jì)算并顯示關(guān)于連接器操作的統(tǒng)計(jì)信息, 比如執(zhí)行時(shí)間,內(nèi)存占用等.
`--traditional-format'
對(duì)于某些目標(biāo)平臺(tái), 'ld'的輸出會(huì)跟某些面有的連接器的輸出有所不同. 這個(gè)開(kāi)關(guān)要求'ld'使用傳
統(tǒng)的格式.
比如, 在SunOS上, 'ld'會(huì)把符號(hào)串表中的兩上完全相同的入口合并起來(lái). 這可以把一個(gè)帶有調(diào)試信息
的輸出文件的大小減小百發(fā)之三十. 不幸地是, SunOS的'dbx'程序不能讀取這個(gè)輸出的程序(gdb就沒(méi)
有問(wèn)題).'--trafitinal-format'開(kāi)關(guān)告訴'ld'不要把相同的入口合并起來(lái).
`--section-start SECTIONNAME=ORG'
通過(guò)指定ORG, 指定節(jié)在輸出文件中的絕對(duì)地址. 你可以多次使用這個(gè)選項(xiàng)來(lái)定位多個(gè)節(jié). ORG必須是
一個(gè)十六進(jìn)制整數(shù); 為了跟基他的連接器兼容,你可以忽略前導(dǎo)'0x'. 注意,在SECTIONNAME,等號(hào),ORG之間不允許有空格出現(xiàn).
`-Tbss ORG'
`-Tdata ORG'
`-Ttext ORG'
跟-section-start同義, 不過(guò)把SECTIONNAME替換為'.bss', '.data'或'.text'.
`--dll-verbose'
`--verbose'
顯示'ld'的版本號(hào),并列出支持的連接器模擬. 顯示哪些輸入文件能被打開(kāi),而哪些不能. 顯示連接器
使用的連接腳本.
`--version-script=VERSION-SCRIPTFILE'
指定連接器的腳本的版本名. 這個(gè)常在創(chuàng)建一個(gè)需要指定附加的關(guān)于版本層次的信息的共享庫(kù)時(shí)使用,
這個(gè)選項(xiàng)只有支持共享庫(kù)的ELF平臺(tái)上有效.
`--warn-common'
當(dāng)一個(gè)普通符號(hào)跟另一個(gè)普通符號(hào)或會(huì)號(hào)定義合并起來(lái)時(shí),警告. 類(lèi)Unix連接器允許這個(gè)選項(xiàng),有時(shí)比
較實(shí)用, 但是在其他的操作系統(tǒng)上的連接器不允許這個(gè). 這個(gè)選項(xiàng)可以讓你在合并全局符號(hào)時(shí)發(fā)現(xiàn)某
些潛在的問(wèn)題. 不幸的是,有些C庫(kù)使用這項(xiàng)特性,所以你可能會(huì)像在你的程序中一樣,在庫(kù)中得到一些
警告信息.
這里給出三種類(lèi)型的全局符號(hào)的解釋(用C語(yǔ)言):
`int i = 1;'
一個(gè)定義, 它會(huì)存在于輸出文件中的已初始化數(shù)據(jù)節(jié).
`extern int i;'
一個(gè)未定義符號(hào),它不占用空間. 必須在另外某一處對(duì)它有一個(gè)定義,或一個(gè)普通符號(hào)
`int i;'
一個(gè)普通符號(hào).如果對(duì)于一個(gè)變量只有(一個(gè)或多個(gè))普通符號(hào), 它進(jìn)入輸出文件的未初始化數(shù)據(jù)域. 連
接器會(huì)把同一變量的多個(gè)普通符號(hào)合并成一個(gè)單一的符號(hào). 如果他們有不同的大小, 它采用最大的一
個(gè). 如果是對(duì)同一變量的定義,連接器把一個(gè)普通符號(hào)轉(zhuǎn)化為一個(gè)聲明.
'--warn-common'選項(xiàng)可以產(chǎn)生五種類(lèi)型的警告. 每種警告由兩行組成: 第一行描述遇到的符號(hào), 第二
行描述遇到的前一個(gè)具有相同名字的符號(hào). 一個(gè)或兩個(gè)都可能成為普通符號(hào).
1. 把一個(gè)普通符號(hào)轉(zhuǎn)化為一個(gè)引用, 因?yàn)檫@個(gè)符號(hào)已經(jīng)有一個(gè)定義了.
FILE(SECTION): warning: common of `SYMBOL'
overridden by definition
FILE(SECTION): warning: defined here
2. 把一個(gè)普通符號(hào)轉(zhuǎn)化為一個(gè)引用,因?yàn)橛龅搅说诙䝼(gè)關(guān)于符號(hào)的定義. 這跟前一種情況相同,除了符
號(hào)遇到的順序相反.
FILE(SECTION): warning: definition of `SYMBOL'
overriding common
FILE(SECTION): warning: common is here
3. 把一個(gè)普通符號(hào)跟前一個(gè)相同大小的普通符號(hào)合并.
FILE(SECTION): warning: multiple common
of `SYMBOL'
FILE(SECTION): warning: previous common is here
4. 把一個(gè)普通符號(hào)跟前一個(gè)更大的普通符號(hào)合并.
FILE(SECTION): warning: common of `SYMBOL'
overridden by larger common
FILE(SECTION): warning: larger common is here
5. 把一個(gè)普通符號(hào)跟前一個(gè)更小的普通符號(hào)合并. 這跟前一種情況相同, 除了遇到的符號(hào)的順序不同.
FILE(SECTION): warning: common of `SYMBOL'
overriding smaller common
FILE(SECTION): warning: smaller common is here
`--warn-constructors'
如果有全局結(jié)構(gòu)體被使用到了,警告. 這只對(duì)很少的一些目標(biāo)文件格式有用. 對(duì)于COFF或ELF格式, 連
接器不同探測(cè)到全局結(jié)構(gòu)體的使用.
`--warn-multiple-gp'
如果在輸出文件中,需要多個(gè)全局指針值,警告. 這只對(duì)特定的處理器有意義, 比如Alpha. 特別的,有
些處理器在特定的節(jié)中放入很大的常數(shù)值. 一個(gè)特殊的寄存器(全局指針)指向這個(gè)節(jié)的中間部分, 所
以通過(guò)一個(gè)基地址寄存器相關(guān)的地址模式,這個(gè)常數(shù)可以很容易地被載入. 因?yàn)檫@個(gè)基寄存器相關(guān)模式
的偏移值是固定的而且很小(比如,16位), 這會(huì)限制常量池的最大尺寸. 所以,一個(gè)很大的問(wèn)題是,為了
能夠定位所有可能的常數(shù),經(jīng)常需要使用多個(gè)全局指針值. 這個(gè)選項(xiàng)在這種情況發(fā)生時(shí)產(chǎn)生一條警告.
`--warn-once'
對(duì)于每一個(gè)未定義符號(hào)只警告一次, 而不是在每一個(gè)用到它的模塊中警告一次.
`--warn-section-align'
如果輸出節(jié)的地址因?yàn)閷?duì)齊被改變了,警告. 通常, 對(duì)齊會(huì)被輸入節(jié)設(shè)置. 如果'SECTION'命令沒(méi)有指
定節(jié)的起始地址, 地址就會(huì)被隱式改變.
`--whole-archive'
對(duì)于每一個(gè)在命令行中'--whole-archive'選項(xiàng)后面出現(xiàn)的檔案文件, 在連接中包含檔案文件中的所有
目標(biāo)文件, 而不是為需要的目標(biāo)文件搜索檔案文件. 這在把一個(gè)檔案文件轉(zhuǎn)化為一個(gè)共享庫(kù)時(shí)使用, 把
所有的目標(biāo)放到最終的共享庫(kù)中. 這個(gè)選項(xiàng)可以被多次使用.
在GCC中使用這個(gè)選項(xiàng)需要注意兩點(diǎn): 首先,GCC不知道這個(gè)選項(xiàng), 所以,你必須使用'-Wl, -whole-archive'.
第二, 不要忘了在你的檔案文件列表的后面使用'-Wl, -no-whole-archive',因?yàn)镚CC會(huì)把它自己的檔
案列表加到你的連接后面, 而這可能并不是你所預(yù)期的.
`--wrap SYMBOL'
對(duì)SYMBOL符號(hào)使用包裝函數(shù). 任何未定義的對(duì)SYMBOL符號(hào)的引用會(huì)被解析成'_wrap_SYMBOL'. 而任何未定義的對(duì)'_real_SYMBOL'的引用會(huì)被解析成SYMBOL.
這可以用來(lái)為系統(tǒng)函靈敏提供一個(gè)包裝. 包裝函靈敏應(yīng)當(dāng)被叫做'__wrap_SYMBOL'. 如果需要調(diào)用這個(gè)函數(shù), 那就應(yīng)該調(diào)用'__real_SYMBOL'
這里是一個(gè)沒(méi)什么實(shí)用價(jià)值的例子:
void *
__wrap_malloc (int c)
{
printf ("malloc called with %ld\n", c);
return __real_malloc ©;
}
如果你使用'--wrap malloc'把這節(jié)代碼跟其他的代碼連接, 那所有的對(duì)'malloc'的調(diào)用都會(huì)調(diào)用
'__wrap_malloc'函數(shù). 而在'__wrap_malloc'中的'__real_malloc'會(huì)調(diào)用真正的'malloc'函數(shù).
你有可能也希望提供一個(gè)'__real_malloc'函數(shù), 這樣,不帶有'--wrap'的連接器也會(huì)成功連接.如果
你這樣做了, 你不能把'__real_malloc'的定義跟'__wrap_malloc'放到同一個(gè)文件中;如果放在一起
匯編器會(huì)在連接器之前把調(diào)用解析成真正的'malloc'.
`--enable-new-dtags'
`--disable-new-dtags'
連接器可以在ELF中創(chuàng)建一個(gè)新的動(dòng)態(tài)標(biāo)簽. 但是舊的ELF系統(tǒng)可能不理解這個(gè). 如果你指定了
'--enable-new-dtags',動(dòng)態(tài)標(biāo)簽會(huì)按需要被創(chuàng)建. 如果你指定了'--disable-new-dtags',那不會(huì)有
新的動(dòng)態(tài)標(biāo)簽被創(chuàng)建. 缺省地,新的動(dòng)態(tài)標(biāo)簽不會(huì)被創(chuàng)建. 注意這些選項(xiàng)只在ELF系統(tǒng)中有效.
i386 PE平臺(tái)的特定選項(xiàng).
-----------------------------------
i386 PE連接器支持'-shared'選項(xiàng), 它使輸出文件為一個(gè)動(dòng)態(tài)鏈接庫(kù)(DLL),而不是一個(gè)普通的可執(zhí)行文件. 在使用這個(gè)選項(xiàng)的時(shí)候,你應(yīng)當(dāng)為輸出文件取名'*.dll',另外, 連接器完全支持標(biāo)準(zhǔn)的'*.def'文件, 這類(lèi)文件可以在連接器命令行上象一個(gè)目標(biāo)文件一樣被指定(實(shí)際上, 它應(yīng)當(dāng)被放在它從中導(dǎo)出符號(hào)的那個(gè)檔案文件前面,以保證它們象一個(gè)普通的目標(biāo)文件一樣被連接進(jìn)去.)
除了對(duì)所有平臺(tái)通用的那些選項(xiàng)外,i386 PE連接器支持一些只對(duì)i386平臺(tái)專(zhuān)有的命令行選面. 帶有值的選項(xiàng)應(yīng)當(dāng)用空格或等號(hào)把它跟值分隔開(kāi).
`--add-stdcall-alias'
如果給出這個(gè)選項(xiàng), 帶有標(biāo)準(zhǔn)調(diào)用后綴(@NN)的符號(hào)會(huì)被剝掉后綴后導(dǎo)出.
`--base-file FILE'
使用FILE作為文件名,該文件是存放用'dlltool'產(chǎn)生 DLL文件時(shí)所需的所有重定位符的基地址的.(這
個(gè)選面是i386 PE平臺(tái)所專(zhuān)有的]
`--dll'
創(chuàng)建一個(gè)DLL文件而不是一個(gè)常規(guī)可執(zhí)行文件. 你可能在一個(gè)給出的'.def'文件中使用'-shared'或指
定'LIBRARY'.
`--enable-stdcall-fixup'
`--disable-stdcall-fixup'
如果連接器發(fā)現(xiàn)有符號(hào)不能解析, 它會(huì)試圖進(jìn)行'失真連接',即尋找另一個(gè)定義的符號(hào),它們只是在
符號(hào)名的格式上不同(cdecl vs stdcall),并把符號(hào)解析為找到的這個(gè)符號(hào). 比如, 一個(gè)未定義的符
號(hào)'_foo'可能被連接到函數(shù)'_foo@12', 或者一個(gè)未定義的符號(hào)'_bar@16'可能被連接到函數(shù)'_bar'.
如果連接器這么做了, 它會(huì)打印出一條警告信息, 因?yàn)樵谡G闆r下,這會(huì)連接失敗, 但有時(shí),由第三
方庫(kù)產(chǎn)生的導(dǎo)入庫(kù)可能需要這個(gè)特性. 如果你指定了'--enable-stdcall-fixup', 這個(gè)特性會(huì)被完全
開(kāi)啟,警告信息也不會(huì)打印出來(lái). 如果你指定了'--disable-stdcall-fixup',這個(gè)特性被關(guān)閉,而且這
樣的錯(cuò)誤匹配會(huì)被認(rèn)為是個(gè)錯(cuò)誤.
`--export-all-symbols'
如果給出這個(gè)選項(xiàng),目標(biāo)中所有由DLL建立的全局符號(hào)會(huì)被DLL導(dǎo)出. 注意這是缺省情況,否則沒(méi)有任何
符號(hào)被導(dǎo)出. 如果符號(hào)由DEF文件顯式地導(dǎo)出,或由函數(shù)本身的屬性隱式地導(dǎo)出, 缺省情況是除非選項(xiàng)
給出,否則不導(dǎo)出任何其他的符號(hào). 注意符號(hào)`DllMain@12',`DllEntryPoint@0',
[email=`DllMainCRTStartup@12']`DllMainCRTStartup@12'[/email]
和`impure_ptr'不會(huì)自動(dòng)被導(dǎo)出.而且,由其他的DLL導(dǎo)入的符號(hào)也不會(huì)被再次導(dǎo)出, 還有指定DLL內(nèi)部布局的符號(hào),比如那些以'_head_'開(kāi)頭,或者以'_iname'結(jié)尾的符號(hào)也不會(huì) 被導(dǎo)出.還有,'libgcc','libstd++','libmingw32'或'crtX.o'中的符號(hào)也不會(huì)被導(dǎo)出. ......
環(huán)境變量
=====================
你可以通過(guò)環(huán)境變量`GNUTARGET', `LDEMULATION'和`COLLECT_NO_DEMANGLE'改變'ld'的行為.
`GNUTARGET'在你沒(méi)有使用'-b'(或者它的同義詞'--format')的時(shí)候,決定輸入文件的格式. 它的值應(yīng)當(dāng)是BFD中關(guān)于輸入格式的一個(gè)名字. 如果環(huán)境中沒(méi)有'GNUTARGET'變量, 'ld'使用目標(biāo)平臺(tái)的缺省格式. 如果'GNUTARGET'被設(shè)為'default', 那BFD就會(huì)通過(guò)檢查二進(jìn)制的輸入文件來(lái)找到輸入格式; 這個(gè)方法通常會(huì)成功, 但會(huì)有潛在的不明確性, 因?yàn)闆](méi)有辦法保證指定一個(gè)目標(biāo)文件格式的魔數(shù)總是唯一的. 但是, 在每一個(gè)系統(tǒng)上的BFD配置程序會(huì)把這個(gè)系統(tǒng)的常規(guī)格式放在搜索列表的首位, 所以不明確性可以通過(guò)這種慣列來(lái)解決.
`LDEMULATION'在你沒(méi)有使用'-m'選項(xiàng)的時(shí)候決定缺省的模擬器. 模擬器可以影響到連接器行為的很多方面, 特別是連接器的缺省連接腳本. 你可以通過(guò)'--verbose'或'-V'選項(xiàng)列出所有可用的模擬器. 如果'-m'選項(xiàng)沒(méi)有使用, 而且`LDEMULATION'環(huán)境變量沒(méi)有定義, 缺省的模擬器跟連接器如何被配置有關(guān).
一般地,連接器缺省狀況下會(huì)重構(gòu)符號(hào).但是,如果在環(huán)境中設(shè)置了`COLLECT_NO_DEMANGLE', 那缺省狀態(tài)下就不會(huì)重構(gòu)符號(hào).這個(gè)環(huán)境變量在GCC的連接包裝程序中會(huì)以相似的方式被使用. 這個(gè)缺省的行為可以被'--demangle' 或'--no-demangle'選項(xiàng)覆蓋.
連接腳本
**************
每個(gè)連接都被一個(gè)'連接腳本'所控制. 這個(gè)腳本是用連接命令語(yǔ)言書(shū)寫(xiě)的.
連接腳本的一個(gè)主要目的是描述輸入文件中的節(jié)如何被映射到輸出文件中,并控制輸出文件的內(nèi)存排布. 幾乎所有的連接腳本只做這兩件事情. 但是,在需要的時(shí)候,連接器腳本還可以指示連接器執(zhí)行很多其他的操作.這通過(guò)下面描述的命令實(shí)現(xiàn).
連接器總是使用連接器腳本的.如果你自己不提供, 連接器會(huì)使用一個(gè)缺省的腳本,這個(gè)腳本是被編譯進(jìn)連接器可執(zhí)行文件的. 你可以使用'--verbose'命令行選項(xiàng)來(lái)顯示缺省的連接器腳本的內(nèi)容. 某些命令行選項(xiàng),比如
'-r'或'-N', 會(huì)影響缺省的連接腳本.
你可以過(guò)使用'-T'命令行選項(xiàng)來(lái)提供你自己的連接腳本. 當(dāng)你這么做的時(shí)候, 你的連接腳本會(huì)替換缺省的連接腳本.
你也可以通過(guò)把連接腳本作為一個(gè)連接器的輸入文件來(lái)隱式地使用它,就象它們是一個(gè)被連接的文件一樣.
基本的連接腳本的概念
============================
我們需要定義一些基本的概念與詞匯以描述連接腳本語(yǔ)言.
連接器把多個(gè)輸入文件合并成單個(gè)輸出文件. 輸出文件和輸入文件都以一種叫做'目標(biāo)文件格式'的數(shù)據(jù)格式形式存在. 每一個(gè)文件被叫做'目標(biāo)文件'. 輸出文件經(jīng)常被叫做'可執(zhí)行文件',但是由于需要,我們也把它叫做目標(biāo)文件. 每一個(gè)目標(biāo)文件中,在其它東西之間,有一個(gè)節(jié)列表.我們有時(shí)把輸入文件的節(jié)叫做輸入節(jié); 相似的,輸出文件中的一個(gè)節(jié)經(jīng)常被叫做輸出節(jié).
一個(gè)目標(biāo)文件中的每一個(gè)節(jié)都有一個(gè)名字和一個(gè)大小尺寸. 大多數(shù)節(jié)還有一個(gè)相關(guān)的數(shù)據(jù)塊, 稱(chēng)為節(jié)內(nèi)容. 某一個(gè)節(jié)可能被標(biāo)式詎'loadable',含義是在輸出文件被執(zhí)行時(shí),這個(gè)節(jié)應(yīng)當(dāng)被載入到內(nèi)存中去. 一個(gè)沒(méi)有內(nèi)容的節(jié)可能是'allocatable', 含義是內(nèi)存中必須為這個(gè)節(jié)開(kāi)辟一塊空間,但是沒(méi)有實(shí)際的內(nèi)容載入到這里(在某些情況下,這塊內(nèi)存必須被標(biāo)式詎零). 一個(gè)既不是loadable也不是allocatable的節(jié)一般含有一些調(diào)試信息.
每一個(gè)loadable或allocatable的輸出節(jié)有兩個(gè)地址. 第一個(gè)是'VMA'或稱(chēng)為虛擬內(nèi)存地址. 這是當(dāng)輸出文件運(yùn)行時(shí)節(jié)所擁有的地址. 第二個(gè)是"LMA', 或稱(chēng)為載入內(nèi)存地址. 這個(gè)節(jié)即將要載入的內(nèi)存地址. 這大多數(shù)情況下這兩個(gè)地址是相同的. 它們兩個(gè)有可能不同的一個(gè)例子是當(dāng)一個(gè)數(shù)據(jù)節(jié)在ROM中時(shí), 當(dāng)程序啟動(dòng)時(shí),被拷貝到RAM中(這個(gè)技術(shù)經(jīng)常被用在基于ROM的系統(tǒng)中進(jìn)行全局變量的初始化). 在這種情況下, ROM地址就是LMA, 而RAM地址就是VMA.
你可以通過(guò)使用帶有'-h'選項(xiàng)的'objdump'來(lái)察看目標(biāo)文件中的節(jié).
每一個(gè)目標(biāo)文件還有一個(gè)關(guān)于符號(hào)的列表, 被稱(chēng)為'符號(hào)表'. 一個(gè)符號(hào)可能是定義過(guò)了的,也可能是未定義的.
每一個(gè)符號(hào)有一個(gè)名字, 而且每一個(gè)定義的符號(hào)有一個(gè)地址. 如果你把一個(gè)C/C++程序編譯為一個(gè)目標(biāo)文件,對(duì)于每一個(gè)定義的函數(shù)和全局或靜態(tài)變量,你為得到一個(gè)定義的符號(hào). 每一個(gè)在輸入文件中只是一個(gè)引用而未定義的函數(shù)或全局變量會(huì)變成一個(gè)未定義的符號(hào).
你可以使用'nm'程序來(lái)看一個(gè)目標(biāo)文件中的符號(hào), 或者使用'objdump'程序帶有'-t'選項(xiàng).
連接腳本的格式
====================
連接腳本是文本文件.
你寫(xiě)了一系列的命令作為一個(gè)連接腳本. 每一個(gè)命令是一個(gè)帶有參數(shù)的關(guān)鍵字,或者是一個(gè)對(duì)符號(hào)的賦值. 你可以用分號(hào)分隔命令. 空格一般被忽略.
文件名或格式名之類(lèi)的字符串一般可以被直接鍵入. 如果文件名含有特殊字符,比如一般作為分隔文件名用的逗號(hào), 你可以把文件名放到雙引號(hào)中. 文件名中間無(wú)法使用雙引號(hào).
你可以象在C語(yǔ)言中一樣,在連接腳本中使用注釋, 用'/*'和'*/'隔開(kāi). 就像在C中,注釋在語(yǔ)法上等同于空格.
簡(jiǎn)單的連接腳本示例
============================
許多腳本是相當(dāng)?shù)暮?jiǎn)單的.
可能的最簡(jiǎn)單的腳本只含有一個(gè)命令: 'SECTIONS'. 你可以使用'SECTIONS'來(lái)描述輸出文件的內(nèi)存布局.
'SECTIONS'是一個(gè)功能很強(qiáng)大的命令. 這里這們會(huì)描述一個(gè)很簡(jiǎn)單的使用. 讓我們假設(shè)你的程序只有代碼節(jié), 初始化過(guò)的數(shù)據(jù)節(jié), 和未初始化過(guò)的數(shù)據(jù)節(jié). 這些會(huì)存在于'.text','.data'和'.bss'節(jié), 另外, 讓我們進(jìn)一步假設(shè)在你的輸入文件中只有這些節(jié).
對(duì)于這個(gè)例子, 我們說(shuō)代碼應(yīng)當(dāng)被載入到地址'0x10000'處, 而數(shù)據(jù)應(yīng)當(dāng)從0x8000000處開(kāi)始. 下面是一個(gè)實(shí)現(xiàn)這個(gè)功能的腳本:
SECTIONS
{
. = 0x10000;
.text : { *(.text) }
. = 0x8000000;
.data : { *(.data) }
.bss : { *(.bss) }
}
你使用關(guān)鍵字'SECTIONS'寫(xiě)了這個(gè)SECTIONS命令, 后面跟有一串放在花括號(hào)中的符號(hào)賦值和輸出節(jié)描述的內(nèi)容.
上例中, 在'SECTIONS'命令中的第一行是對(duì)一個(gè)特殊的符號(hào)'.'賦值, 這是一個(gè)定位計(jì)數(shù)器. 如果你沒(méi)有以其它的方式指定輸出節(jié)的地址(其他方式在后面會(huì)描述), 那地址值就會(huì)被設(shè)為定位計(jì)數(shù)器的現(xiàn)有值. 定位計(jì)數(shù)器然后被加上輸出節(jié)的尺寸. 在'SECTIONS'命令的開(kāi)始處, 定位計(jì)數(shù)器擁有值'0'.
第二行定義一個(gè)輸出節(jié),'.text'. 冒號(hào)是語(yǔ)法需要,現(xiàn)在可以被忽略. 節(jié)名后面的花括號(hào)中,你列出所有應(yīng)當(dāng)被放入到這個(gè)輸出節(jié)中的輸入節(jié)的名字. '*'是一個(gè)通配符,匹配任何文件名. 表達(dá)式'*(.text)'意思是所有的輸入文件中的'.text'輸入節(jié).
因?yàn)楫?dāng)輸出節(jié)'.text'定義的時(shí)候, 定位計(jì)數(shù)器的值是'0x10000',連接器會(huì)把輸出文件中的'.text'節(jié)的地址設(shè)為'0x10000'.
余下的內(nèi)容定義了輸出文件中的'.data'節(jié)和'.bss'節(jié). 連接器會(huì)把'.data'輸出節(jié)放到地址'0x8000000'處. 連接器放好'.data'輸出節(jié)之后, 定位計(jì)數(shù)器的值是'0x8000000'加上'.data'輸出節(jié)的長(zhǎng)度. 得到的結(jié)果是連接器會(huì)把'.bss'輸出節(jié)放到緊接'.data'節(jié)后面的位置.
連接器會(huì)通過(guò)在必要時(shí)增加定位計(jì)數(shù)器的值來(lái)保證每一個(gè)輸出節(jié)具有它所需的對(duì)齊. 在這個(gè)例子中, 為'.text'和'.data'節(jié)指定的地址會(huì)滿足對(duì)齊約束, 但是連接器可能會(huì)需要在'.data'和'.bss'節(jié)之間創(chuàng)建一個(gè)小的缺口.
就這樣,這是一個(gè)簡(jiǎn)單但完整的連接腳本.
簡(jiǎn)單的連接腳本命令.
=============================
在本章中,我們會(huì)描述一些簡(jiǎn)單的腳本命令.
設(shè)置入口點(diǎn).
-----------------------
在運(yùn)行一個(gè)程序時(shí)第一個(gè)被執(zhí)行到的指令稱(chēng)為"入口點(diǎn)". 你可以使用'ENTRY'連接腳本命令來(lái)設(shè)置入口點(diǎn).參數(shù)是一個(gè)符號(hào)名:
ENTRY(SYMBOL)
有多種不同的方法來(lái)設(shè)置入口點(diǎn).連接器會(huì)通過(guò)按順序嘗試以下的方法來(lái)設(shè)置入口點(diǎn), 如果成功了,就會(huì)停止.
* `-e'入口命令行選項(xiàng);
* 連接腳本中的`ENTRY(SYMBOL)'命令;
* 如果定義了start, 就使用start的值;
* 如果存在,就使用'.text'節(jié)的首地址;
* 地址`0'.
處理文件的命令.
---------------------------
有幾個(gè)處理文件的連接腳本命令.
`INCLUDE FILENAME'
在當(dāng)前點(diǎn)包含連接腳本文件FILENAME. 在當(dāng)前路徑下或用'-L'選項(xiàng)指定的所有路徑下搜索這個(gè)文件,
你可以嵌套使用'INCLUDE'達(dá)10層.
`INPUT(FILE, FILE, ...)'
`INPUT(FILE FILE ...)'
'INPUT'命令指示連接器在連接時(shí)包含文件, 就像它們是在命令行上指定的一樣.
比如,如果你在連接的時(shí)候總是要包含文件'subr.o',但是你對(duì)每次連接時(shí)要在命令行上輸入感到厭煩
, 你就可以在你的連接腳本中輸入'INPUT (subr.o).
事實(shí)上,如果你喜歡,你可以把你所有的輸入文件列在連接腳本中, 然后在連接的時(shí)候什么也不需要,
只要一個(gè)'-T'選項(xiàng)就夠了.
在一個(gè)'系統(tǒng)根前綴'被配置的情況下, 一個(gè)文件名如果以'/'字符打頭, 并且腳本也存放在系統(tǒng)根
前綴的某個(gè)子目錄下, 文件名就會(huì)被在系統(tǒng)根前綴下搜索. 否則連接器就會(huì)企圖打開(kāi)當(dāng)前目錄下的文
件. 如果沒(méi)有發(fā)現(xiàn), 連接器會(huì)通過(guò)檔案庫(kù)搜索路徑進(jìn)行搜索.
如果你使用了'INPUT (-lFILE)', 'ld'會(huì)把文件名轉(zhuǎn)換為'libFILE.a', 就象命令行參數(shù)'-l'一樣.
當(dāng)你在一個(gè)隱式連接腳本中使用'INPUT'命令的時(shí)候, 文件就會(huì)在連接時(shí)連接腳本文件被包含的點(diǎn)上
被包含進(jìn)來(lái). 這會(huì)影響到檔案搜索.
`GROUP(FILE, FILE, ...)'
`GROUP(FILE FILE ...)'
除了文件必須全是檔案文件之外, 'GROUP'命令跟'INPUT'相似, 它們會(huì)被反復(fù)搜索,直至沒(méi)有未定義
的引用被創(chuàng)建.
`OUTPUT(FILENAME)'
'OUTPUT'命令命名輸出文件. 在連接腳本中使用'OUTPUT(FILENAME)'命令跟在命令行中使用'-o
FILENAME'命令是完全等效的. 如果兩個(gè)都使用了, 那命令行選項(xiàng)優(yōu)先.
你可以使用'OUTPUT'命令為輸出文件創(chuàng)建一個(gè)缺省的文件名,而不是常用的'a.out'.
`SEARCH_DIR(PATH)'
`SEARCH_DIR'命令給'ld'用于搜索檔案文件的路徑中再增加新的路徑. 使用`SEARCH_DIR(PATH)'跟在命令行上使用'-L PATH'選項(xiàng)是完全等效的. 如果兩個(gè)都使用了, 那連接器會(huì)兩個(gè)路徑都搜索. 用命
令行選項(xiàng)指定的路徑首先被搜索.
`STARTUP(FILENAME)'
除了FILENAME會(huì)成為第一個(gè)被連接的輸入文件, 'STARTUP'命令跟'INPUT'命令完全相似, 就象這個(gè)文件是在命令行上第一個(gè)被指定的文件一樣. 如果在一個(gè)系統(tǒng)中, 入口點(diǎn)總是存在于第一個(gè)文件中,那
這個(gè)就很有用.
處理目標(biāo)文件格式的命令.
-----------------------------------------
有兩個(gè)處理目標(biāo)文件格式的連接腳本命令.
`OUTPUT_formAT(BFDNAME)'
`OUTPUT_formAT(DEFAULT, BIG, LITTLE)'
`OUTPUT_formAT'命令為輸出文件使用的BFD格式命名. 使用`OUTPUT_formAT(BFDNAME)'跟在命令行上
使用'-oformat BFDNAME'是完全等效的. 如果兩個(gè)都使用了, 命令行選項(xiàng)優(yōu)先.
你可在使用`OUTPUT_formAT'時(shí)帶有三個(gè)參數(shù)以使用不同的基于'-EB'和'-EL'的命令行選項(xiàng)的格式.
如果'-EB'和'-EL'都沒(méi)有使用, 那輸出格式會(huì)是第一個(gè)參數(shù)DEFAULT, 如果使用了'-EB',輸出格式會(huì)是
第二個(gè)參數(shù)BIG, 如果使用了'-EL', 輸出格式會(huì)是第三個(gè)參數(shù), LITTLE.
比如, 缺省的基于MIPS ELF平臺(tái)連接腳本使用如下命令:
OUTPUT_formAT(elf32-bigmips, elf32-bigmips, elf32-littlemips)
這表示缺省的輸出文件格式是'elf32-bigmips', 但是當(dāng)用戶使用'-EL'命令行選項(xiàng)的時(shí)候, 輸出文件就會(huì)
被以`elf32-littlemips'格式創(chuàng)建.
`TARGET(BFDNAME)'
'TARGET'命令在讀取輸入文件時(shí)命名BFD格式. 它會(huì)影響到后來(lái)的'INPUT'和'GROUP'命令. 這個(gè)命令跟在命令行上使用`-b BFDNAME'相似. 如果使用了'TARGET'命令但`OUTPUT_formAT'沒(méi)有指定, 最后的'TARGET'命令也被用來(lái)設(shè)置輸出文件的格式.
其它的連接腳本命令.
----------------------------
還有一些其它的連接腳本命令.
`ASSERT(EXP, MESSAGE)'
確保EXP不等于零,如果等于零, 連接器就會(huì)返回一個(gè)錯(cuò)誤碼退出,并打印出MESSAGE.
`EXTERN(SYMBOL SYMBOL ...)'
強(qiáng)制SYMBOL作為一個(gè)無(wú)定義的符號(hào)輸入到輸出文件中去. 這樣做了,可能會(huì)引發(fā)從標(biāo)準(zhǔn)庫(kù)中連接一些
節(jié)外的庫(kù). 你可以為每一個(gè)EXTERN'列出幾個(gè)符號(hào), 而且你可以多次使用'EXTERN'. 這個(gè)命令跟'-u'
命令行選項(xiàng)具有相同的效果.
`FORCE_COMMON_ALLOCATION'
這個(gè)命令跟命令行選項(xiàng)'-d'具有相同的效果: 就算指定了一個(gè)可重定位的輸出文件('-r'),也讓'ld'
為普通符號(hào)分配空間.
`INHIBIT_COMMON_ALLOCATION'
這個(gè)命令跟命令行選項(xiàng)`--no-define-common'具有相同的效果: 就算是一個(gè)不可重位輸出文件, 也讓
'ld'忽略為普通符號(hào)分配的空間.
`NOCROSSREFS(SECTION SECTION ...)'
這個(gè)命令在遇到在某些特定的節(jié)之間引用的時(shí)候會(huì)產(chǎn)生一條錯(cuò)誤信息.
在某些特定的程序中, 特別是在使用覆蓋技術(shù)的嵌入式系統(tǒng)中, 當(dāng)一個(gè)節(jié)被載入內(nèi)存時(shí),另外一個(gè)節(jié)
就不會(huì)在內(nèi)存中. 任何在兩個(gè)節(jié)之間的直接引用都會(huì)是一個(gè)錯(cuò)誤. 比如, 如果節(jié)1中的代碼調(diào)用了另
一個(gè)節(jié)中的一個(gè)函數(shù),這就會(huì)產(chǎn)生一個(gè)錯(cuò)誤.
`NOCROSSREFS'命令帶有一個(gè)輸出節(jié)名字的列表. 如果'ld'遇到任何在這些節(jié)之間的交叉引用, 它就
會(huì)報(bào)告一個(gè)錯(cuò)誤,并返回一個(gè)非零退出碼. 注意, `NOCROSSREFS'命令使用輸出節(jié)名,而不是輸入節(jié)名.
`OUTPUT_ARCH(BFDARCH)'
指定一個(gè)特定的輸出機(jī)器架構(gòu). 這個(gè)參數(shù)是BFD庫(kù)中使用的一個(gè)名字. 你可以通過(guò)使用帶有'-f'選項(xiàng)
的'objdump'程序來(lái)查看一個(gè)目標(biāo)文件的架構(gòu).
為符號(hào)賦值.
===========================
你可以在一個(gè)連接腳本中為一個(gè)符號(hào)賦一個(gè)值. 這會(huì)把一個(gè)符號(hào)定義為一個(gè)全局符號(hào).
簡(jiǎn)單的賦值.
------------------
你可以使用所有的C賦值符號(hào)為一個(gè)符號(hào)賦值.
`SYMBOL = EXPRESSION ;'
`SYMBOL += EXPRESSION ;'
`SYMBOL -= EXPRESSION ;'
`SYMBOL *= EXPRESSION ;'
`SYMBOL /= EXPRESSION ;'
`SYMBOL >= EXPRESSION ;'
`SYMBOL &= EXPRESSION ;'
`SYMBOL |= EXPRESSION ;'
第一個(gè)情況會(huì)把SYMBOL定義為值EXPRESSION. 其它情況下, SYMBOL必須是已經(jīng)定義了的, 而值會(huì)作出相應(yīng)的調(diào)整.
特殊符號(hào)名'.'表示定位計(jì)數(shù)器. 你只可以在'SECTIONS'命令中使用它.
EXPRESSION后面的分號(hào)是必須的.
表達(dá)式下面會(huì)定義.
你在寫(xiě)表達(dá)式賦值的時(shí)候,可以把它們作為單獨(dú)的部分,也可以作為'SECTIONS'命令中的一個(gè)語(yǔ)句,或者作為'SECTIONS'命令中輸出節(jié)描述的一個(gè)部分.
符號(hào)所在的節(jié)會(huì)被設(shè)置成表達(dá)式所在的節(jié).
下面是一個(gè)關(guān)于在三處地方使用符號(hào)賦值的例子:
floating_point = 0;
SECTIONS
{
.text :
{
*(.text)
_etext = .;
}
_bdata = (. + 3) & ~ 3;
.data : { *(.data) }
}
在這個(gè)例子中, 符號(hào)`floating_point'被定義為零. 符號(hào)'-etext'會(huì)被定義為前面一個(gè)'.text'節(jié)尾部的地址. 而符號(hào)'_bdata'會(huì)被定義為'.text'輸出節(jié)后面的一個(gè)向上對(duì)齊到4字節(jié)邊界的一個(gè)地址值.
PROVIDE
-------
在某些情況下, 一個(gè)符號(hào)被引用到的時(shí)候只在連接腳本中定義,而不在任何一個(gè)被連接進(jìn)來(lái)的目標(biāo)文件中定義. 這種做法是比較明智的. 比如, 傳統(tǒng)的連接器定義了一個(gè)符號(hào)'etext'. 但是, ANSI C需要用戶能夠把'etext'作為一個(gè)函數(shù)使用而不會(huì)產(chǎn)生錯(cuò)誤. 'PROVIDE'關(guān)鍵字可以被用來(lái)定義一個(gè)符號(hào), 比如'etext', 這個(gè)定義只在它被引用到的時(shí)候有效,而在它被定義的時(shí)候無(wú)效.語(yǔ)法是 `PROVIDE(SYMBOL = EXPRESSION)'.
下面是一個(gè)關(guān)于使用'PROVIDE'定義'etext'的例子:
SECTIONS
{
.text :
{
*(.text)
_etext = .;
PROVIDE(etext = .);
}
}
在這個(gè)例子中, 如果程序定義了一個(gè)'_etext'(帶有一個(gè)前導(dǎo)下劃線), 連接器會(huì)給出一個(gè)重定義錯(cuò)誤. 如果, 程序定義了一個(gè)'etext'(不帶前導(dǎo)下劃線), 連接器會(huì)默認(rèn)使用程序中的定義. 如果程序引用了'etext'但不定義它, 連接器會(huì)使用連接腳本中的定義.
SECTIONS命令
================
'SECTIONS'命令告訴連接器如何把輸入節(jié)映射到輸出節(jié), 并如何把輸出節(jié)放入到內(nèi)存中.
'SECTIONS'命令的格式如下:
SECTIONS
{
SECTIONS-COMMAND
SECTIONS-COMMAND
...
}
每一個(gè)SECTIONS-COMMAND可能是如下的一種:
* 一個(gè)'ENTRY'命令.
* 一個(gè)符號(hào)賦值.
* 一個(gè)輸出節(jié)描述.
* 一個(gè)重疊描述.
'ENTRY'命令和符號(hào)賦值在'SECTIONS'命令中是允許的, 這是為了方便在這些命令中使用定位計(jì)數(shù)器. 這也可以讓連接腳本更容易理解, 因?yàn)槟憧梢栽诟幸饬x的地方使用這些命令來(lái)控制輸出文件的布局.
輸出節(jié)描述和重疊描述在下面描述.
如果你在連接腳本中不使用'SECTIONS'命令, 連接器會(huì)按在輸入文件中遇到的節(jié)的順序把每一個(gè)輸入節(jié)放到同名的輸出節(jié)中. 如果所有的輸入節(jié)都在第一個(gè)文件中存在,那輸出文件中的節(jié)的順序會(huì)匹配第一個(gè)輸入文件中的節(jié)的順序. 第一個(gè)節(jié)會(huì)在地址零處.
輸出節(jié)描述
--------------------------
一個(gè)完整的輸出節(jié)的描述應(yīng)該是這個(gè)樣子的:
SECTION [ADDRESS] [(TYPE)] : [AT(LMA)]
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP]
大多數(shù)輸出節(jié)不使用這里的可選節(jié)屬性.
SECTION邊上的空格是必須的, 所以節(jié)名是明確的. 冒號(hào)跟花括號(hào)也是必須的. 斷行和其他的空格是可選的.
每一個(gè)OUTPUT-SECTION-COMMAND可能是如下的情況:
* 一個(gè)符號(hào)賦值.
* 一個(gè)輸入節(jié)描述.
* 直接包含的數(shù)據(jù)值.
* 一個(gè)特定的輸出節(jié)關(guān)鍵字.
輸出節(jié)名.
-------------------
輸出節(jié)的名字是SECTION. SECTION必須滿足你的輸出格式的約束. 在一個(gè)只支持限制數(shù)量的節(jié)的格式中,比如'a.out',這個(gè)名字必須是格式支持的節(jié)名中的一個(gè)(比如, 'a.out'只允許'.text', '.data'或'.bss').如果輸出格式支持任意數(shù)量的節(jié), 但是只支持?jǐn)?shù)字,而沒(méi)有名字(就像Oasys中的情況), 名字應(yīng)當(dāng)以一個(gè)雙引號(hào)中的數(shù)值串的形式提供.一個(gè)節(jié)名可以由任意數(shù)量的字符組成,但是一個(gè)含有任意非常用字符(比如逗號(hào))的字句必須用雙引號(hào)引起來(lái).
輸出節(jié)描述
--------------------------
ADDRESS是關(guān)于輸出節(jié)中VMS的一個(gè)表達(dá)式. 如果你不提供ADDRESS, 連接器會(huì)基于REGION(如果存在)設(shè)置它,或者基于定位計(jì)數(shù)器的當(dāng)前值.
如果你提供了ADDRESS, 那輸出節(jié)的地址會(huì)被精確地設(shè)為這個(gè)值. 如果你既不提供ADDRESS也不提供REGION, 那輸出節(jié)的地址會(huì)被設(shè)為當(dāng)前的定位計(jì)數(shù)器向上對(duì)齊到輸出節(jié)需要的對(duì)齊邊界的值. 輸出節(jié)的對(duì)齊要求是所有輸入節(jié)中含有的對(duì)齊要求中最嚴(yán)格的一個(gè).
比如:
.text . : { *(.text) }

.text : { *(.text) }
有細(xì)微的不同. 第一個(gè)會(huì)把'.text'輸出節(jié)的地址設(shè)為當(dāng)前定位計(jì)數(shù)器的值. 第二個(gè)會(huì)把它設(shè)為定位計(jì)數(shù)器的當(dāng)前值向上對(duì)齊到'.text'輸入節(jié)中對(duì)齊要求最嚴(yán)格的一個(gè)邊界.
ADDRESS可以是任意表達(dá)式; 比如,如果你需要把節(jié)對(duì)齊對(duì)0x10字節(jié)邊界,這樣就可以讓低四字節(jié)的節(jié)地址值為零, 你可以這樣做:
.text ALIGN(0x10) : { *(.text) }
這個(gè)語(yǔ)句可以正常工作,因?yàn)?ALIGN'返回當(dāng)前的定位計(jì)數(shù)器,并向上對(duì)齊到指定的值.
指定一個(gè)節(jié)的地址會(huì)改變定位計(jì)數(shù)器的值.
輸入節(jié)描述
-------------------------
最常用的輸出節(jié)命令是輸入節(jié)描述.
輸入節(jié)描述是最基本的連接腳本操作. 你使用輸出節(jié)來(lái)告訴連接器在內(nèi)存中如何布局你的程序. 你使用輸入節(jié)來(lái)告訴連接器如何把輸入文件映射到你的內(nèi)存中.
輸入節(jié)基礎(chǔ)
---------------------------
一個(gè)輸入節(jié)描述由一個(gè)文件名后跟有可選的括號(hào)中的節(jié)名列表組成.
文件名和節(jié)名可以通配符形式出現(xiàn), 這個(gè)我們以后再介紹.
最常用的輸入節(jié)描述是包含在輸出節(jié)中的所有具有特定名字的輸入節(jié). 比如, 包含所有輸入'.text'節(jié),你可以這樣寫(xiě):
*(.text)
這里,'*'是一個(gè)通配符,匹配所有的文件名. 為把一部分文件排除在匹配的名字通配符之外, EXCLUDE_FILE可以用來(lái)匹配所有的除了在EXCLUDE_FILE列表中指定的文件.比如:
(*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors))
會(huì)讓除了`crtend.o'文件和`otherfile.o'文件之外的所有的文件中的所有的.ctors節(jié)被包含進(jìn)來(lái).
有兩種方法包含多于一個(gè)的節(jié):
*(.text .rdata)
*(.text) *(.rdata)
上面兩句的區(qū)別在于'.text'和'.rdata'輸入節(jié)的輸出節(jié)中出現(xiàn)的順序不同. 在第一個(gè)例子中, 兩種節(jié)會(huì)交替出現(xiàn),并以連接器的輸入順序排布. 在第二個(gè)例子中,所有的'.text'輸入節(jié)會(huì)先出現(xiàn),然后是所有的'.rdata'節(jié).
你可以指定文件名,以從一個(gè)特定的文件中包含節(jié). 如果一個(gè)或多個(gè)你的文件含有特殊的數(shù)據(jù)在內(nèi)存中需要特殊的定位,你可以這樣做. 比如:
data.o(.data)
如果你使用一個(gè)不帶有節(jié)列表的文件名, 那輸入文件中的所有的節(jié)會(huì)被包含到輸出節(jié)中. 通常不會(huì)這樣做, 但是在某些場(chǎng)合下這個(gè)可能非常有用. 比如:
data.o
當(dāng)你使用一個(gè)不含有任何通配符的文件名時(shí), 連接器首先會(huì)查看你是否在連接命令行上指定了文件名或者在'INPUT'命令中. 如果你沒(méi)有, 連接器會(huì)試圖把這個(gè)文件作為一個(gè)輸入文件打開(kāi), 就像它在命令行上出現(xiàn)一樣.注意這跟'INPUT'命令不一樣, 因?yàn)檫B接器會(huì)在檔案搜索路徑中搜索文件.
輸入節(jié)通配符
---------------------------------
在一個(gè)輸入節(jié)描述中, 文件名或者節(jié)名,或者兩者同時(shí)都可以是通配符形式.
文件名通配符'*'在很多例子中都可以看到,這是一個(gè)簡(jiǎn)單的文件名通配符形式.
通配符形式跟Unix Shell中使用的一樣.
`*'
匹配任意數(shù)量的字符.
`?'
匹配單個(gè)字符.
`[CHARS]'
匹配CHARS中的任意單個(gè)字符; 字符'-'可以被用來(lái)指定字符的方訌, 比如[a-z]匹配任意小字字符.
`\'
轉(zhuǎn)義其后的字符.
當(dāng)一個(gè)文件名跟一個(gè)通配符匹配時(shí), 通配符字符不會(huì)匹配一個(gè)'/'字符(在UNIX系統(tǒng)中用來(lái)分隔目錄名), 一個(gè)含有單個(gè)'*'字符的形式是個(gè)例外; 它總是匹配任意文件名, 不管它是否含有'/'. 在一個(gè)節(jié)名中, 通配符字
符會(huì)匹配'/'字符.
文件名通配符只匹配那些在命令行或在'INPUT'命令上顯式指定的文件. 連接器不會(huì)通過(guò)搜索目錄來(lái)展開(kāi)通配符.
如果一個(gè)文件名匹配多于一個(gè)通配符, 或者如果一個(gè)文件名顯式出現(xiàn)同時(shí)又匹配了一個(gè)通配符, 連接器會(huì)使用第一次匹配到的連接腳本. 比如, 下面的輸入節(jié)描述序列很可能就是錯(cuò)誤的,因?yàn)?data.o'規(guī)則沒(méi)有被使用:
.data : { *(.data) }
.data1 : { data.o(.data) }
通常, 連接器會(huì)把匹配通配符的文件和節(jié)按在連接中被看到的順序放置. 你可以通過(guò)'SORT'關(guān)鍵字改變它, 它出現(xiàn)在括號(hào)中的通配符之前(比如, 'SORT(.text*)'). 當(dāng)'SORT'關(guān)鍵字被使用時(shí), 連接器會(huì)在把文件和節(jié)放到輸出文件中之前按名字順序重新排列它們.
如果你對(duì)于輸入節(jié)被放置到哪里去了感到很困惑, 那可以使用'-M'連接選項(xiàng)來(lái)產(chǎn)生一個(gè)位圖文件. 位圖文件會(huì)精確顯示輸入節(jié)是如何被映射到輸出節(jié)中的.
這個(gè)例子顯示了通配符是如何被用來(lái)區(qū)分文件的. 這個(gè)連接腳本指示連接器把所有的'.text'節(jié)放到'.text'中, 把所有的'.bss'節(jié)放到'.bss'. 連接器會(huì)把所有的來(lái)自文件名以一個(gè)大寫(xiě)字母開(kāi)始的文件中的'.data'節(jié)放進(jìn)'.DATA'節(jié)中; 對(duì)于所有其他文件, 連接器會(huì)把'.data'節(jié)放進(jìn)'.data'節(jié)中.
SECTIONS {
.text : { *(.text) }
.DATA : { [A-Z]*(.data) }
.data : { *(.data) }
.bss : { *(.bss) }
}
輸入節(jié)中的普通符號(hào).
-----------------------------------
對(duì)于普通符號(hào),需要一個(gè)特殊的標(biāo)識(shí), 因?yàn)樵诤芏嗄繕?biāo)格式中, 普通符號(hào)沒(méi)有一個(gè)特定的輸入節(jié). 連接器會(huì)把普通符號(hào)處理成好像它們?cè)谝粋(gè)叫做'COMMON'的節(jié)中.
你可能像使用帶有其他輸入節(jié)的文件名一樣使用帶有'COMMON'節(jié)的文件名。你可以通過(guò)這個(gè)把來(lái)自一個(gè)特定輸入文件的普通符號(hào)放入一個(gè)節(jié)中,同時(shí)把來(lái)自其它輸入文件的普通符號(hào)放入另一個(gè)節(jié)中。
在大多數(shù)情況下,輸入文件中的普通符號(hào)會(huì)被放到輸出文件的'.bss'節(jié)中。比如:
.bss { *(.bss) *(COMMON) }
有些目標(biāo)文件格式具有多于一個(gè)的普通符號(hào)。比如,MIPS ELF目標(biāo)文件格式區(qū)分標(biāo)準(zhǔn)普通符號(hào)和小普通符號(hào)。在這種情況下,連接器會(huì)為其他類(lèi)型的普通符號(hào)使用一個(gè)不同的特殊節(jié)名。 在MIPS ELF的情況中, 連接器為標(biāo)準(zhǔn)普通符號(hào)使用'COMMON',并且為小普通符號(hào)使用'.common'。這就允許你把不同類(lèi)型的普通符號(hào)映射到內(nèi)存的不同位置。
在一些老的連接腳本上,你有時(shí)會(huì)看到'[COMMON]'。這個(gè)符號(hào)現(xiàn)在已經(jīng)過(guò)時(shí)了, 它等效于'*(COMMON)'。
輸入節(jié)和垃圾收集
---------------------------------------
當(dāng)連接時(shí)垃圾收集正在使用中時(shí)('--gc-sections'),這在標(biāo)識(shí)那些不應(yīng)該被排除在外的節(jié)時(shí)非常有用。這
是通過(guò)在輸入節(jié)的通配符入口外面加上'KEEP()'實(shí)現(xiàn)的,比如'KEEP(*(.init))'或者'KEEP(SORT(*)(.sorts))
'。
輸入節(jié)示例
---------------------
接下來(lái)的例子是一個(gè)完整的連接腳本。它告訴連接器去讀取文件'all.o'中的所有節(jié),并把它們放到輸出節(jié)'outputa'的開(kāi)始位置處, 該輸出節(jié)是從位置'0x10000'處開(kāi)始的。 從文件'foo.o'中來(lái)的所有節(jié)'.input1'在同一個(gè)輸出節(jié)中緊密排列。 從文件'foo.o'中來(lái)的所有節(jié)'.input2'全部放入到輸出節(jié)'outputb'中,后面跟上從'foo1.o'中來(lái)的節(jié)'.input1'。來(lái)自所有文件的所有余下的'.input1'和'.input2'節(jié)被寫(xiě)入到輸出節(jié)'outputc'中。
SECTIONS {
outputa 0x10000 :
{
all.o
foo.o (.input1)
}
outputb :
{
foo.o (.input2)
foo1.o (.input1)
}
outputc :
{
*(.input1)
*(.input2)
}
}
輸出節(jié)數(shù)據(jù)
-------------------
你可以通過(guò)使用輸出節(jié)命令'BYTE','SHORT','LONG','QUAD',或者'SQUAD'在輸出節(jié)中顯式包含幾個(gè)字節(jié)的數(shù)據(jù)每一個(gè)關(guān)鍵字后面都跟上一個(gè)圓括號(hào)中的要存入的值。表達(dá)式的值被存在當(dāng)前的定位計(jì)數(shù)器的值處。
‘BYTE’,‘SHORT’,‘LONG’‘QUAD’命令分別存儲(chǔ)一個(gè),兩個(gè),四個(gè),八個(gè)字節(jié)。存入字節(jié)后,定位計(jì)數(shù)器的值加上被存入的字節(jié)數(shù)。
比如,下面的命令會(huì)存入一字節(jié)的內(nèi)容1,后面跟上四字節(jié),其內(nèi)容是符號(hào)'addr'的值。
BYTE(1)
LONG(addr)
當(dāng)使用64位系統(tǒng)時(shí),‘QUAD’和‘SQUAD’是相同的;它們都會(huì)存儲(chǔ)8字節(jié),或者說(shuō)是64位的值。而如果軟硬件系統(tǒng)都是32位的,一個(gè)表達(dá)式就會(huì)被作為32位計(jì)算。在這種情況下,‘QUAD’存儲(chǔ)一個(gè)32位值,并把它零擴(kuò)展到64位, 而‘SQUAD’會(huì)把32位值符號(hào)擴(kuò)展到64位。
如果輸出文件的目標(biāo)文件格式有一個(gè)顯式的endianness,它在正常的情況下,值就會(huì)被以這種endianness存儲(chǔ)當(dāng)一個(gè)目標(biāo)文件格式?jīng)]有一個(gè)顯式的endianness時(shí), 值就會(huì)被以第一個(gè)輸入目標(biāo)文件的endianness存儲(chǔ)。
注意, 這些命令只在一個(gè)節(jié)描述內(nèi)部才有效,而不是在它們之間, 所以,下面的代碼會(huì)使連接器產(chǎn)生一個(gè)錯(cuò)誤信息:
SECTIONS { .text : { *(.text) } LONG(1) .data : { *(.data) } }
而這個(gè)才是有效的:
SECTIONS { .text : { *(.text) ; LONG(1) } .data : { *(.data) } }
你可能使用‘FILL’命令來(lái)為當(dāng)前節(jié)設(shè)置填充樣式。它后面跟有一個(gè)括號(hào)中的表達(dá)式。任何未指定的節(jié)內(nèi)內(nèi)存區(qū)域(比如,因?yàn)檩斎牍?jié)的對(duì)齊要求而造成的裂縫)會(huì)以這個(gè)表達(dá)式的值進(jìn)行填充。一個(gè)'FILL'語(yǔ)句會(huì)覆蓋到它本身在節(jié)定義中出現(xiàn)的位置后面的所有內(nèi)存區(qū)域;通過(guò)引入多個(gè)‘FILL’語(yǔ)句,你可以在輸出節(jié)的不同位置擁有不同的填充樣式。
這個(gè)例子顯示如何在未被指定的內(nèi)存區(qū)域填充'0x90':
FILL(0x90909090)
‘FILL’命令跟輸出節(jié)的‘=FILLEXP’屬性相似,但它只影響到節(jié)內(nèi)跟在‘FILL’命令后面的部分,而不是整個(gè)節(jié)。如果兩個(gè)都用到了,那‘FILL’命令優(yōu)先。
輸出節(jié)關(guān)鍵字
-----------------------
有兩個(gè)關(guān)鍵字作為輸出節(jié)命令的形式出現(xiàn)。
`CREATE_OBJECT_SYMBOLS'
這個(gè)命令告訴連接器為每一個(gè)輸入文件創(chuàng)建一個(gè)符號(hào)。而符號(hào)的名字正好就是相關(guān)輸入文件的名字。
而每一個(gè)符號(hào)的節(jié)就是`CREATE_OBJECT_SYMBOLS'命令出現(xiàn)的那個(gè)節(jié)。
這個(gè)命令一直是a.out目標(biāo)文件格式特有的。 它一般不為其它的目標(biāo)文件格式所使用。
`CONSTRUCTORS'
當(dāng)使用a.out目標(biāo)文件格式進(jìn)行連接的時(shí)候, 連接器使用一組不常用的結(jié)構(gòu)以支持C++的全局構(gòu)造函
數(shù)和析構(gòu)函數(shù)。當(dāng)連接不支持專(zhuān)有節(jié)的目標(biāo)文件格式時(shí), 比如ECOFF和XCOFF,連接器會(huì)自動(dòng)辯識(shí)C++全局構(gòu)造函數(shù)和析構(gòu)函數(shù)的名字。對(duì)于這些目標(biāo)文件格式,‘CONSTRUCTORS’命令告訴連接器把構(gòu)造函數(shù)信息放到‘CONSTRUCTORS’命令出現(xiàn)的那個(gè)輸出節(jié)中。對(duì)于其它目標(biāo)文件格式,‘CONSTRUCTORS’
命令被忽略。
符號(hào)`__CTOR_LIST__'標(biāo)識(shí)全局構(gòu)造函數(shù)的開(kāi)始,而符號(hào)`__DTOR_LIST'標(biāo)識(shí)結(jié)束。這個(gè)列表的第一個(gè)WORD是入口的數(shù)量,緊跟在后面的是每一個(gè)構(gòu)造函數(shù)和析構(gòu)函數(shù)的地址,再然后是一個(gè)零WORD。編譯器必須安排如何實(shí)際運(yùn)行代碼。對(duì)于這些目標(biāo)文件格式,GNU C++通常從一個(gè)`__main'子程序中調(diào)用構(gòu)造函數(shù),而對(duì)`__main'的調(diào)用自動(dòng)被插入到`main'的啟動(dòng)代碼中。GNU C++通常使用'atexit'運(yùn)行析構(gòu)函數(shù),或者直接從函數(shù)'exit'中運(yùn)行。
對(duì)于像‘COFF’或‘ELF’這樣支持專(zhuān)有節(jié)名的目標(biāo)文件格式,GNU C++通常會(huì)把全局構(gòu)造函數(shù)與析構(gòu)函數(shù)的地址值放到'.ctors'和'.dtors'節(jié)中。把下面的代碼序列放到你的連接腳本中去,這樣會(huì)構(gòu)建
出GNU C++運(yùn)行時(shí)代碼希望見(jiàn)到的表類(lèi)型。
__CTOR_LIST__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
*(.ctors)
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
*(.dtors)
LONG(0)
__DTOR_END__ = .;
如果你正使用GNU C++支持來(lái)進(jìn)行優(yōu)先初始化,那它提供一些可以控制全局構(gòu)造函數(shù)運(yùn)行順序的功能,你必須在連接時(shí)給構(gòu)造函數(shù)排好序以保證它們以正確的順序被執(zhí)行。當(dāng)使用'CONSTRUCTORS'命令時(shí),替代為`SORT(CONSTRUCTORS)'。當(dāng)使用'.ctors'和'dtors'節(jié)時(shí),使用`*(SORT(.ctors))'和`*(SORT(.dtors))' 而不是`*(.ctors)'和`*(.dtors)'。
通常,編譯器和連接器會(huì)自動(dòng)處理這些事情,并且你不必親自關(guān)心這些事情。但是,當(dāng)你正在使用
C++,并自己編寫(xiě)連接腳本時(shí),你可能就要考慮這些事情了。
輸出節(jié)的丟棄。
-------------------------
連接器不會(huì)創(chuàng)建那些不含有任何內(nèi)容的輸出節(jié)。這是為了引用那些可能出現(xiàn)或不出現(xiàn)在任何輸入文件中的輸入節(jié)時(shí)方便。比如:
.foo { *(.foo) }
如果至少在一個(gè)輸入文件中有'.foo'節(jié),它才會(huì)在輸出文件中創(chuàng)建一個(gè)'.foo'節(jié)
如果你使用了其它的而不是一個(gè)輸入節(jié)描述作為一個(gè)輸出節(jié)命令,比如一個(gè)符號(hào)賦值,那這個(gè)輸出節(jié)總是被創(chuàng)建,即使沒(méi)有匹配的輸入節(jié)也會(huì)被創(chuàng)建。
一個(gè)特殊的輸出節(jié)名`/DISCARD/'可以被用來(lái)丟棄輸入節(jié)。任何被分配到名為`/DISCARD/'的輸出節(jié)中的輸入節(jié)不包含在輸出文件中。
輸出節(jié)屬性
-------------------------
上面,我們已經(jīng)展示了一個(gè)完整的輸出節(jié)描述,看下去就象這樣:
SECTION [ADDRESS] [(TYPE)] : [AT(LMA)]
{
OUTPUT-SECTION-COMMAND
OUTPUT-SECTION-COMMAND
...
} [>REGION] [AT>LMA_REGION] [:PHDR :PHDR ...] [=FILLEXP]
我們已經(jīng)介紹了SECTION, ADDRESS, 和OUTPUT-SECTION-COMMAND. 在這一節(jié)中,我們將介紹余下的節(jié)屬性。
輸出節(jié)類(lèi)型
...................
每一個(gè)輸出節(jié)可以有一個(gè)類(lèi)型。類(lèi)型是一個(gè)放在括號(hào)中的關(guān)鍵字,已定義的類(lèi)型如下所示:
`NOLOAD'
這個(gè)節(jié)應(yīng)當(dāng)被標(biāo)式詎不可載入,所以當(dāng)程序運(yùn)行時(shí),它不會(huì)被載入到內(nèi)存中。
`DSECT'
`COPY'
`INFO'
`OVERLAY'
支持這些類(lèi)型名只是為了向下兼容,它們很少使用。它們都具有相同的效果:這個(gè)節(jié)應(yīng)當(dāng)被標(biāo)式詎不
可分配,所以當(dāng)程序運(yùn)行時(shí),沒(méi)有內(nèi)存為這個(gè)節(jié)分配。
連接器通;谟成涞捷敵龉(jié)的輸入節(jié)來(lái)設(shè)置輸出節(jié)的屬性。你可以通過(guò)使用節(jié)類(lèi)型來(lái)重設(shè)這個(gè)屬性,
比如,在下面的腳本例子中,‘ROM’節(jié)被定址在內(nèi)存地址零處,并且在程序運(yùn)行時(shí)不需要被載入。
‘ROM’節(jié)的內(nèi)容會(huì)正常出現(xiàn)在連接輸出文件中。
SECTIONS {
ROM 0 (NOLOAD) : { ... }
...
}
輸出節(jié)LMA
..................
每一個(gè)節(jié)有一個(gè)虛地址(VMA)和一個(gè)載入地址(LMA);出現(xiàn)在輸出節(jié)描述中的地址表達(dá)式設(shè)置VMS
連接器通常把LMA跟VMA設(shè)成相等。你可以通過(guò)使用‘AT’關(guān)鍵字改變這個(gè)。跟在關(guān)鍵字‘AT’后面的表達(dá)式LMA指定節(jié)的載入地址;蛘,通過(guò)`AT>LMA_REGION'表達(dá)式, 你可以為節(jié)的載入地址指定一個(gè)內(nèi)存區(qū)域。
這個(gè)特性是為了便于建立ROM映像而設(shè)計(jì)的。比如,下面的連接腳本創(chuàng)建了三個(gè)輸出節(jié):一個(gè)叫做‘.text’從地址‘0x1000’處開(kāi)始,一個(gè)叫‘.mdata’,盡管它的VMA是'0x2000',它會(huì)被載入到'.text'節(jié)的后面,最后一個(gè)叫做‘.bss’是用來(lái)放置未初始化的數(shù)據(jù)的,其地址從'0x3000'處開(kāi)始。符號(hào)'_data'被定義為值'0x2000', 它表示定位計(jì)數(shù)器的值是VMA的值,而不是LMA。
SECTIONS
{
.text 0x1000 : { *(.text) _etext = . ; }
.mdata 0x2000 :
AT ( ADDR (.text) + SIZEOF (.text) )
{ _data = . ; *(.data); _edata = . ; }
.bss 0x3000 :
{ _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;}
}
這個(gè)連接腳本產(chǎn)生的程序使用的運(yùn)行時(shí)初始化代碼會(huì)包含象下面所示的一些東西,以把初始化后的數(shù)據(jù)從ROM映像中拷貝到它的運(yùn)行時(shí)地址中去。注意這節(jié)代碼是如何利用好連接腳本定義的符號(hào)的。
extern char _etext, _data, _edata, _bstart, _bend;
char *src = &_etext;
char *dst = &_data;
/* ROM has data at end of text; copy it. */
while (dst REGION'把一個(gè)節(jié)賦給前面已經(jīng)定義的一個(gè)內(nèi)存區(qū)域。
這里有一個(gè)簡(jiǎn)單的例子:
MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 }
SECTIONS { ROM : { *(.text) } >rom }
輸出節(jié)Phdr


本文來(lái)自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/5039/showart_354505.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專(zhuān)區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP