日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LDS文件格式分析

發(fā)布時(shí)間:2023/12/31 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LDS文件格式分析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近在看Linux內(nèi)核時(shí),總是遇到一些和連接腳本相關(guān)的東東,搞得人一頭霧水,終于下定決心把它搞明白,寫下一點(diǎn)心得,希望對和我一樣的人有所幫助!

連接腳本的格式
====================

連接腳本是文本文件.

你寫了一系列的命令作為一個(gè)連接腳本. 每一個(gè)命令是一個(gè)帶有參數(shù)的關(guān)鍵字,或者是一個(gè)對符號的賦值. 你可
以用分號分隔命令. 空格一般被忽略.

文件名或格式名之類的字符串一般可以被直接鍵入. 如果文件名含有特殊字符,比如一般作為分隔文件名用的逗
號, 你可以把文件名放到雙引號中. 文件名中間無法使用雙引號.

你可以象在C語言中一樣,在連接腳本中使用注釋, 用'/*'和'*/'隔開. 就像在C中,注釋在語法上等同于空格.

簡單的連接腳本示例
============================

許多腳本是相當(dāng)?shù)暮唵蔚?

可能的最簡單的腳本只含有一個(gè)命令: 'SECTIONS'. 你可以使用'SECTIONS'來描述輸出文件的內(nèi)存布局.

'SECTIONS'是一個(gè)功能很強(qiáng)大的命令. 這里這們會(huì)描述一個(gè)很簡單的使用. 讓我們假設(shè)你的程序只有代碼節(jié),
初始化過的數(shù)據(jù)節(jié), 和未初始化過的數(shù)據(jù)節(jié). 這些會(huì)存在于'.text','.data'和'.bss'節(jié), 另外, 讓我們進(jìn)一
步假設(shè)在你的輸入文件中只有這些節(jié).

對于這個(gè)例子, 我們說代碼應(yīng)當(dāng)被載入到地址'0x10000'處, 而數(shù)據(jù)應(yīng)當(dāng)從0x8000000處開始. 下面是一個(gè)實(shí)現(xiàn)
這個(gè)功能的腳本:

? ?SECTIONS
? ?{
? ? ?. = 0x10000;
? ? ?.text : { *(.text) }
? ? ?. = 0x8000000;
? ? ?.data : { *(.data) }
? ? ?.bss : { *(.bss) }
? ?}

你使用關(guān)鍵字'SECTIONS'寫了這個(gè)SECTIONS命令, 后面跟有一串放在花括號中的符號賦值和輸出節(jié)描述的內(nèi)容.

上例中, 在'SECTIONS'命令中的第一行是對一個(gè)特殊的符號'.'賦值, 這是一個(gè)定位計(jì)數(shù)器. 如果你沒有以其
它的方式指定輸出節(jié)的地址(其他方式在后面會(huì)描述), 那地址值就會(huì)被設(shè)為定位計(jì)數(shù)器的現(xiàn)有值. 定位計(jì)數(shù)器
然后被加上輸出節(jié)的尺寸. 在'SECTIONS'命令的開始處, 定位計(jì)數(shù)器擁有值'0'.

第二行定義一個(gè)輸出節(jié),'.text'. 冒號是語法需要,現(xiàn)在可以被忽略. 節(jié)名后面的花括號中,你列出所有應(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é)的長度. 得到的結(jié)果是連接器會(huì)
把'.bss'輸出節(jié)放到緊接'.data'節(jié)后面的位置.

連接器會(huì)通過在必要時(shí)增加定位計(jì)數(shù)器的值來保證每一個(gè)輸出節(jié)具有它所需的對齊. 在這個(gè)例子中, 為'.text'
和'.data'節(jié)指定的地址會(huì)滿足對齊約束, 但是連接器可能會(huì)需要在'.data'和'.bss'節(jié)之間創(chuàng)建一個(gè)小的缺口.

就這樣,這是一個(gè)簡單但完整的連接腳本.

簡單的連接腳本命令.
=============================

在本章中,我們會(huì)描述一些簡單的腳本命令.

設(shè)置入口點(diǎn).
-----------------------

在運(yùn)行一個(gè)程序時(shí)第一個(gè)被執(zhí)行到的指令稱為"入口點(diǎn)". 你可以使用'ENTRY'連接腳本命令來設(shè)置入口點(diǎn).參數(shù)
是一個(gè)符號名:
? ?ENTRY(SYMBOL)

有多種不同的方法來設(shè)置入口點(diǎn).連接器會(huì)通過按順序嘗試以下的方法來設(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',但是你對每次連接時(shí)要在命令行上輸入感到厭煩
, 你就可以在你的連接腳本中輸入'INPUT (subr.o).

事實(shí)上,如果你喜歡,你可以把你所有的輸入文件列在連接腳本中, 然后在連接的時(shí)候什么也不需要,
只要一個(gè)'-T'選項(xiàng)就夠了.

在一個(gè)'系統(tǒng)根前綴'被配置的情況下, 一個(gè)文件名如果以'/'字符打頭, 并且腳本也存放在系統(tǒng)根
前綴的某個(gè)子目錄下, 文件名就會(huì)被在系統(tǒng)根前綴下搜索. 否則連接器就會(huì)企圖打開當(dāng)前目錄下的文
件. 如果沒有發(fā)現(xiàn), 連接器會(huì)通過檔案庫搜索路徑進(jìn)行搜索.

如果你使用了'INPUT (-lFILE)', 'ld'會(huì)把文件名轉(zhuǎn)換為'libFILE.a', 就象命令行參數(shù)'-l'一樣.

當(dāng)你在一個(gè)隱式連接腳本中使用'INPUT'命令的時(shí)候, 文件就會(huì)在連接時(shí)連接腳本文件被包含的點(diǎn)上
被包含進(jìn)來. 這會(huì)影響到檔案搜索.

`GROUP(FILE, FILE, ...)'
`GROUP(FILE FILE ...)'
除了文件必須全是檔案文件之外, 'GROUP'命令跟'INPUT'相似, 它們會(huì)被反復(fù)搜索,直至沒有未定義
的引用被創(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'都沒有使用, 那輸出格式會(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ì)影響到后來的'INPUT'和'GROUP'命令. 這個(gè)命令跟
在命令行上使用`-b BFDNAME'相似. 如果使用了'TARGET'命令但`OUTPUT_formAT'沒有指定, 最后的
'TARGET'命令也被用來設(shè)置輸出文件的格式.

其它的連接腳本命令.
----------------------------

還有一些其它的連接腳本命令.

`ASSERT(EXP, MESSAGE)'
確保EXP不等于零,如果等于零, 連接器就會(huì)返回一個(gè)錯(cuò)誤碼退出,并打印出MESSAGE.

`EXTERN(SYMBOL SYMBOL ...)'
強(qiáng)制SYMBOL作為一個(gè)無定義的符號輸入到輸出文件中去. 這樣做了,可能會(huì)引發(fā)從標(biāo)準(zhǔn)庫中連接一些
節(jié)外的庫. 你可以為每一個(gè)EXTERN'列出幾個(gè)符號, 而且你可以多次使用'EXTERN'. 這個(gè)命令跟'-u'
命令行選項(xiàng)具有相同的效果.

`FORCE_COMMON_ALLOCATION'
這個(gè)命令跟命令行選項(xiàng)'-d'具有相同的效果: 就算指定了一個(gè)可重定位的輸出文件('-r'),也讓'ld'
為普通符號分配空間.

`INHIBIT_COMMON_ALLOCATION'
這個(gè)命令跟命令行選項(xiàng)`--no-define-common'具有相同的效果: 就算是一個(gè)不可重位輸出文件, 也讓
'ld'忽略為普通符號分配的空間.

`NOCRO×××EFS(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ò)誤.

`NOCRO×××EFS'命令帶有一個(gè)輸出節(jié)名字的列表. 如果'ld'遇到任何在這些節(jié)之間的交叉引用, 它就
會(huì)報(bào)告一個(gè)錯(cuò)誤,并返回一個(gè)非零退出碼. 注意, `NOCRO×××EFS'命令使用輸出節(jié)名,而不是輸入節(jié)名.

`OUTPUT_ARCH(BFDARCH)'
指定一個(gè)特定的輸出機(jī)器架構(gòu). 這個(gè)參數(shù)是BFD庫中使用的一個(gè)名字. 你可以通過使用帶有'-f'選項(xiàng)
的'objdump'程序來查看一個(gè)目標(biāo)文件的架構(gòu).

為符號賦值.
===========================

你可以在一個(gè)連接腳本中為一個(gè)符號賦一個(gè)值. 這會(huì)把一個(gè)符號定義為一個(gè)全局符號.

簡單的賦值.
------------------

你可以使用所有的C賦值符號為一個(gè)符號賦值.

`SYMBOL = EXPRESSION ;'
`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)
整.

特殊符號名'.'表示定位計(jì)數(shù)器. 你只可以在'SECTIONS'命令中使用它.

EXPRESSION后面的分號是必須的.

表達(dá)式下面會(huì)定義.

你在寫表達(dá)式賦值的時(shí)候,可以把它們作為單獨(dú)的部分,也可以作為'SECTIONS'命令中的一個(gè)語句,或者作為
'SECTIONS'命令中輸出節(jié)描述的一個(gè)部分.

符號所在的節(jié)會(huì)被設(shè)置成表達(dá)式所在的節(jié).

下面是一個(gè)關(guān)于在三處地方使用符號賦值的例子:

? ?floating_point = 0;
? ?SECTIONS
? ?{
? ? ?.text :
? ? ? ?{
? ? ? ? ?*(.text)
? ? ? ? ?_etext = .;
? ? ? ?}
? ? ?_bdata = (. + 3) & ~ 3;
? ? ?.data : { *(.data) }
? ?}

在這個(gè)例子中, 符號`floating_point'被定義為零. 符號'-etext'會(huì)被定義為前面一個(gè)'.text'節(jié)尾部的地址.
而符號'_bdata'會(huì)被定義為'.text'輸出節(jié)后面的一個(gè)向上對齊到4字節(jié)邊界的一個(gè)地址值.

PROVIDE
-------

在某些情況下, 一個(gè)符號被引用到的時(shí)候只在連接腳本中定義,而不在任何一個(gè)被連接進(jìn)來的目標(biāo)文件中定
義. 這種做法是比較明智的. 比如, 傳統(tǒng)的連接器定義了一個(gè)符號'etext'. 但是, ANSI C需要用戶能夠把
'etext'作為一個(gè)函數(shù)使用而不會(huì)產(chǎn)生錯(cuò)誤. 'PROVIDE'關(guān)鍵字可以被用來定義一個(gè)符號, 比如'etext', 這個(gè)
定義只在它被引用到的時(shí)候有效,而在它被定義的時(shí)候無效.語法是 `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è)符號賦值.

?* 一個(gè)輸出節(jié)描述.

?* 一個(gè)重疊描述.

'ENTRY'命令和符號賦值在'SECTIONS'命令中是允許的, 這是為了方便在這些命令中使用定位計(jì)數(shù)器. 這也可
以讓連接腳本更容易理解, 因?yàn)槟憧梢栽诟幸饬x的地方使用這些命令來控制輸出文件的布局.

輸出節(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é)名是明確的. 冒號跟花括號也是必須的. 斷行和其他的空格是可選的.

每一個(gè)OUTPUT-SECTION-COMMAND可能是如下的情況:

?* 一個(gè)符號賦值.

?* 一個(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ù)字,而沒有名字(就像Oasys中的情況), 名字應(yīng)當(dāng)以一個(gè)雙引號中的
數(shù)值串的形式提供.一個(gè)節(jié)名可以由任意數(shù)量的字符組成,但是一個(gè)含有任意非常用字符(比如逗號)的字句必須
用雙引號引起來.

輸出節(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ù)器向上對齊到輸出節(jié)需要的對齊邊界的值. 輸出節(jié)的對齊要求是所有輸
入節(jié)中含有的對齊要求中最嚴(yán)格的一個(gè).

比如:
? ?.text . : { *(.text) }


? ?.text : { *(.text) }

有細(xì)微的不同. 第一個(gè)會(huì)把'.text'輸出節(jié)的地址設(shè)為當(dāng)前定位計(jì)數(shù)器的值. 第二個(gè)會(huì)把它設(shè)為定位計(jì)數(shù)器的
當(dāng)前值向上對齊到'.text'輸入節(jié)中對齊要求最嚴(yán)格的一個(gè)邊界.

ADDRESS可以是任意表達(dá)式; 比如,如果你需要把節(jié)對齊對0x10字節(jié)邊界,這樣就可以讓低四字節(jié)的節(jié)地址值為
零, 你可以這樣做:

? ?.text ALIGN(0x10) : { *(.text) }

這個(gè)語句可以正常工作,因?yàn)?#39;ALIGN'返回當(dāng)前的定位計(jì)數(shù)器,并向上對齊到指定的值.

指定一個(gè)節(jié)的地址會(huì)改變定位計(jì)數(shù)器的值.

輸入節(jié)描述
-------------------------

最常用的輸出節(jié)命令是輸入節(jié)描述.

輸入節(jié)描述是最基本的連接腳本操作. 你使用輸出節(jié)來告訴連接器在內(nèi)存中如何布局你的程序. 你使用輸入節(jié)
來告訴連接器如何把輸入文件映射到你的內(nèi)存中.

輸入節(jié)基礎(chǔ)
---------------------------

一個(gè)輸入節(jié)描述由一個(gè)文件名后跟有可選的括號中的節(jié)名列表組成.

文件名和節(jié)名可以通配符形式出現(xiàn), 這個(gè)我們以后再介紹.

最常用的輸入節(jié)描述是包含在輸出節(jié)中的所有具有特定名字的輸入節(jié). 比如, 包含所有輸入'.text'節(jié),你可以
這樣寫:

? ?*(.text)

這里,'*'是一個(gè)通配符,匹配所有的文件名. 為把一部分文件排除在匹配的名字通配符之外, EXCLUDE_FILE可
以用來匹配所有的除了在EXCLUDE_FILE列表中指定的文件.比如:

? ?(*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors))

會(huì)讓除了`crtend.o'文件和`otherfile.o'文件之外的所有的文件中的所有的.ctors節(jié)被包含進(jìn)來.

有兩種方法包含多于一個(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ì)這樣做, 但
是在某些場合下這個(gè)可能非常有用. 比如:

? ?data.o

當(dāng)你使用一個(gè)不含有任何通配符的文件名時(shí), 連接器首先會(huì)查看你是否在連接命令行上指定了文件名或者在
'INPUT'命令中. 如果你沒有, 連接器會(huì)試圖把這個(gè)文件作為一個(gè)輸入文件打開, 就像它在命令行上出現(xiàn)一樣.
注意這跟'INPUT'命令不一樣, 因?yàn)檫B接器會(huì)在檔案搜索路徑中搜索文件.

輸入節(jié)通配符
---------------------------------

在一個(gè)輸入節(jié)描述中, 文件名或者節(jié)名,或者兩者同時(shí)都可以是通配符形式.

文件名通配符'*'在很多例子中都可以看到,這是一個(gè)簡單的文件名通配符形式.

通配符形式跟Unix Shell中使用的一樣.

`*'
匹配任意數(shù)量的字符.

`?'
匹配單個(gè)字符.

`[CHARS]'
匹配CHARS中的任意單個(gè)字符; 字符'-'可以被用來指定字符的方訌, 比如[a-z]匹配任意小字字符.

`\'
轉(zhuǎn)義其后的字符.

當(dāng)一個(gè)文件名跟一個(gè)通配符匹配時(shí), 通配符字符不會(huì)匹配一個(gè)'/'字符(在UNIX系統(tǒng)中用來分隔目錄名), 一個(gè)
含有單個(gè)'*'字符的形式是個(gè)例外; 它總是匹配任意文件名, 不管它是否含有'/'. 在一個(gè)節(jié)名中, 通配符字
符會(huì)匹配'/'字符.

文件名通配符只匹配那些在命令行或在'INPUT'命令上顯式指定的文件. 連接器不會(huì)通過搜索目錄來展開通配
符.

如果一個(gè)文件名匹配多于一個(gè)通配符, 或者如果一個(gè)文件名顯式出現(xiàn)同時(shí)又匹配了一個(gè)通配符, 連接器會(huì)使用
第一次匹配到的連接腳本. 比如, 下面的輸入節(jié)描述序列很可能就是錯(cuò)誤的,因?yàn)?#39;data.o'規(guī)則沒有被使用:

