Linux下的lds鏈結指令碼簡介(四)

2021-06-29 13:05:05 字數 4062 閱讀 4835

linux下的lds鏈結指令碼簡介(四)

小狼@十一、 表示式

lds中表示式的文法與c語言的表示式文法一致,表示式的值都是整型,如果ld的執行主機和生成檔案的目標機都是32位,則表示式是32位資料,否則是64位資料。

以下是一些常用的表示式:

_fourk_1 = 4k;

/* k、m單位 */

_fourk_2 = 4096;

/* 整數 */

_fourk_3 = 0×1000; 

/* 16 進製 */

_fourk_4 = 01000; 

/* 8 進製 */

注意:1k=1024 1m=1024*1024

11.1、符號名

沒有被引號」"包圍的符號,以字母、下劃線或』.'開頭,可包含字母、下劃線、』.'和』-'。當符號名被引號包圍時,符號名可以與關鍵字相同。如,

「section」=9;

「with a space」 = 「also with a space」 + 10;

11.2、定位符號』.'

只在sections命令內有效,代表乙個程式位址空間內的位址。

注意:在連線時,當定位符用在sections命令的

輸出section描述內

時,它代表的是該section的當前**偏移**,而不是程式位址空間的絕對位址。當然當程式載入後,符號最後的位址還是程式位址空間的絕對位址。

示例11.2_1:

sections

= 0×1234;

}其中由於對定位符的賦值而產生的空隙由0×1234填充。其他的內容應該容易理解吧。

示例11.2_2:

sections

.= 0×500

.data

: } 

.text section在程式位址空間的開始位置是0x100

示例11.2_3

檔案src\a.c

#include

int a = 100;

int b=0;

int c=0;

int d=1;

int main()

檔案lds\a.lds

a = 10; 

/* 全域性位置 */

sections

_bdata = (. + 3) & ~ 4; 

/* sections命令內 */

.data :

} 在沒有使用a.lds情況下編譯

gcc -wall -o a-without-lds.exe ./src/a.c

執行./a-without-lds.exe

結果:&a=0x601020

&b=0x601038

&c=0x60103c

&d=0x601024

在使用a.lds情況下編譯

gcc -wall -o a-with-lds.exe ./src/a.c ./lds/a.lds

執行./a-with-lds.exe

結果:&a=0xa

&b=0xb

&c=0x400638

&d=0x402b20

10.3、表示式的操作符

在lds中,表示式的操作符與c語言一致。

優先順序 結合順序 操作符 1

left ! – ~

(1)2

left * / %

3left + -

4left >>  =

5left &

6left |

7left &&

8left ||

9right ? :

10right &= += -= *= /= 

(2)(1)表示字首符,(2)表示賦值符。

10.4、表示式的計算

聯結器延遲計算大部分表示式的值。

但是,對待與連線過程緊密相關的表示式,聯結器會立即計算表示式,如果不能計算則報錯。比如,

例子,

sections

}這個例子中,9+this_isnt_constant表示式的值用於設定.text section的vma位址,因此需要立即運算,但是由於this_isnt_constant變數的值不確定,所以此時聯結器無法確立表示式的值,此時聯結器會報錯。

10.5、相對值與絕對值

在輸出section描述內

的表示式,聯結器取其

相對值,相對與該section的開始位置的偏移

在sections命令內且非輸出section描述內

的表示式,聯結器取其

絕對值通過absolute關鍵字可以將相對值轉化成絕對值,即在原來值的基礎上加上表示式所在section的vma值。

示例

sections

}該例子中,_edata符號的值是.data section的末尾位置(絕對值,在程式位址空間內)。

10.6、內建函式

lds中有以下一些內建函式:

absolute(exp) :轉換成絕對值

addr(section) :返回某section的vma值。

align(exp) :返回定位符』.'的按照exp進行對齊後的修調值,對齊後的修調值演算法為:(. + exp – 1) & ~(exp – 1)。

block(exp) :如同align(exp),為了向前相容。

defined(symbol) :如果符號symbol在全域性符號表內,且被定義了,那麼返回1,否則返回0。

示例

sections …

}loadaddr(section) :返回三section的lma

max(exp1,exp2) :返回大者

min(exp1,exp2) :返回小者

next(exp) :返回下乙個能被使用的位址,該位址是exp的倍數,類似於align(exp)。除非使用了memory命令定義了一些非連續的記憶體塊,否則next(exp)與aligh(exp)一定相同。

sizeof(section) :返回section的大小。當section沒有被分配時,即此時section的大小還不能確定時,聯結器會報錯。

sizeof_headers :返回輸出檔案頭部的位元組數。這些資訊出現在輸出檔案的開始處。當設定第乙個段的開始位址時,你可以使用這個數字。如果你選擇了加速分頁,當產生乙個elf輸出檔案時,如果鏈結器指令碼使用sizeof_headers內建函式,聯結器必須在它

算出所有段位址和長度之前計算程式頭部的數值。如果聯結器後來發現它需要附加程式頭,它將報告乙個「not enough room for 

program headers」錯誤。為了避免這樣的錯誤,你必須避免使用sizeof_headers函式,或者你必須修改你的聯結器指令碼去避免強制

聯結器去使用附加程式頭,或者你必須使用phdrs命令去定義你自己的程式頭

十二、 暗含的連線指令碼

輸入檔案可以是目標檔案,也可以是連線指令碼,此時的連線指令碼被稱為 暗含的連線指令碼

如果聯結器不認識某個輸入檔案,那麼該檔案被當作連線指令碼被解析。更進一步,如果發現它的格式又不是連線指令碼的格式,那麼聯結器報錯。

乙個暗含的連線指令碼不會替換預設的連線指令碼,僅僅是增加新的連線而已。

一般來說,暗含的連線指令碼符號分配命令,或input、group、version命令。

在連線命令列中,每個輸入檔案的順序都被固定好了,暗含的連線指令碼在連線命令行內佔住乙個位置,這個位置決定了由該連線指令碼指定的輸入檔案在連線過程中的順序。

典型的暗含的連線指令碼是libc.so檔案,在gnu/linux內一般存在/usr/lib目錄下。

參考文獻:linux下的lds鏈結指令碼簡介

Linux下的lds鏈結指令碼簡介(四)

十一 表示式 lds中表示式的文法與c語言的表示式文法一致,表示式的值都是整型,如果ld的執行主機和生成檔案的目標機都是32位,則表示式是32位資料,否則是64位資料。以下是一些常用的表示式 fourk 1 4k k m單位 fourk 2 4096 整數 fourk 3 0 1000 16 進製 ...

Linux下的lds鏈結指令碼簡介(四)

十一 表示式 lds中表示式的文法與c語言的表示式文法一致,表示式的值都是整型,如果ld的執行主機和生成檔案的目標機都是32位,則表示式是32位資料,否則是64位資料。以下是一些常用的表示式 fourk 1 4k k m單位 fourk 2 4096 整數 fourk 3 0 1000 16 進製 ...

Linux下的lds鏈結指令碼簡介(四)

十一 表示式 lds中表示式的文法與c語言的表示式文法一致,表示式的值都是整型,如果ld的執行主機和生成檔案的目標機都是32位,則表示式是32位資料,否則是64位資料。以下是一些常用的表示式 fourk 1 4k k m單位 fourk 2 4096 整數 fourk 3 0 1000 16 進製 ...