? ?.data : { *(.data) }
? ?.data1 : { data.o(.data) }

通常, 連接器會(huì)把匹配通配符的文件和節(jié)按在連接中被看到的順序放置. 你可以通過'SORT'關(guān)鍵字改變它, 它
出現(xiàn)在括號中的通配符之前(比如, 'SORT(.text*)'). 當(dāng)'SORT'關(guān)鍵字被使用時(shí), 連接器會(huì)在把文件和節(jié)放到
輸出文件中之前按名字順序重新排列它們.

如果你對于輸入節(jié)被放置到哪里去了感到很困惑, 那可以使用'-M'連接選項(xiàng)來產(chǎn)生一個(gè)位圖文件. 位圖文件會(huì)
精確顯示輸入節(jié)是如何被映射到輸出節(jié)中的.

這個(gè)例子顯示了通配符是如何被用來區(qū)分文件的. 這個(gè)連接腳本指示連接器把所有的'.text'節(jié)放到'.text'中, 把所有的'.bss'節(jié)放到'.bss'. 連接器會(huì)把所有的來自文件名以一個(gè)大寫字母開始的文件中的'.data'節(jié)放進(jìn)'.DATA'節(jié)中; 對于所有其他文件, 連接器會(huì)把'.data'節(jié)放進(jìn)'.data'節(jié)中.

? ?SECTIONS {
? ? ?.text : { *(.text) }
? ? ?.DATA : { [A-Z]*(.data) }
? ? ?.data : { *(.data) }
? ? ?.bss : { *(.bss) }
? ?}

輸入節(jié)中的普通符號.
-----------------------------------

對于普通符號,需要一個(gè)特殊的標(biāo)識(shí), 因?yàn)樵诤芏嗄繕?biāo)格式中, 普通符號沒有一個(gè)特定的輸入節(jié). 連接器會(huì)把
普通符號處理成好像它們在一個(gè)叫做'COMMON'的節(jié)中.

你可能像使用帶有其他輸入節(jié)的文件名一樣使用帶有'COMMON'節(jié)的文件名。你可以通過這個(gè)把來自一個(gè)特定輸
入文件的普通符號放入一個(gè)節(jié)中,同時(shí)把來自其它輸入文件的普通符號放入另一個(gè)節(jié)中。

在大多數(shù)情況下,輸入文件中的普通符號會(huì)被放到輸出文件的'.bss'節(jié)中。比如:

? ?.bss { *(.bss) *(COMMON) }

有些目標(biāo)文件格式具有多于一個(gè)的普通符號。比如,MIPS ELF目標(biāo)文件格式區(qū)分標(biāo)準(zhǔn)普通符號和小普通符號。
在這種情況下,連接器會(huì)為其他類型的普通符號使用一個(gè)不同的特殊節(jié)名。 在MIPS ELF的情況中, 連接器
為標(biāo)準(zhǔn)普通符號使用'COMMON',并且為小普通符號使用'.common'。這就允許你把不同類型的普通符號映射到
內(nèi)存的不同位置。

在一些老的連接腳本上,你有時(shí)會(huì)看到'[COMMON]'。這個(gè)符號現(xiàn)在已經(jīng)過時(shí)了, 它等效于'*(COMMON)'。

輸入節(jié)和垃圾收集
---------------------------------------

當(dāng)連接時(shí)垃圾收集正在使用中時(shí)('--gc-sections'),這在標(biāo)識(shí)那些不應(yīng)該被排除在外的節(jié)時(shí)非常有用。這
是通過在輸入節(jié)的通配符入口外面加上'KEEP()'實(shí)現(xiàn)的,比如'KEEP(*(.init))'或者'KEEP(SORT(*)(.sorts))
'。

輸入節(jié)示例
---------------------

接下來的例子是一個(gè)完整的連接腳本。它告訴連接器去讀取文件'all.o'中的所有節(jié),并把它們放到輸出節(jié)
'outputa'的開始位置處, 該輸出節(jié)是從位置'0x10000'處開始的。 從文件'foo.o'中來的所有節(jié)'.input1'
在同一個(gè)輸出節(jié)中緊密排列。 從文件'foo.o'中來的所有節(jié)'.input2'全部放入到輸出節(jié)'outputb'中,后面
跟上從'foo1.o'中來的節(jié)'.input1'。來自所有文件的所有余下的'.input1'和'.input2'節(jié)被寫入到輸出節(jié)
'outputc'中。

? ?SECTIONS {
? ? ?outputa 0x10000 :
? ? ? ?{
? ? ? ?all.o
? ? ? ?foo.o (.input1)
? ? ? ?}
? ? ?outputb :
? ? ? ?{
? ? ? ?foo.o (.input2)
? ? ? ?foo1.o (.input1)
? ? ? ?}
? ? ?outputc :
? ? ? ?{
? ? ? ?*(.input1)
? ? ? ?*(.input2)
? ? ? ?}
? ?}

輸出節(jié)數(shù)據(jù)
-------------------

你可以通過使用輸出節(jié)命令'BYTE','SHORT','LONG','QUAD',或者'SQUAD'在輸出節(jié)中顯式包含幾個(gè)字節(jié)的數(shù)據(jù)
每一個(gè)關(guān)鍵字后面都跟上一個(gè)圓括號中的要存入的值。表達(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)容是符號'addr'的值。

? ?BYTE(1)
? ?LONG(addr)

當(dāng)使用64位系統(tǒng)時(shí),‘QUAD’和‘SQUAD’是相同的;它們都會(huì)存儲(chǔ)8字節(jié),或者說是64位的值。而如果軟硬件
系統(tǒng)都是32位的,一個(gè)表達(dá)式就會(huì)被作為32位計(jì)算。在這種情況下,‘QUAD’存儲(chǔ)一個(gè)32位值,并把它零擴(kuò)展
到64位, 而‘SQUAD’會(huì)把32位值符號擴(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’命令來為當(dāng)前節(jié)設(shè)置填充樣式。它后面跟有一個(gè)括號中的表達(dá)式。任何未指定的節(jié)內(nèi)內(nèi)存
區(qū)域(比如,因?yàn)檩斎牍?jié)的對齊要求而造成的裂縫)會(huì)以這個(gè)表達(dá)式的值進(jìn)行填充。一個(gè)'FILL'語句會(huì)覆蓋到
它本身在節(jié)定義中出現(xiàn)的位置后面的所有內(nèi)存區(qū)域;通過引入多個(gè)‘FILL’語句,你可以在輸出節(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è)符號。而符號的名字正好就是相關(guān)輸入文件的名字。
而每一個(gè)符號的節(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)連接不支持專有節(jié)的目標(biāo)文件格式時(shí), 比如ECOFF和XCOFF,連接器會(huì)自動(dòng)辯識(shí)C++
全局構(gòu)造函數(shù)和析構(gòu)函數(shù)的名字。對于這些目標(biāo)文件格式,‘CONSTRUCTORS’命令告訴連接器把構(gòu)造
函數(shù)信息放到‘CONSTRUCTORS’命令出現(xiàn)的那個(gè)輸出節(jié)中。對于其它目標(biāo)文件格式,‘CONSTRUCTORS’
命令被忽略。

符號`__CTOR_LIST__'標(biāo)識(shí)全局構(gòu)造函數(shù)的開始,而符號`__DTOR_LIST'標(biāo)識(shí)結(jié)束。這個(gè)列表的第一個(gè)
WORD是入口的數(shù)量,緊跟在后面的是每一個(gè)構(gòu)造函數(shù)和析構(gòu)函數(shù)的地址,再然后是一個(gè)零WORD。編譯
器必須安排如何實(shí)際運(yùn)行代碼。對于這些目標(biāo)文件格式,GNU C++通常從一個(gè)`__main'子程序中調(diào)用
構(gòu)造函數(shù),而對`__main'的調(diào)用自動(dòng)被插入到`main'的啟動(dòng)代碼中。GNU C++通常使用'atexit'運(yùn)行
析構(gòu)函數(shù),或者直接從函數(shù)'exit'中運(yùn)行。

對于像‘COFF’或‘ELF’這樣支持專有節(jié)名的目標(biāo)文件格式,GNU C++通常會(huì)把全局構(gòu)造函數(shù)與析構(gòu)
函數(shù)的地址值放到'.ctors'和'.dtors'節(jié)中。把下面的代碼序列放到你的連接腳本中去,這樣會(huì)構(gòu)建
出GNU C++運(yùn)行時(shí)代碼希望見到的表類型。

? ? ? ? ? ? ?__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++支持來進(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++,并自己編寫連接腳本時(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è)符號賦值,那這個(gè)輸出節(jié)總是被
創(chuàng)建,即使沒有匹配的輸入節(jié)也會(huì)被創(chuàng)建。

一個(gè)特殊的輸出節(jié)名`/DISCARD/'可以被用來丟棄輸入節(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é)類型
...................

每一個(gè)輸出節(jié)可以有一個(gè)類型。類型是一個(gè)放在括號中的關(guān)鍵字,已定義的類型如下所示:

`NOLOAD'
這個(gè)節(jié)應(yīng)當(dāng)被標(biāo)式詎不可載入,所以當(dāng)程序運(yùn)行時(shí),它不會(huì)被載入到內(nèi)存中。

`DSECT'
`COPY'
`INFO'
`OVERLAY'
支持這些類型名只是為了向下兼容,它們很少使用。它們都具有相同的效果:這個(gè)節(jié)應(yīng)當(dāng)被標(biāo)式詎不
可分配,所以當(dāng)程序運(yùn)行時(shí),沒有內(nèi)存為這個(gè)節(jié)分配。

連接器通常基于映射到輸出節(jié)的輸入節(jié)來設(shè)置輸出節(jié)的屬性。你可以通過使用節(jié)類型來重設(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è)成相等。你可以通過使用‘AT’關(guān)鍵字改變這個(gè)。跟在關(guān)鍵字‘AT’后面的表達(dá)式
LMA指定節(jié)的載入地址。或者,通過`AT>LMA_REGION'表達(dá)式, 你可以為節(jié)的載入地址指定一個(gè)內(nèi)存區(qū)域。

這個(gè)特性是為了便于建立ROM映像而設(shè)計(jì)的。比如,下面的連接腳本創(chuàng)建了三個(gè)輸出節(jié):一個(gè)叫做‘.text’
從地址‘0x1000’處開始,一個(gè)叫‘.mdata’,盡管它的VMA是'0x2000',它會(huì)被載入到'.text'節(jié)的后面,最
后一個(gè)叫做‘.bss’是用來放置未初始化的數(shù)據(jù)的,其地址從'0x3000'處開始。符號'_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é)代碼是如何利用好連接腳本定義的符號的。

? ?extern char _etext, _data, _edata, _bstart, _bend;
? ?char *src = &_etext;
? ?char *dst = &_data;

? ?/* ROM has data at end of text; copy it. */
? ?while (dst < &_edata) {
? ? ?*dst++ = *src++;
? ?}

? ?/* Zero bss */
? ?for (dst = &_bstart; dst< &_bend; dst++)
? ? ?*dst = 0;

輸出節(jié)區(qū)域
.....................

你可以通過使用`>REGION'把一個(gè)節(jié)賦給前面已經(jīng)定義的一個(gè)內(nèi)存區(qū)域。

這里有一個(gè)簡單的例子:

? ?MEMORY { rom : ORIGIN = 0x1000, LENGTH = 0x1000 }
? ?SECTIONS { ROM : { *(.text) } >rom }

輸出節(jié)Phdr
...................

你可以通過使用`:PHDR'把一個(gè)節(jié)賦給前面已定義的一個(gè)程序段。如果一個(gè)節(jié)被賦給一個(gè)或多個(gè)段,那后來分
配的節(jié)都會(huì)被賦給這些段,除非它們顯式使用了':PHDR'修飾符。你可以使用':NONE'來告訴連接器不要把節(jié)
放到任何一個(gè)段中。

這兒有一個(gè)簡單的例子:

? ?PHDRS { text PT_LOAD ; }
? ?SECTIONS { .text : { *(.text) } :text }

輸出段填充
...................

你可以通過使用'=FILLEXP'為整個(gè)節(jié)設(shè)置填充樣式。FILLEXP是一個(gè)表達(dá)式。任何沒有指定的輸出段內(nèi)的內(nèi)存
區(qū)域(比如,因?yàn)檩斎攵蔚膶R要求而產(chǎn)生的裂縫)會(huì)被填入這個(gè)值。如果填充表達(dá)式是一個(gè)簡單的十六進(jìn)制
值,比如,一個(gè)以'0x'開始的十六進(jìn)制數(shù)字組成的字符串,并且尾部不是'k'或'M',那一個(gè)任意的十六進(jìn)制數(shù)
字長序列可以被用來指定填充樣式;前導(dǎo)零也變?yōu)闃邮降囊徊糠帧τ谒衅渌那闆r,包含一個(gè)附加的括號
或一元操作符'+',那填充樣式是表達(dá)式的最低四字節(jié)的值。在所有的情況下,數(shù)值是big-endian.

你還可以通過在輸出節(jié)命令中使用'FILL'命令來改變填充值。

這里是一個(gè)簡單的例子:
? ?SECTIONS { .text : { *(.text) } =0x90909090 }

覆蓋描述
-------------------

一個(gè)覆蓋描述提供一個(gè)簡單的描述辦法,以描述那些要被作為一個(gè)單獨(dú)內(nèi)存映像的一部分載入內(nèi)存,但是卻要
在同一內(nèi)存地址運(yùn)行的節(jié)。在運(yùn)行時(shí),一些覆蓋管理機(jī)制會(huì)把要被覆蓋的節(jié)按需要拷入或拷出運(yùn)行時(shí)內(nèi)存地址,
并且多半是通過簡單地處理內(nèi)存位。 這個(gè)方法可能非常有用,比如在一個(gè)特定的內(nèi)存區(qū)域比另一個(gè)快時(shí)。

覆蓋是通過‘OVERLAY’命令進(jìn)行描述。‘OVERLAY’命令在‘SECTIONS’命令中使用,就像輸出段描述一樣。
‘OVERLAY’命令的完整語法如下:

? ?OVERLAY [START] : [NOCRO×××EFS] [AT ( LDADDR )]
? ? ?{
? ? ? ?SECNAME1
? ? ? ? ?{
? ? ? ? ? ?OUTPUT-SECTION-COMMAND
? ? ? ? ? ?OUTPUT-SECTION-COMMAND
? ? ? ? ? ?...
? ? ? ? ?} [:PHDR...] [=FILL]
? ? ? ?SECNAME2
? ? ? ? ?{
? ? ? ? ? ?OUTPUT-SECTION-COMMAND
? ? ? ? ? ?OUTPUT-SECTION-COMMAND
? ? ? ? ? ?...
? ? ? ? ?} [:PHDR...] [=FILL]
? ? ? ?...
? ? ?} [>REGION] [:PHDR...] [=FILL]

除了‘OVERLAY’關(guān)鍵字,所有的都是可選的,每一個(gè)節(jié)必須有一個(gè)名字(上面的SECNAME1和SECNAME2)。在
‘OVERLAY’結(jié)構(gòu)中的節(jié)定義跟通常的‘SECTIONS’結(jié)構(gòu)中的節(jié)定義是完全相同的,除了一點(diǎn),就是在‘OVERLAY’
中沒有地址跟內(nèi)存區(qū)域的定義。

節(jié)都被定義為同一個(gè)開始地址。所有節(jié)的載入地址都被排布,使它們在內(nèi)存中從整個(gè)'OVERLAY'的載入地址開
始都是連續(xù)的(就像普通的節(jié)定義,載入地址是可選的,缺省的就是開始地址;開始地址也是可選的,缺省的
是當(dāng)前的定位計(jì)數(shù)器的值。)

如果使用了關(guān)鍵字`NOCRO×××EFS', 并且在節(jié)之間存在引用,連接器就會(huì)報(bào)告一個(gè)錯(cuò)誤。因?yàn)楣?jié)都運(yùn)行在同一
個(gè)地址上,所以一個(gè)節(jié)直接引用另一個(gè)節(jié)中的內(nèi)容是錯(cuò)誤的。

對于'OVERLAY'中的每一個(gè)節(jié),連接器自動(dòng)定義兩個(gè)符號。符號`__load_start_SECNAME'被定義為節(jié)的開始載
入地址。符號`__load_stop_SECNAME'被定義為節(jié)的最后載入地址。SECNAME中的不符合C規(guī)定的任何字符都將
被刪除。C(或者匯編語言)代碼可能使用這些符號在必要的時(shí)間搬移覆蓋代碼。

在覆蓋區(qū)域的最后,定位計(jì)數(shù)器的值被設(shè)為覆蓋區(qū)域的開始地址加上最大的節(jié)的長度。

這里是一個(gè)例子。記住這只會(huì)出現(xiàn)在‘SECTIONS’結(jié)構(gòu)的內(nèi)部。

? ? ?OVERLAY 0x1000 : AT (0x4000)
? ? ?{
? ? ? ?.text0 { o1/*.o(.text) }
? ? ? ?.text1 { o2/*.o(.text) }
? ? ?}

這段代碼會(huì)定義'.text0'和'.text1',它們都從地址0x1000開始。‘.text0'會(huì)被載入到地址0x4000處,而
'.text1'會(huì)被載入到緊隨'.text0'后的位置。下面的幾個(gè)符號會(huì)被定義:`__load_start_text0',
`__load_stop_text0', `__load_start_text1', `__load_stop_text1'.

拷貝'.text1'到覆蓋區(qū)域的C代碼看上去可能會(huì)像下面這樣:

? ? ?extern char __load_start_text1, __load_stop_text1;
? ? ?memcpy ((char *) 0x1000, &__load_start_text1,
? ? ? ? ? ? ?&__load_stop_text1 - &__load_start_text1);

注意'OVERLAY'命令只是為了語法上的便利,因?yàn)樗龅乃惺虑槎伎梢杂酶踊镜拿罴右源妗I厦?br />的例子可以用下面的完全特效的寫法:

? ? ?.text0 0x1000 : AT (0x4000) { o1/*.o(.text) }
? ? ?__load_start_text0 = LOADADDR (.text0);
? ? ?__load_stop_text0 = LOADADDR (.text0) + SIZEOF (.text0);
? ? ?.text1 0x1000 : AT (0x4000 + SIZEOF (.text0)) { o2/*.o(.text) }
? ? ?__load_start_text1 = LOADADDR (.text1);
? ? ?__load_stop_text1 = LOADADDR (.text1) + SIZEOF (.text1);
? ? ?. = 0x1000 + MAX (SIZEOF (.text0), SIZEOF (.text1));



============

連接器在缺省狀態(tài)下被配置為允許分配所有可用的內(nèi)存塊。你可以使用‘MEMORY’命令重新配置這個(gè)設(shè)置。

‘MEMORY’命令描述目標(biāo)平臺(tái)上內(nèi)存塊的位置與長度。你可以用它來描述哪些內(nèi)存區(qū)域可以被連接器使用,
哪些內(nèi)存區(qū)域是要避免使用的。然后你就可以把節(jié)分配到特定的內(nèi)存區(qū)域中。連接器會(huì)基于內(nèi)存區(qū)域設(shè)置節(jié)
的地址,對于太滿的區(qū)域,會(huì)提示警告信息。連接器不會(huì)為了適應(yīng)可用的區(qū)域而攪亂節(jié)。

一個(gè)連接腳本最多可以包含一次'MEMORY'命令。但是,你可以在命令中隨心所欲定義任意多的內(nèi)存塊,語法
如下:

? ?MEMORY
? ? ?{
? ? ? ?NAME [(ATTR)] : ORIGIN = ORIGIN, LENGTH = LEN
? ? ? ?...
? ? ?}

NAME是用在連接腳本中引用內(nèi)存區(qū)域的名字。出了連接腳本,區(qū)域名就沒有任何實(shí)際意義。區(qū)域名存儲(chǔ)在一個(gè)
單獨(dú)的名字空間中,它不會(huì)和符號名,文件名,節(jié)名產(chǎn)生沖突,每一塊內(nèi)存區(qū)域必須有一個(gè)唯一的名字。

ATTR字符串是一個(gè)可選的屬性列表,它指出是否為一個(gè)沒有在連接腳本中進(jìn)行顯式映射地輸入段使用一個(gè)特定
的內(nèi)存區(qū)域。如果你沒有為某些輸入段指定一個(gè)輸出段,連接器會(huì)創(chuàng)建一個(gè)跟輸入段同名的輸出段。如果你定
義了區(qū)域?qū)傩?#xff0c;連接器會(huì)使用它們來為它創(chuàng)建的輸出段選擇內(nèi)存區(qū)域。

ATTR字符串必須包含下面字符中的一個(gè),且必須只包含一個(gè):
`R'
只讀節(jié)。
`W'
? ?可讀寫節(jié)。
`X'
可執(zhí)行節(jié)。
`A'
可分配節(jié)。
`I'
已初始化節(jié)。
`L'
? ?同‘I’
`!'
對前一個(gè)屬性值取反。

如果一個(gè)未映射節(jié)匹配了上面除'!'之外的一個(gè)屬性,它就會(huì)被放入該內(nèi)存區(qū)域。'!'屬性對該測試取反,所以
只有當(dāng)它不匹配上面列出的行何屬性時(shí),一個(gè)未映射節(jié)才會(huì)被放入到內(nèi)存區(qū)域。

ORIGIN是一個(gè)關(guān)于內(nèi)存區(qū)域地始地址的表達(dá)式。在內(nèi)存分配執(zhí)行之前,這個(gè)表達(dá)式必須被求值產(chǎn)生一個(gè)常數(shù),
這意味著你不可以使用任何節(jié)相關(guān)的符號。關(guān)鍵字'ORIGIN'可以被縮寫為'org'或'o'(但是,不可以寫為,比
如‘ORG’)

LEN是一個(gè)關(guān)于內(nèi)存區(qū)域長充(以字節(jié)為單位)的表達(dá)式。就像ORIGIN表達(dá)式,這個(gè)表達(dá)式在分配執(zhí)行前也
必須被求得為一個(gè)常數(shù)值。關(guān)鍵字'LENGTH'可以被簡寫為‘len'或'l'。

在下面的例子中,我們指定兩個(gè)可用于分配的內(nèi)存區(qū)域:一個(gè)從0開始,有256kb長度,另一個(gè)從0x4000000
開始,有4mb長度。連接器會(huì)把那些沒有進(jìn)行顯式映射且是只讀或可執(zhí)行的節(jié)放到'rom'內(nèi)存區(qū)域。并會(huì)把另
外的沒有被顯式映射地節(jié)放入到'ram'內(nèi)存區(qū)域。

? ?MEMORY
? ? ?{
? ? ? ?rom (rx) ?: ORIGIN = 0, LENGTH = 256K
? ? ? ?ram (!rx) : org = 0x40000000, l = 4M
? ? ?}

一旦你定義了一個(gè)內(nèi)存區(qū)域,你也可以指示連接器把指定的輸出段放入到這個(gè)內(nèi)存區(qū)域中,這可以通過使用
'>REGION'輸出段屬性。比如,如果你有一個(gè)名為'mem'的內(nèi)存區(qū)域,你可以在輸出段定義中使用'>mem'。如
果沒有為輸出段指定地址,連接器就會(huì)把地址設(shè)置為內(nèi)存區(qū)域中的下一個(gè)可用的地址。如果總共的映射到一
個(gè)內(nèi)存區(qū)域的輸出段對于區(qū)域來說太大了,連接器會(huì)提示一條錯(cuò)誤信息。

PHDRS命令
=============

ELF目標(biāo)文件格式使用“程序頭”,它也就是人們熟知的“節(jié)”。程序頭描述了程序應(yīng)當(dāng)如何被載入到內(nèi)存中。
你可以通過使用帶有'-p'選項(xiàng)的‘objdump’命令來打印出這個(gè)程序頭。

當(dāng)你在一個(gè)純ELF系統(tǒng)上運(yùn)行ELF程序時(shí),系統(tǒng)的載入程序通過讀取文件頭來計(jì)算得到如何來載入這個(gè)文件。這
只在程序頭被正確設(shè)置的情況下才會(huì)正常工作。本手冊并不打算介紹系統(tǒng)載入程序如何解釋文件頭的相關(guān)細(xì)節(jié)
問題;關(guān)于更多信息,請參閱ELF ABI。

連接順在缺省狀態(tài)下會(huì)自己創(chuàng)建一個(gè)可用的程序頭。但是,在某些情況下,你可能需要更為精確地指定程序頭。
你可以使用命令‘PHDRS’達(dá)到這個(gè)目的。當(dāng)連接器在連接腳本中看到‘PHDRS’命令時(shí),它只會(huì)創(chuàng)建被指定了
的程序頭。

連接器只在產(chǎn)生ELF輸出文件時(shí)關(guān)心‘PHDRS’命令。在其它情況下,連接器只是簡單地忽略‘PHDRS’。

下面是‘PHDRS’命令的語法。單詞‘PHDRS’,‘FILEHDR’,‘AT’和‘FLAGS’都是關(guān)鍵字。

? ?PHDRS
? ?{
? ? ?NAME TYPE [ FILEHDR ] [ PHDRS ] [ AT ( ADDRESS ) ]
? ? ? ? ? ?[ FLAGS ( FLAGS ) ] ;
? ?}

NAME只在連接腳本的‘SECTIONS’命令中引用時(shí)用到。它不會(huì)被放到輸出文件中。程序頭的名字會(huì)被存儲(chǔ)到單獨(dú)
的名字空間中。每一個(gè)程序頭都必須有一個(gè)唯一的名字。

某些特定類型的程序頭描述系統(tǒng)載入程序要從文件中載入到內(nèi)存的節(jié)。在連接腳本中,你通過把可載入的輸出節(jié)放
到段中來指定這些段的內(nèi)容。你可以使用‘:PHDR’輸出節(jié)屬性把一個(gè)節(jié)放到一個(gè)特定的段中。

把某些節(jié)放到多個(gè)段中也是正常的。這僅僅暗示了一個(gè)內(nèi)存段中含有另一個(gè)段。你可以重復(fù)使用‘:PHDR’,在每
一個(gè)應(yīng)當(dāng)含有這個(gè)節(jié)的段中使用它一次。

如果你使用‘:PHDR’把一個(gè)節(jié)放到多個(gè)段中,那連接器把隨后的所有沒有指定‘:PHDR’的可分配節(jié)都放到同一個(gè)
段中。這是為了方便,因?yàn)橥ǔR淮B續(xù)的節(jié)會(huì)被放到一個(gè)單獨(dú)的段中。你可以使用‘:NONE’來覆蓋缺省的段,
告訴連接器不要把節(jié)放到任何一個(gè)段中。

你可能在程序頭類型后面使用‘FILEHDR’和‘PHDRS’關(guān)鍵字來進(jìn)一步描述段的內(nèi)容。‘FILEHDR’關(guān)鍵字表示段應(yīng)
當(dāng)包含ELF文件頭。‘PHDRS’關(guān)鍵字表示段應(yīng)當(dāng)包含ELF程序頭本身。

TYPE可以是如下的一個(gè)。數(shù)字表示關(guān)鍵字的值。

`PT_NULL' (0)
表示一個(gè)不用的程序頭。

`PT_LOAD' (1)
表示這個(gè)程序頭描述了一個(gè)被從文件中載入的段。

`PT_DYNAMIC' (2)
? ?表示一個(gè)可以從中找到動(dòng)態(tài)鏈接信息的段。

`PT_INTERP' (3)
?表示一個(gè)可以從中找到關(guān)于程序名解釋的段。

`PT_NOTE' (4)
表示一個(gè)存有備注信息的段。

`PT_SHLIB' (5)
?一個(gè)保留的程序頭類型,被定義了,但沒有被ELF ABI指定。

`PT_PHDR' (6)
表示一個(gè)可以從中找到程序頭的段。

EXPRESSION
一個(gè)給出程序頭的數(shù)值類型的表達(dá)式。這可以在使用上面未定義的類型時(shí)使用。

你可以通過使用‘AT’表達(dá)式指定一個(gè)段應(yīng)當(dāng)被載入到內(nèi)存中的一個(gè)特定的地址。這跟
在輸出節(jié)屬性中使用‘AT’命令是完全一樣的。程序頭中的‘AT’命令會(huì)覆蓋輸出節(jié)屬
性中的。

連接器通常會(huì)基于組成段的節(jié)來設(shè)置段屬性。你可以通過使用‘FLAGS’關(guān)鍵字來顯式指
定段標(biāo)志。FLAGS的值必須是一個(gè)整型值。它被用來設(shè)置程序頭的‘p_flags'域。

這里是一個(gè)關(guān)于‘PHDRS’的例子。它展示一個(gè)在純ELF系統(tǒng)上的一個(gè)標(biāo)準(zhǔn)的程序頭設(shè)置。

? ?PHDRS
? ?{
? ? ?headers PT_PHDR PHDRS ;
? ? ?interp PT_INTERP ;
? ? ?text PT_LOAD FILEHDR PHDRS ;
? ? ?data PT_LOAD ;
? ? ?dynamic PT_DYNAMIC ;
? ?}

? ?SECTIONS
? ?{
? ? ?. = SIZEOF_HEADERS;
? ? ?.interp : { *(.interp) } :text :interp
? ? ?.text : { *(.text) } :text
? ? ?.rodata : { *(.rodata) } /* defaults to :text */
? ? ?...
? ? ?. = . + 0x1000; /* move to a new page in memory */
? ? ?.data : { *(.data) } :data
? ? ?.dynamic : { *(.dynamic) } :data :dynamic
? ? ?...
? ?}

VERSION命令
===============

在使用ELF時(shí),連接器支持符號版本。符號版本只在使用共享庫時(shí)有用。動(dòng)態(tài)連接器在運(yùn)行一個(gè)
可能跟一個(gè)更早版本的共享庫鏈接程序時(shí),可以使用符號版本來選擇一個(gè)函數(shù)的特定版本。

你可以直接在主連接腳本中包含一個(gè)版本腳本,或者你可以以一個(gè)隱式連接腳本的形式提供這個(gè)
版本腳本。你也可以使用‘--version-script'連接器選項(xiàng)。

‘VERSION’命令的語法很簡單:

? ?VERSION { version-script-commands }

版本腳本命令的格式跟Sun在Solaris 2.5中的連接器的格式是完全一樣的。版本腳本定義一個(gè)版本
節(jié)點(diǎn)樹。你可以在版本腳本中指定節(jié)點(diǎn)名和依賴關(guān)系。你可以指定哪些符號被綁定到哪些版本節(jié)點(diǎn)
上,你還可以把一組指定的符號限定到本地范圍,這樣在共享庫的外面它們就不是全局可見的了。

最簡單的演示版本腳本語言的方法是出示幾個(gè)小例子:

? ?VERS_1.1 {
? ?global:
? ?foo1;
? ?local:
? ?old*;
? ?original*;
? ?new*;
? ?};

? ?VERS_1.2 {
? ?foo2;
? ?} VERS_1.1;

? ?VERS_2.0 {
? ?bar1; bar2;
? ?} VERS_1.2;

這個(gè)示例版本腳本定義了三個(gè)版本節(jié)點(diǎn)。第一個(gè)版本節(jié)點(diǎn)定義為‘VERS_1.1’它沒有其它的依賴。
腳本把符號‘foo1’綁定給‘VERS_1.1’。它把一些數(shù)量的符號限定到本地范圍,這樣它們在共
享庫的外面就不可見了;這是通過通配符來完成的,所以任何名字以‘old’,‘original’或
‘new’開頭的符號都會(huì)被匹配。可用的通配符跟在shell中匹配文件名時(shí)一樣。

下面,版本腳本定義一個(gè)節(jié)點(diǎn)‘VER_1.2’。這個(gè)節(jié)點(diǎn)依賴‘VER_1.1’。腳本把符號‘foo2’綁
定給節(jié)點(diǎn)‘VERS_1.2’。

最后,版本腳本定義節(jié)點(diǎn)‘VERS_2.0’。這個(gè)節(jié)點(diǎn)依賴‘VERS_1.2’。腳本把符號‘bar1’和
‘bar2 ’綁定給版本節(jié)點(diǎn)‘VERS_2.0’。

當(dāng)連接器發(fā)現(xiàn)一個(gè)定義在庫中的符號沒有被指定綁定到一個(gè)版本節(jié)點(diǎn),它會(huì)把它綁定到一個(gè)未指
定基礎(chǔ)版本的庫。你可以通過使用‘global: *;’把所有未指定的符號綁定到一個(gè)給定的版本節(jié)
點(diǎn)上。

版本節(jié)點(diǎn)的名字沒有任何特殊的含義只是為了方便人們閱讀。版本‘2.0’可以出現(xiàn)在‘1.1’和
‘1.2’之間。但是,在書寫版本腳本時(shí),這會(huì)是一個(gè)引起混亂的辦法。

如果在版本腳本中,這是一個(gè)唯一的版本節(jié)點(diǎn),節(jié)點(diǎn)名可以被省略。這樣的版本腳本不給符號賦
任何版本,只是選擇哪些符號會(huì)被全局可見而哪些不會(huì)。

? ?{ global: foo; bar; local: *; };

當(dāng)你把一個(gè)程序跟一個(gè)帶有版本符號的共享庫連接時(shí),程序自身知道每個(gè)符號的哪個(gè)版本是它需
要的,而且它還知道它連接的每一個(gè)節(jié)享庫中哪些版本的節(jié)點(diǎn)是它需要的。這樣,在運(yùn)行時(shí),動(dòng)
態(tài)載入程序可以做一個(gè)快速的確認(rèn),以保證你連接的庫確實(shí)提供了所有的程序需要用來解析所有
動(dòng)態(tài)符號的版本節(jié)點(diǎn)。用這種方法,就有可能讓每一個(gè)動(dòng)態(tài)連接器知道所有的外部符號不需要通
過搜索每一個(gè)符號引用就能解析。

符號版本在SunOS上做次版本確認(rèn)是一種很成熟的方法。一個(gè)被提出來的基本的問題是對于外部
函數(shù)的標(biāo)準(zhǔn)引用會(huì)在需要時(shí)被綁定到正確的版本,但不是在程序啟動(dòng)的時(shí)候全部被綁定。如果一
個(gè)共享庫過期了,一個(gè)需要的界面可能就不存在了;當(dāng)程序需要使用這個(gè)界面的時(shí)候,它可能會(huì)
突然地意外失敗。有了符號版本后,當(dāng)用戶啟動(dòng)他們的程序時(shí),如果要使用的共享庫太老了的話,
用戶會(huì)得到一條警告信息。

GNU對Sun的版本確認(rèn)辦法有一些擴(kuò)展。首先就是能在符號定義的源文件中把一個(gè)符號綁定到一個(gè)
版本節(jié)點(diǎn)而不是在一個(gè)版本腳本中。這主要是為了減輕庫維護(hù)的工作量。你可以通過類似下面的
代碼實(shí)現(xiàn)這一點(diǎn):

? ?__asm__(".symver original_foo,foo@VERS_1.1");

在C源文件中。這句會(huì)給函數(shù)'original_foo'取一個(gè)別名'foo',并綁定到版本節(jié)點(diǎn)`VERS_1.1'。
操作符'local:'可以被用來阻止符號'original_foo'被導(dǎo)出。操作符'.symver'使這句優(yōu)先于版
本腳本。

第二個(gè)GNU的擴(kuò)展是在一個(gè)給定的共享庫中允許同一個(gè)函數(shù)的多個(gè)版本。通過這種辦法,你可以
不增加共享庫的主版本號而對界面做完全不相容的修改。

要實(shí)現(xiàn)這個(gè),你必須在一個(gè)源文件中多次使用'.symver'操作符。這里是一個(gè)例子:

? ?__asm__(".symver original_foo,foo@");
? ?__asm__(".symver old_foo,foo@VERS_1.1");
? ?__asm__(".symver old_foo1,foo@VERS_1.2");
? ?__asm__(".symver new_foo,foo@@VERS_2.0");

在這個(gè)例子中,'foo@'表示把符號'foo'綁定到一個(gè)沒有指基版本的符號上。含有這個(gè)例子的源
文件必須定義4個(gè)C函數(shù):`original_foo', `old_foo', `old_foo1', 和`new_foo'.

當(dāng)你有一個(gè)給定符號的多個(gè)定義后,有必要有一個(gè)方法可以指定一個(gè)缺省的版本,對于這個(gè)符號
的外部引用就可以找到這個(gè)版本。用這種方法,你可以只聲明一個(gè)符號的一個(gè)版本作為缺省版本,
否則,你會(huì)擁有同一個(gè)符號的多個(gè)定義。

如果你想要綁定一個(gè)引用到共享庫中的符號的一個(gè)指定的版本,你可以很方便地使用別名(比如,
old_foo),或者你可以使用'.symver'操作符來指定綁定到一個(gè)外部函數(shù)的特定版本。

你也可以在版本腳本中指定語言。

? ?VERSION extern "lang" { version-script-commands }

被支持的'lang'有‘C’,‘C++’和‘Java’。

連接腳本中的表達(dá)式
=============================

連接腳本語言中的表達(dá)式的語法跟C的表達(dá)式是完全是致的。所有的表達(dá)式都以整型值被求值。所有
的表達(dá)式也被以相同的寬度求值。在32位系統(tǒng)是它是32位,否則是64位。

你可以在表達(dá)式中使用和設(shè)置符號值。

連接器為了使用表達(dá)式,定義了幾個(gè)具有特殊途的內(nèi)建函數(shù)。

常數(shù)
---------

所有的常數(shù)都是整型值。

就像在C中,連接器把以'0'開頭的整型數(shù)視為八進(jìn)制數(shù),把以'0x'或'0X'開頭的視為十六進(jìn)制。連接器
把其它的整型數(shù)視為十進(jìn)制。

另外,你可以使用'K'和'M'后綴作為常數(shù)的度量單位,分別為'1024'和'1024*1024'。比如,下面的三個(gè)
常數(shù)表示同一個(gè)值。

? ?_fourk_1 = 4K;
? ?_fourk_2 = 4096;
? ?_fourk_3 = 0x1000;

符號名
------------

除了引用,符號名都是以一個(gè)字母,下劃線或者句號開始,可以包含字母,數(shù)字,下劃線,句點(diǎn)和連接號。
不是被引用的符號名必須不和任何關(guān)鍵字沖突。你可以指定一個(gè)含有不固定它符數(shù)或具有跟關(guān)鍵字相同名
字但符號名必須在雙引號內(nèi):

? ?"SECTION" = 9;
? ?"with a space" = "also with a space" + 10;

因?yàn)榉柨梢院泻芏喾俏淖肿址?#xff0c;所以以空格分隔符號是很安全的。比如,'A-B'是一個(gè)符號,而'A - B'
是一個(gè)執(zhí)行減法運(yùn)算的表達(dá)式。

定位計(jì)數(shù)器
--------------------

一個(gè)特殊的連接器變量"dot"'.'總是含有當(dāng)前的輸出定位計(jì)數(shù)器。因?yàn)?#39;.'總引用輸出段中的一個(gè)位置,它
只可以出現(xiàn)在'SECTIONS'命令中的表達(dá)式中。'.'符號可以出現(xiàn)在表達(dá)式中一個(gè)普能符號允許出現(xiàn)的任何位
置。

把一個(gè)值賦給'.'會(huì)讓定位計(jì)數(shù)器產(chǎn)生移動(dòng)。這會(huì)在輸出段中產(chǎn)生空洞。定位計(jì)數(shù)器從不向前移動(dòng)。

? ?SECTIONS
? ?{
? ? ?output :
? ? ? ?{
? ? ? ? ?file1(.text)
? ? ? ? ?. = . + 1000;
? ? ? ? ?file2(.text)
? ? ? ? ?. += 1000;
? ? ? ? ?file3(.text)
? ? ? ?} = 0x12345678;
? ?}

在前面的例子中,來自'file1'的'.text'節(jié)被定位在輸出節(jié)'output'的起始位置。它后面跟有1000byte的
空隙。然后是來自'file2'的'.text'節(jié),同樣是后面跟有1000byte的空隙,最后是來自'file3'的'.text'
節(jié)。符號'=0x12345678'指定在空隙中填入什么樣的數(shù)據(jù)。

注意:'.'實(shí)際上引用的是當(dāng)前包含目標(biāo)的從開始處的字節(jié)偏移。通常,它就是'SECTIONS'語句,其起始地
址是0,因?yàn)?#39;.'可以被用作絕對地址。但是如果'.'被用在一個(gè)節(jié)描述中,它引用的是從這個(gè)節(jié)起始處開始
的偏移,而不是一個(gè)絕對地址。這樣,在下面這樣一個(gè)腳本中:

? ?SECTIONS
? ?{
? ? ? ?. = 0x100
? ? ? ?.text: {
? ? ? ? ?*(.text)
? ? ? ? ?. = 0x200
? ? ? ?}
? ? ? ?. = 0x500
? ? ? ?.data: {
? ? ? ? ?*(.data)
? ? ? ? ?. += 0x600
? ? ? ?}
? ?}

'.text'節(jié)被賦于起始地址0x100,盡管在'.text'輸入節(jié)中沒有足夠的數(shù)據(jù)來填充這個(gè)區(qū)域,但其長
度還是0x200bytes。(如果數(shù)據(jù)太多,那會(huì)產(chǎn)生一條錯(cuò)誤信息,因?yàn)檫@會(huì)試圖把'.'向前移)。'.data'
節(jié)會(huì)從0x500處開始,并且它在結(jié)尾處還會(huì)有0x600的額外空間。

運(yùn)算符
---------

連接器可以識(shí)別標(biāo)準(zhǔn)的C的算術(shù)運(yùn)算符集, 以及它們的優(yōu)先集.

? ?優(yōu)先集 ? ? ? ?結(jié)合性 ? ? ? ? ?運(yùn)算符 ? ? ? ? ? ? ? ? ?備注
? ?(highest)
? ?1 ? ? ? ? ? ? ?left ? ? ? ? ? ?! ?- ?~ ? ? ? ? ? ? ? ? ?(1)
? ?2 ? ? ? ? ? ? ?left ? ? ? ? ? ?* ?/ ?%
? ?3 ? ? ? ? ? ? ?left ? ? ? ? ? ?+ ?-
? ?4 ? ? ? ? ? ? ?left ? ? ? ? ? ?>> ?<<
? ?5 ? ? ? ? ? ? ?left ? ? ? ? ? ?== ?!= ?> ?< ?<= ?>=
? ?6 ? ? ? ? ? ? ?left ? ? ? ? ? ?&
? ?7 ? ? ? ? ? ? ?left ? ? ? ? ? ?|
? ?8 ? ? ? ? ? ? ?left ? ? ? ? ? ?&&
? ?9 ? ? ? ? ? ? ?left ? ? ? ? ? ?||
? ?10 ? ? ? ? ? ? ?right ? ? ? ? ?? :
? ?11 ? ? ? ? ? ? ?right ? ? ? ? ?&= ?+= ?-= ?*= ?/= ? ? ?(2)
? ?(lowest)
?注: (1) 前綴運(yùn)算符 (2) *Note Assignments::.

求值
----------

連接器是懶惰求表達(dá)式的值。它只在確實(shí)需要的時(shí)候去求一個(gè)表達(dá)式的值。

連接器需要一些信息,比如第一個(gè)節(jié)的起始地址的值,還有內(nèi)存區(qū)域的起點(diǎn)與長度,在做任何連接的
時(shí)候這都需要。在連接器讀取連接腳本的時(shí)候,這些值在可能的時(shí)候被計(jì)算出來。

但是,其它的值(比如符號的值)直到內(nèi)存被分配之后才會(huì)知道或需要。這樣的值直到其它信息(比
如輸出節(jié)的長度)可以被用來進(jìn)行符號賦值的時(shí)候才被計(jì)算出來。

直到內(nèi)存分配之后,節(jié)的長度才會(huì)被知道,所以依賴于節(jié)長度的賦值只能到內(nèi)存分配之后才會(huì)被執(zhí)行。

有些表達(dá)式,比如那些依賴于定位計(jì)數(shù)器'.'的表達(dá)式,必須在節(jié)分配的過程中被計(jì)算出來。

如果一個(gè)表達(dá)式的結(jié)果現(xiàn)在被需要,但是目前得不到這個(gè)值,這樣會(huì)導(dǎo)致一個(gè)錯(cuò)誤。比如,象下面這
樣一個(gè)腳本:

? ?SECTIONS
? ? ?{
? ? ? ?.text 9+this_isnt_constant :
? ? ? ? ?{ *(.text) }
? ? ?}

會(huì)產(chǎn)生一個(gè)錯(cuò)誤信息'non constant expression for initial address'.

表達(dá)式的節(jié)
----------------------------

當(dāng)一個(gè)連接器計(jì)算一個(gè)表達(dá)式時(shí),得到的結(jié)果可能是一個(gè)絕對值,也可能跟某個(gè)節(jié)相關(guān)。一個(gè)節(jié)相關(guān)的
表達(dá)式是從一個(gè)節(jié)的基地址開始的固定的偏稱值。

表達(dá)式在連接腳本中的位置決定了它是絕對的或節(jié)相關(guān)的。一個(gè)出現(xiàn)在輸出節(jié)定義中的表達(dá)式是跟輸出
節(jié)的基地址相關(guān)的。一個(gè)出現(xiàn)在其它地方的表達(dá)式則是絕對的。

如果你通過'-r'選項(xiàng)指定需要可重位輸出,那一個(gè)被賦為節(jié)相關(guān)的表達(dá)式的符號就會(huì)是可重定位的。意
思是下一步的連接操作會(huì)改變這個(gè)符號的值。符號的節(jié)就是節(jié)相關(guān)的表達(dá)式所在的節(jié)。

一個(gè)被賦為絕對表達(dá)式的符號在后面進(jìn)一步的連接操作中會(huì)始終保持它的值不變。符號會(huì)是絕對的,并
不會(huì)有任何的特定的相關(guān)節(jié)。

如果一個(gè)表達(dá)式有可能會(huì)是節(jié)相關(guān)的,你可以使用內(nèi)建函數(shù)'ABSOLUTE'強(qiáng)制一個(gè)表達(dá)式為絕對的。比如,
要?jiǎng)?chuàng)建一個(gè)被賦為輸出節(jié)'.data'的末尾地址的絕對符號:

? ?SECTIONS
? ? ?{
? ? ? ?.data : { *(.data) _edata = ABSOLUTE(.); }
? ? ?}

如果沒有使用'ABSOLUTE','_edata'會(huì)跟節(jié)'.data'相關(guān)。

內(nèi)建函數(shù)
-----------------

為了使用連接腳本表達(dá)式,連接腳本語言含有一些內(nèi)建函數(shù)。

`ABSOLUTE(EXP)'
返回表達(dá)式EXP的絕對值(不可重定位,而不是非負(fù))。主要在把一個(gè)絕對值賦給一個(gè)節(jié)定義內(nèi)的
符號時(shí)有用。

`ADDR(SECTION)'
返回節(jié)SECTION的絕對地址(VMA)。你的腳本之前必須已經(jīng)定義了這個(gè)節(jié)的地址。在接下來的例子
中,'symbol_1'和'symbol_2'被賦以相同的值。

? ? ? ?SECTIONS { ...
? ? ? ? ?.output1 :
? ? ? ? ? ?{
? ? ? ? ? ?start_of_output_1 = ABSOLUTE(.);
? ? ? ? ? ?...
? ? ? ? ? ?}
? ? ? ? ?.output :
? ? ? ? ? ?{
? ? ? ? ? ?symbol_1 = ADDR(.output1);
? ? ? ? ? ?symbol_2 = start_of_output_1;
? ? ? ? ? ?}
? ? ? ?... }

`ALIGN(EXP)'
返回定位計(jì)數(shù)器'.'對齊到下一個(gè)EXP指定的邊界后的值。‘ALIGN’不改變定位計(jì)數(shù)器的值,它只是
在定位計(jì)數(shù)器上面作了一個(gè)算術(shù)運(yùn)算。這里有一個(gè)例子,它在前面的節(jié)之后,把輸出節(jié)'.data'對齊
到下一個(gè)'0x2000'字節(jié)的邊界,并在輸入節(jié)之后把節(jié)內(nèi)的一個(gè)變量對齊到下一個(gè)'0x8000'字節(jié)的邊界。

? ? ? ?SECTIONS { ...
? ? ? ? ?.data ALIGN(0x2000): {
? ? ? ? ? ?*(.data)
? ? ? ? ? ?variable = ALIGN(0x8000);
? ? ? ? ?}
? ? ? ?... }

這個(gè)例子中前一個(gè)'ALIGN'指定一個(gè)節(jié)的位置,因?yàn)樗亲鳛楣?jié)定義的可選項(xiàng)ADDRESS屬性出現(xiàn)的。第
二個(gè)‘ALIGN’被用來定義一個(gè)符號的值。

內(nèi)建函數(shù)'NEXT'跟‘ALIGN’非常相似。

`BLOCK(EXP)'
這是'ALIGN'的同義詞,是為了與其它的連接器保持兼容。這在設(shè)置輸出節(jié)的地址時(shí)非常有用。

`DATA_SEGMENT_ALIGN(MAXPAGESIZE, COMMONPAGESIZE)'
? ?這跟下面的兩個(gè)表達(dá)同義:
? ? ? ?(ALIGN(MAXPAGESIZE) + (. & (MAXPAGESIZE - 1)))
? ?或者:
? ? ? ?(ALIGN(MAXPAGESIZE) + (. & (MAXPAGESIZE - COMMONPAGESIZE)))

隱式連接腳本
=======================

如果你指定了一個(gè)連接器輸出文件,而連接器不能識(shí)別它是一個(gè)目標(biāo)文件還是檔案文件,它會(huì)試圖把它讀作
一個(gè)連接腳本。如果這個(gè)文件不能作為一個(gè)連接腳本被分析,連接器就會(huì)報(bào)告一個(gè)錯(cuò)誤。

一個(gè)隱式的連接器腳本不會(huì)替代缺省的連接器腳本。

一般,一個(gè)隱式的連接器腳本只包含符號賦值,或者'INPUT','GROUP'或'VERSION'命令。

BFD
***

連接器通過BFD庫來對目標(biāo)文件和檔案文件進(jìn)行操作。這些庫允許連接器忽略目標(biāo)文件的格式而使用相關(guān)的
例程來操作目標(biāo)文件。只要簡單地創(chuàng)建一個(gè)新的BFD后臺(tái)并把它加到庫中,一個(gè)不同的目標(biāo)文件格式就會(huì)被
支持。但是為了節(jié)約運(yùn)行時(shí)內(nèi)存,連接器和相關(guān)的工具一般被配置為只支持可用的目標(biāo)文件格式的一個(gè)子集,
你可以使用'objdump -i'來列出你配置的所有支持的格式。

就像大多數(shù)的案例,BFD是一個(gè)在多種相互有沖突的需求之間的一個(gè)折中,影響B(tài)FD設(shè)計(jì)的一個(gè)最主要的因
素是效率。因?yàn)锽FD簡化了程序和后臺(tái),更多的時(shí)間和精力被放在了優(yōu)化算法以追求更快的速度。

BFD解決方案的一個(gè)副產(chǎn)品是你必須記住有信息丟失的潛在可能。在使用BFD機(jī)制時(shí),有兩處地方有用信息可
能丟失:在轉(zhuǎn)化時(shí)和在輸出時(shí)。

它如何工作: BFD概要。
===============================

當(dāng)一個(gè)目標(biāo)文件被打開時(shí),BFD子程序自動(dòng)確定輸入目標(biāo)文件的格式。然后它們在內(nèi)存中用指向子程序的指針
構(gòu)建一個(gè)描述符,這個(gè)描述符被用作存取目標(biāo)文件的數(shù)據(jù)結(jié)構(gòu)元素。

因?yàn)樾枰獊碜阅繕?biāo)文件的不同信息,BFD從文件的不同節(jié)中讀取它們,并處理。比如,連接器的一個(gè)非常普遍
的操作是處理符號表。每一個(gè)BFD后臺(tái)提供一個(gè)在目標(biāo)文件的符號表達(dá)形式跟內(nèi)部規(guī)范格式之間的轉(zhuǎn)化的函數(shù),
當(dāng)一個(gè)連接器需要一個(gè)目標(biāo)文件的符號表時(shí),它通過一個(gè)內(nèi)存指針調(diào)用一個(gè)來自相應(yīng)的BFD后臺(tái)的子程序,這
個(gè)子程序讀取表并把它轉(zhuǎn)化為規(guī)范表。然后,連接器寫輸出文件的符號表,另一個(gè)BFD后臺(tái)子程序被調(diào)用,以
創(chuàng)建新的符號表并把它轉(zhuǎn)化為選定的輸出格式。

信息丟失。
----------------

在輸出的過程中,信息可能會(huì)被丟失。BFD支持的輸出格式并不提供一致的特性,并且在某一種格式中可以被
描述的信息可能在另一種格式中沒有地方可放。一個(gè)例子是在'b.out'中的對齊信息,在一個(gè)'a.out'格式的
文件中,沒有地方可以存儲(chǔ)對齊信息,所以當(dāng)一個(gè)文件是從'b.out'連接而成的,并產(chǎn)生的是一個(gè)'a.out'的
文件,對齊信息就不會(huì)被傳入到輸出文件中(連接器還是在內(nèi)部使用對齊信息,所以連接器的執(zhí)行還是正確的)

另一個(gè)例子是COFF節(jié)名字。COFF文件中可以含有不限數(shù)量的節(jié),每一個(gè)都有一個(gè)文字的節(jié)名。如果連接的目標(biāo)是
一種不支持過多節(jié)的格式(比如,'a.out')或者是一種不含有節(jié)名的格式(比如,Oasys格式),連接器不
能像通常那樣簡單地處理它。你可以通過把所需的輸入輸出節(jié)通過連接腳本語言進(jìn)行詳細(xì)映射來解決這下問題。

在規(guī)范化的過程中信息也會(huì)丟失。BFD內(nèi)部的對應(yīng)于外部格式的規(guī)范形式并不是完全詳盡的;有些在輸入格式
中的結(jié)構(gòu)在內(nèi)部并沒有對應(yīng)的表示方法。這意味著BFD后臺(tái)在從外部到內(nèi)部或從內(nèi)部到外部的轉(zhuǎn)化過程中不能
維護(hù)所有可能的數(shù)據(jù)。

這個(gè)限制只在一個(gè)程序讀取一種格式并寫成另一種格式的時(shí)候會(huì)是一個(gè)問題。每一個(gè)BFD后臺(tái)有責(zé)任維護(hù)盡可能
多的數(shù)據(jù),內(nèi)部的BFD規(guī)范格式具有對BFD內(nèi)核不透明的結(jié)構(gòu)體,只導(dǎo)出給后臺(tái)。當(dāng)一個(gè)文件以一種格式讀取后,
規(guī)范格式就會(huì)為之產(chǎn)生。同時(shí),后臺(tái)把所有可能丟失的信息進(jìn)行存儲(chǔ)。如果這些數(shù)據(jù)隨后會(huì)寫以相同的格式寫
回,后臺(tái)程序就可以使用BFD內(nèi)核提供的跟選前準(zhǔn)備的相同的規(guī)范格式。因?yàn)樵诤笈_(tái)之間有大量相同的東西,在
把big endianCOFF拷貝成littile endian COFF時(shí),或者'a.out'到'b.out'時(shí),不會(huì)有信息丟失。當(dāng)一些混合格
式被連接到一起時(shí),只有那些格式跟目標(biāo)格式不同的文件會(huì)丟失信息。


轉(zhuǎn)載于:https://blog.51cto.com/7090376/1264609

總結(jié)

以上是生活随笔為你收集整理的LDS文件格式分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

色91av | 91久久精品一区二区三区 | 亚洲91精品在线观看 | www.狠狠操| 久久久久久久久精 | 国产精品视频在线看 | 国产精品第7页 | 成人av在线网址 | 国产青春久久久国产毛片 | 天天综合网久久 | 五月天免费网站 | 国产成人1区| 久久久久久久久久国产精品 | 日韩| 在线a亚洲视频播放在线观看 | 五月婷婷激情综合网 | 国产精品色婷婷视频 | 97超碰超碰| 色香蕉在线 | 中文字幕亚洲不卡 | 国产99久久久久久免费看 | 国产视频久久 | 日本精品视频在线观看 | 日韩字幕 | 日本一区二区三区视频在线播放 | 天天天干夜夜夜操 | 免费看黄在线观看 | 国产91精品在线播放 | 日韩视频免费看 | 99久久久国产精品免费99 | 国产二区精品 | 手机看片久久 | 欧美日韩一区二区三区在线观看视频 | 六月丁香激情综合色啪小说 | 99热这里精品 | 久久精品免费看 | 91在线小视频 | 中文字幕乱视频 | 精品久久久久久久久久久久久久久久久久 | 久久久精品久久 | www.狠狠插.com | 成人久久18免费 | 日韩黄色大片在线观看 | 韩国在线视频一区 | 国产精品成人自产拍在线观看 | 99se视频在线观看 | 五月天婷亚洲天综合网鲁鲁鲁 | 人人网人人爽 | 99久久免费看 | 国内视频 | 91精品视频在线看 | 在线观看国产v片 | 亚洲va天堂va欧美ⅴa在线 | 在线观看免费版高清版 | 免费在线观看av网址 | 视频在线观看日韩 | 狠狠干成人综合网 | 在线免费黄色av | 成人免费影院 | 亚洲一二三在线 | 日韩一级黄色av | 亚洲女人av| 91豆麻精品91久久久久久 | 中文字幕日韩在线播放 | 精品国产乱码一区二 | 天天干天天在线 | 欧美亚洲国产日韩 | 最新av观看 | 久久久精品网站 | 91中文字幕在线 | 成人激情开心网 | 久热免费在线 | 九九九九精品 | 97色在线观看免费视频 | 欧美日韩精品影院 | 国产视频97 | 久热这里有精品 | 久草在线视频资源 | 最近能播放的中文字幕 | 日韩手机在线观看 | 国产成人高清av | 美女在线国产 | 色婷婷一| 亚洲精品一区二区三区高潮 | 在线黄色毛片 | 国产专区欧美专区 | 日日夜夜精品免费观看 | 久久人人爽人人爽人人片av软件 | 色www.| 成人av资源在线 | 超碰人人在 | 精品一区二区电影 | 久久伦理电影 | 久久精品男人的天堂 | 国产精品视频永久免费播放 | www日韩视频 | 欧美a视频在线观看 | 久久 在线 | 中文字幕一区三区 | 中文字幕综合在线 | 日韩精品在线观看视频 | 亚洲高清网站 | 伊人狠狠色 | 亚洲年轻女教师毛茸茸 | 久久久久久久久久久久久国产精品 | 亚洲免费av片 | 啪嗒啪嗒免费观看完整版 | 五月天伊人网 | 免费观看视频黄 | 欧美日韩亚洲在线观看 | 久99视频 | 激情电影影院 | 国产性天天综合网 | 免费在线观看的av网站 | 96超碰在线 | 中文字幕在线一区二区三区 | 九九精品视频在线观看 | 亚洲一级在线观看 | 精品国产伦一区二区三区 | 久久在草 | 国产视频中文字幕在线观看 | 操操操干干干 | 成人av在线一区二区 | 免费视频一级片 | 国内外激情视频 | 欧美日韩亚洲在线观看 | 亚洲成人黄色 | 午夜av剧场 | 亚洲国产精品免费 | 久久视频国产精品免费视频在线 | 国产综合视频在线观看 | 国产夫妻自拍av | 日韩欧美一区二区三区黑寡妇 | 中国一级片在线播放 | 国产精品mv在线观看 | 91视频久久久久 | 久久超级碰视频 | 一区二区三区福利 | 狠狠干干 | 日韩欧美国产激情在线播放 | 欧美中文字幕第一页 | 三级黄在线 | av色综合 | 成人h电影在线观看 | 日日干av| av看片在线观看 | 免费a v视频 | 香蕉97视频观看在线观看 | 久久精品视频免费观看 | 国产18精品乱码免费看 | 日韩精品久久久久久久电影99爱 | 天天操天天爱天天爽 | 久久久久国产免费免费 | 国产色视频一区二区三区qq号 | 成人黄色片在线播放 | 中文字幕第一页在线vr | 国产成人在线观看免费 | 成人91视频 | 日本性生活免费看 | 欧洲精品码一区二区三区免费看 | 国产自在线观看 | 综合铜03| 亚洲精品大片www | 91精品资源 | 91福利视频在线 | 国产黄网站在线观看 | 99久久影院 | 天天艹天天 | 国产高清在线免费观看 | 亚洲欧美国产精品18p | av怡红院 | 色综合久久久网 | 波多野结衣在线观看一区二区三区 | 国产精品网红福利 | 国产精品精品 | 日韩欧美成| 五月天婷婷免费视频 | 欧美最猛性xxxxx免费 | av资源网在线播放 | 又黄又爽又色无遮挡免费 | 久操中文字幕在线观看 | 国产精品久久久久久久av大片 | 国产精品久久久久久一区二区三区 | 久久不卡国产精品一区二区 | 激情五月激情综合网 | 最近中文国产在线视频 | 国产原创av片 | 国产无区一区二区三麻豆 | 91精品免费视频 | 日韩免费一区 | 日日插日日干 | 久久免费中文视频 | 国产69精品久久久久99尤 | 国产成人精品午夜在线播放 | 免费的黄色的网站 | 狠狠狠狠狠狠 | 欧美日韩不卡一区二区 | 伊人五月天综合 | 91成人免费 | 五月天精品视频 | 国产精品婷婷午夜在线观看 | 国产 日韩 欧美 在线 | 极品嫩模被强到高潮呻吟91 | 99免费在线视频观看 | 久久国产二区 | 青青草华人在线视频 | 射射射av | 天天插综合 | 五月综合色婷婷 | 精品国产一区二区三区在线 | 日本韩国中文字幕 | 国产精品久久电影观看 | 欧美激情在线网站 | 全久久久久久久久久久电影 | 一本一道久久a久久精品 | av激情五月 | 2019中文| 黄色亚洲在线 | 国产精品午夜久久久久久99热 | 天天干人人干 | 在线电影av | 伊人久久影视 | 免费看污网站 | 成人一区二区三区在线观看 | 国产中文字幕三区 | 91视频这里只有精品 | 一区二区三区免费在线观看视频 | 亚洲在线网址 | 国产91精品看黄网站在线观看动漫 | 欧美久久九九 | 国内精品视频在线 | 欧美视频网址 | 永久免费的av电影 | 日韩电影中文 | 中文字幕免费观看全部电影 | 日韩av播放在线 | 亚洲精品66 | 国产h在线播放 | 日日夜夜精品免费 | 免费一级日韩欧美性大片 | 国产精品网红直播 | 精品亚洲免a | 国产精品99久久久久 | 国产在线资源 | 久久久久国产精品厨房 | 99精品久久99久久久久 | 欧美激情精品久久久久久免费印度 | 中文字幕在线免费观看视频 | 在线视频你懂 | 丁香午夜 | 国产中文字幕国产 | 久久综合久久综合久久综合 | 国产一级二级在线观看 | 四虎在线视频 | 九九视频在线播放 | 麻豆 videos | 7777精品伊人久久久大香线蕉 | 伊人黄色网 | 国产91成人在在线播放 | 日产乱码一二三区别在线 | 日韩a在线 | 99精品偷拍视频一区二区三区 | 欧美黄色免费 | 黄网站app在线观看免费视频 | 国产精品电影在线 | 国产精品久久久久久久久久久久久久 | 国产正在播放 | 成人羞羞视频在线观看免费 | 婷婷久久亚洲 | 337p西西人体大胆瓣开下部 | 超黄视频网站 | 日韩最新中文字幕 | 国产精品手机播放 | 久久中文字幕在线视频 | 成人国产在线 | 在线免费观看黄色大片 | 色综久久 | 亚洲精品视频一 | 丁香婷婷综合色啪 | 亚洲涩涩网| 色婷婷成人 | 91网站在线视频 | 精品99在线| 欧美日韩不卡一区二区 | 91精品在线视频 | 免费男女羞羞的视频网站中文字幕 | 国产毛片aaa| 国产精品午夜在线观看 | 久久一区91 | 99视频网址| 国产我不卡 | 在线视频黄 | 国产精品免费久久久久久 | 久久久久欠精品国产毛片国产毛生 | 精品欧美小视频在线观看 | 国产精品亚洲片夜色在线 | 国产资源 | 最近中文字幕大全中文字幕免费 | 国产高清精品在线 | 精品国产综合区久久久久久 | 波多野结衣网址 | 夜夜操天天干, | 日日干网址 | 成年人免费av | 日韩视频免费观看高清完整版在线 | 99精品国产一区二区三区不卡 | 97超碰总站 | 欧美日韩亚洲第一 | 国产一区二区电影在线观看 | 亚洲精品一区二区久 | 欧美 日韩 视频 | 亚洲欧美乱综合图片区小说区 | 麻豆国产网站入口 | 国产午夜精品一区二区三区 | 国产色久 | 国产午夜精品一区二区三区嫩草 | 91精品久久久久久综合乱菊 | 伊甸园永久入口www 99热 精品在线 | 久久激情电影 | 亚洲精品88欧美一区二区 | 天天干,狠狠干 | 色多多在线观看 | 18国产精品白浆在线观看免费 | 国产成人在线观看免费 | 国产精品美女999 | 狠狠操综合 | 免费 在线 中文 日本 | 日本在线观看中文字幕 | 欧美一区二区三区免费观看 | 欧美一级免费黄色片 | 一区二区视频在线免费观看 | 激情综合婷婷 | 日本中文字幕网 | 久草久热| 国产精品久久久久久一二三四五 | 五月婷婷视频在线 | 天天综合中文 | 国产视频1 | 97精品国自产拍在线观看 | 亚洲国产一区在线观看 | 国产精品福利小视频 | 99精品欧美一区二区蜜桃免费 | 亚洲情感电影大片 | 99婷婷狠狠成为人免费视频 | 免费碰碰| 国产不卡免费av | 日韩在线观看视频中文字幕 | 黄色在线观看网站 | 国产福利一区在线观看 | wwwwww色| 亚洲妇女av | 亚洲一级电影 | 久久夜视频| 国产99一区视频免费 | 午夜av免费 | 日本护士三级少妇三级999 | 亚洲精品午夜久久久久久久久久久 | 999视频精品 | av在线免费在线观看 | 最近能播放的中文字幕 | 久久艹人人 | 久久久国产精品成人免费 | 青青草国产精品 | 九九九九免费视频 | 欧美激情xxxx性bbbb | 五月丁色 | 国产在线一区二区三区播放 | 亚洲视频电影在线 | 99色在线观看 | 天天干,夜夜爽 | 国产精品久久久久一区二区 | 丁香六月婷婷综合 | 亚洲精选在线观看 | 精品亚洲成人 | 午夜av免费观看 | 亚洲人成人99网站 | av在线专区 | 午夜精品一区二区三区视频免费看 | 91av网站在线观看 | 午夜av一区 | 首页国产精品 | 成人久久综合 | 欧美资源 | 精品国产美女 | 久久手机看片 | 久久国产影院 | 中文字幕电影一区 | 免费日韩一区二区三区 | 91精品视频观看 | 超碰97中文 | 亚洲经典视频 | 精品日韩中文字幕 | 最新日韩视频在线观看 | 日韩欧美有码在线 | 天堂av免费 | 免费日韩三级 | 成人在线免费av | 亚洲女同videos| 香蕉视频在线视频 | 69久久99精品久久久久婷婷 | 天天曰天天射 | 精品视频中文字幕 | 欧美动漫一区二区三区 | 亚洲电影一区二区 | 最近中文字幕免费av | 一个色综合网站 | av在线之家电影网站 | 97超碰精品 | 国产精品一区二区美女视频免费看 | 玖玖在线播放 | 在线播放视频一区 | 久久香蕉国产精品麻豆粉嫩av | 久久久久久久久久国产精品 | 99久热在线精品视频观看 | 国产香蕉在线 | 玖玖在线观看视频 | 色综合五月天 | 久久无码精品一区二区三区 | 午夜丰满寂寞少妇精品 | 在线高清av | 国产美女在线免费观看 | 中文字幕乱在线伦视频中文字幕乱码在线 | 欧美日韩在线播放一区 | www五月 | 在线观看免费 | 亚洲四虎在线 | 国产精品久久久久久久久久了 | 国产精品爽爽久久久久久蜜臀 | 97超碰资源总站 | 免费一级片视频 | 日韩久久精品一区二区 | 激情在线网站 | 国产麻豆精品在线观看 | 一区二区三区四区久久 | 成人在线黄色 | 午夜男人影院 | 超碰在线人人 | 天天操天天谢 | www久草| 一区二区三区免费在线观看 | 久久全国免费视频 | 精品国产精品久久一区免费式 | 亚洲一区二区三区91 | 五月天久久久久 | 97色在线观看免费视频 | 在线免费中文字幕 | 天堂av在线免费 | 国产一区二区不卡在线 | 国产福利精品在线观看 | 91福利视频久久久久 | 狠狠干天天射 | 日韩精品一区二区在线观看视频 | 亚洲91精品在线观看 | 狠狠地操 | 91最新在线观看 | 99精品偷拍视频一区二区三区 | 国产精品欧美久久久久三级 | 欧美日韩3p | 91精品色| 99草在线视频 | 国产99久久九九精品免费 | 日韩在线播放视频 | 国产精品国产三级国产专区53 | 国产欧美最新羞羞视频在线观看 | 久久女同性恋中文字幕 | 欧美精品久久久久久久亚洲调教 | 就操操久久 | 五月香婷| 国产第一页精品 | 国产亚洲精品久久久网站好莱 | av亚洲产国偷v产偷v自拍小说 | 99热国产精品 | 色欧美视频 | 国产乱对白刺激视频不卡 | 中文字幕亚洲欧美日韩 | 天天操狠狠操 | 色网站黄| 久久久在线观看 | 国产精品情侣视频 | 伊人中文网 | 一二三区高清 | 精品亚洲网 | 亚洲一区不卡视频 | 欧美日视频 | 91精品播放| www.91国产 | 九九九九免费视频 | 久产久精国产品 | 日韩精品视频在线观看免费 | av在线8| 99热在线观看免费 | 国产日韩视频在线观看 | 天天色天天射天天综合网 | 久久精品屋| 欧美一区二区日韩一区二区 | 国产精品久久久久久久毛片 | 五月激情六月丁香 | 免费观看视频的网站 | 成人免费观看在线视频 | www.av免费观看 | 国内外成人免费在线视频 | 成人国产网站 | a黄色一级 | 午夜视频播放 | a天堂一码二码专区 | 黄色国产高清 | www.久久99| 在线黄频 | 国产亚洲婷婷免费 | www..com黄色片 | 亚洲激情婷婷 | 久久久影院官网 | 免费看片色 | 国产一级视频在线免费观看 | 91爱爱网址 | 久久精品激情 | 精品国产乱码一区二区三区在线 | 美女在线国产 | a视频免费看 | 天天av在线播放 | 国产精品成人在线 | 97香蕉超级碰碰久久免费软件 | 国产精品精品久久久久久 | 免费在线观看午夜视频 | 亚洲视频久久 | 日本女人逼 | 日日干夜夜草 | 4p变态网欧美系列 | 精品美女久久久久久免费 | 少妇搡bbbb搡bbb搡69 | 中文字幕中文中文字幕 | 欧美日韩国内在线 | 国产一卡久久电影永久 | 国产亚洲精品久久久久久网站 | 国产麻豆果冻传媒在线观看 | 久久有精品| 国产人成在线观看 | 久久草| 国产手机精品视频 | 奇米四色影狠狠爱7777 | 成人免费观看视频大全 | 国产在线91在线电影 | 一色屋精品视频在线观看 | 日本在线观看中文字幕 | 亚洲欧洲av在线 | 在线免费观看国产黄色 | 久久免费国产视频 | 国产精品一区二区三区视频免费 | 91传媒免费在线观看 | 日日夜精品| 91丨精品丨蝌蚪丨白丝jk | 天天干亚洲 | 国产群p视频 | 国产精品成久久久久三级 | 久草视频精品 | a天堂最新版中文在线地址 久久99久久精品国产 | 亚洲激情 欧美激情 | 天天操夜夜干 | 欧美激情精品一区 | 国产亚洲精品综合一区91 | 中文字幕乱视频 | 亚洲女欲精品久久久久久久18 | 欧美极品裸体 | 在线观看日韩精品 | 日韩中文字幕a | 中文字幕在线观看免费高清完整版 | 成年人在线免费视频观看 | 精品无人国产偷自产在线 | 国产精品视频app | 在线视频 精品 | 国产高清视频在线播放 | 综合久久久久久久久 | 国产精品 日韩精品 | 久久黄色小说 | 中文字幕在线观看资源 | 欧美在线视频免费 | 五月婷网站 | 国产精品久久久久久久久久99 | 91精品国产乱码久久 | 久久在线观看视频 | 一二区电影 | 国产精品手机在线观看 | 久久一二区 | 98超碰在线 | 黄色亚洲精品 | 欧美日韩国产一二 | 在线韩国电影免费观影完整版 | 新版资源中文在线观看 | 日本乱视频 | 一级黄色av | 久久91久久久久麻豆精品 | 久久精品99国产精品日本 | 探花视频在线观看免费 | 亚洲国产经典视频 | 国产成人av一区二区三区在线观看 | 中文字幕在线观看完整版 | 免费成人在线电影 | 搡bbbb搡bbb视频 | 超碰97成人| 国内99视频| 亚洲精品国偷自产在线91正片 | 青草视频在线播放 | 97夜夜澡人人爽人人免费 | 久久国产高清 | av看片在线| 亚州天堂 | 国产成人精品999在线观看 | 91精品久| 久久精品官网 | 国产精品亚 | 一级免费看 | 黄色毛片在线 | 精品自拍网 | 亚洲综合色丁香婷婷六月图片 | 99这里只有久久精品视频 | 丝袜美腿在线视频 | 蜜臀av夜夜澡人人爽人人桃色 | 国产视频亚洲精品 | 亚洲国产成人精品电影在线观看 | 色黄视频免费观看 | 婷婷深爱五月 | 亚洲一级影院 | 久久国产经典视频 | 制服丝袜亚洲 | 成人精品久久久 | 亚洲美女视频在线 | 婷婷色网 | 成人在线超碰 | 一区中文字幕在线观看 | 五月天狠狠操 | 99在线热播精品免费99热 | 日韩电影中文 | 国产在线精品二区 | 午夜精品视频在线 | 青春草视频 | 久久综合狠狠狠色97 | 黄色电影网站在线观看 | 国产午夜三级 | 欧美日韩中文字幕综合视频 | 日韩va在线观看 | 久99热| 国产精品免费不卡 | 九九热av| 亚洲 精品在线视频 | 国产精品资源 | 久久国产精品99国产精 | 国产一区欧美在线 | 国产伦精品一区二区三区… | 中文字幕有码在线观看 | 日韩视频中文字幕在线观看 | 欧美午夜精品久久久久久孕妇 | 久久高清毛片 | 午夜精品久久久99热福利 | 亚洲精区二区三区四区麻豆 | 少妇bbb| 国产品久精国精产拍 | 亚洲精品18日本一区app | 久久久三级视频 | 人人插人人爱 | 91视频91色 | 国产精品久久久网站 | 午夜视频免费在线观看 | 综合久久精品 | 国偷自产视频一区二区久 | 天天干天天爽 | 亚洲在线网址 | 少妇高潮冒白浆 | 成人黄色在线 | 久久艹人人 | 午夜精品成人一区二区三区 | 久久污视频| 日日夜夜骑 | 中文字幕高清免费日韩视频在线 | 在线草 | 久久女同性恋中文字幕 | 中文字幕在线观 | 天天摸夜夜添 | 免费网站v | 九热精品 | 天天综合人人 | 色av色av色av | 久久亚洲福利 | 久久久福利视频 | 狠狠操91| 亚洲欧美激情插 | 综合久久综合久久 | 亚洲国产激情 | 国产黄色免费在线观看 | 免费亚洲成人 | 国产无遮挡又黄又爽在线观看 | 欧美日韩在线观看不卡 | 久久只精品99品免费久23小说 | 国产香蕉视频在线播放 | 精品在线观看一区二区三区 | 中文字幕在线国产 | 黄色小说网站在线 | 美女av电影 | 国产一级片一区二区三区 | 毛片视频网址 | 日韩av高潮 | 国产精品一区二区免费 | 超碰个人在线 | 国产看片免费 | 成人久久久久久久久久 | 成人av在线直播 | 天天综合网入口 | 99爱在线| 亚洲综合激情五月 | 又黄又刺激 | 天天天天色射综合 | 久久精品久久久精品美女 | 久草在线久草在线2 | 99在线免费观看视频 | 国产aa精品| 亚洲精品777 | 国产精品久久久久av | 精品欧美一区二区三区久久久 | 久久精品福利视频 | 亚洲精品免费看 | 狠狠ri | 久久久久观看 | 国产精品一区二区三区视频免费 | 一本色道久久综合亚洲二区三区 | 精品久久久久久久久久久久久 | 五月开心婷婷网 | 国产一级片观看 | 国产一区二区不卡视频 | 国内揄拍国内精品 | 免费视频91 | 美女福利视频在线 | 国产精品久久久久久久久久久久冷 | 17婷婷久久www | 午夜在线日韩 | 精品国产乱码一区二区三区在线 | 日韩系列在线 | 亚洲精品视频中文字幕 | 在线午夜av | 人人草在线视频 | 综合伊人av | 在线久热 | 超碰999| 97人人爽| 九九热精品在线 | 成人观看 | 久久r精品 | 亚洲精品在线免费 | 96久久欧美麻豆网站 | 精品1区2区3区| av网站免费在线 | 91福利在线观看 | 91精品在线观看视频 | 99久久精品视频免费 | 色婷av | 青草草在线 | 日本精品免费看 | 欧美一级裸体视频 | 97高清免费视频 | 91丨九色丨高潮 | 成人精品视频 | 国产精品毛片一区二区在线 | 日韩视 | 99免费在线观看视频 | 日韩精品一二三 | 国产91勾搭技师精品 | 欧美国产亚洲精品久久久8v | 黄色成人av网址 | 中文字幕在线观看一区二区三区 | 麻花豆传媒一二三产区 | 香蕉久久国产 | 亚洲综合在线一区二区三区 | 丁香六月国产 | 国产又粗又硬又爽的视频 | 欧美999| 久久久久久久久久久久久久av | 久久国精品 | 色婷婷激情四射 | 成人黄色大片网站 | www视频在线播放 | 99精品视频一区 | 亚洲人成精品久久久久 | 在线视频免费观看 | 四虎国产永久在线精品 | 国产精品1区2区3区 久久免费视频7 | 国产精品完整版 | 色综合久久中文综合久久牛 | 99久久99视频| 久久99亚洲精品久久久久 | 成人午夜电影免费在线观看 | 国产精品一二三 | 中文字幕在线观看完整版 | 97人人爽 | 国产成人精品一区一区一区 | 亚洲精品久久久久久久蜜桃 | 国产又粗又猛又黄又爽视频 | 91资源在线播放 | 日日日日日 | 精品黄色在线观看 | 久久免费99 | 欧美日韩免费在线视频 | 日韩激情一二三区 | 国产一级黄色av | 久久免费的精品国产v∧ | 尤物一区二区三区 | www.婷婷色 | 久久国产精品小视频 | 手机看片午夜 | av免费网站在线观看 | 国产不卡精品 | 69精品久久 | 婷婷久久一区二区三区 | 亚洲情影院 | 欧美在线视频第一页 | 亚洲天堂免费视频 | 日韩黄色免费看 | 精品乱码一区二区三四区 | 高清国产一区 | 久久久精品欧美一区二区免费 | 一区二区三区韩国免费中文网站 | 日韩精品一区二区免费 | 亚洲视频 视频在线 | 狠狠色伊人亚洲综合网站野外 | 国产精品婷婷午夜在线观看 | 国产黄色大片 | 久草在线欧美 | 日韩欧美在线一区二区 | 九九九热精品免费视频观看 | 热99久久精品 | 久久国产精彩视频 | 久久久黄视频 | 日韩欧美一二三 | 色婷婷狠狠干 | 国产99久久精品一区二区300 | 亚洲精品国产精品国自产在线 | 国产精品久久久久永久免费观看 | 欧美国产日韩激情 | 2019久久精品 | 在线韩国电影免费观影完整版 | 玖玖视频 | av大全在线播放 | 国产在线观 | www操操 | 999成人精品 | 日韩资源在线观看 | 五月婷婷久草 | 午夜在线资源 | 成年人视频免费在线播放 | 久久国产高清视频 | 91色在线观看 | 8x成人免费视频 | 特黄特色特刺激视频免费播放 | 日本黄色特级片 | 人人爱人人做人人爽 | 久草视频在线资源站 | 91精品蜜桃 | 五月天电影免费在线观看一区 | 一区 二区 精品 | 亚洲一本视频 | 911香蕉视频| 成人午夜精品福利免费 | 国产99久久精品 | 国产午夜精品在线 | 中日韩三级视频 | 视频91在线 | 精品不卡视频 | 中文字幕精品三级久久久 | 二区视频在线 | 成人四虎 | 成人一区在线观看 | 国产原创中文在线 | av超碰在线 | 日韩理论电影在线观看 | www.国产高清 | 香蕉视频在线免费看 | 99精品国产福利在线观看免费 | 丁香资源影视免费观看 | 亚洲国产97在线精品一区 | 色夜视频 | 国产原创在线观看 | 热久久99这里有精品 | 99久热在线精品视频成人一区 | 91麻豆精品久久久久久 | 精品视频9999 | 色999精品| 99热国产在线中文 | 在线观看国产成人av片 | 国产精品成人一区二区 | 日精品在线观看 | 国产精品毛片久久 | 麻豆一级视频 | 免费合欢视频成人app | 亚洲成aⅴ人在线观看 | 国产免费一区二区三区最新 | 日韩超碰 | 国产精品 中文字幕 亚洲 欧美 | 欧洲精品视频一区二区 | 日本mv大片欧洲mv大片 | 日韩精品视频免费在线观看 | av中文字幕网站 | 九九热在线视频 | 91在线视频免费观看 | 日韩欧美视频 | 国产精品免费一区二区 | 91xav| 在线观看黄污 | 国产精品免费在线观看视频 | 综合国产在线 | 亚洲电影一级黄 | 狠狠色丁香九九婷婷综合五月 | 国产免费又粗又猛又爽 | 欧美一级久久久 | 人人射| 岛国av在线免费 | 欧美日韩三级 | 久久99精品国产99久久6尤 | 日韩视频在线观看免费 | 99精品免费久久久久久日本 | 天天操天天能 | 亚洲国产99 | 国产又黄又爽又猛视频日本 | 丝袜美女在线 | 波多野结衣在线观看一区 | 亚洲一区二区精品在线 | 天天干,天天射,天天操,天天摸 | 国产不卡视频在线播放 | 在线91观看 | 久久久久免费精品国产小说色大师 | 狠狠干中文字幕 | 国产精品成人一区 | www.久久色.com| 日本黄色一级电影 | 福利一区二区三区四区 | 国产麻豆成人传媒免费观看 | 久久精品国产精品亚洲 | 五月天九九 | www色婷婷com| 2019中文字幕网站 | 精品国产一区二区三区四区在线观看 | av一级在线 | 黄色大片免费网站 | 欧美,日韩 | 久久9999久久免费精品国产 | 亚洲成人午夜av | 韩国视频一区二区三区 | 久二影院 | 人人超碰在线 | 一区二区三区国 | 97国产视频 | 久久久久久久久久久久国产精品 | 欧美一区日韩一区 | 亚洲国产精品一区二区久久hs | 999视频在线播放 | 成人免费网站视频 | 亚洲一区日韩 | 美女视频黄是免费的 | 97成人精品视频在线播放 | 成人黄色大片 | 美女在线免费视频 | 国产生活一级片 | 色综合久久久久久久 | 成年人网站免费在线观看 | 91精品国产自产在线观看 | sm免费xx网站| 日韩在线大片 | 2019中文最近的2019中文在线 | 天天操天天操一操 | 午夜av在线 | 精品三级av | 免费在线一区二区 | 久草视频在线看 | 日本电影黄色 | 国产精品99久久久久久大便 | 国产专区精品视频 | 欧美日韩伦理在线 | 激情综合网色播五月 | 亚洲欧美经典 | 黄色高清视频在线观看 | 激情综合交 | 午夜丁香网 | 欧美狠狠色| 久久国产剧场电影 | 欧美性生活免费 | 国产69精品久久久久久 | 一区二区电影在线观看 | 五月在线视频 | 国产日本亚洲 | 天天干天天射天天插 | 99久久99久久免费精品蜜臀 | av中文字幕亚洲 | 激情丁香 | av短片在线观看 | 在线免费视 | 免费www视频 | av在线免费在线观看 | 日韩电影在线观看一区 | 激情影音 | 亚洲综合导航 | 国产一区免费看 | 在线观看黄色国产 |