Linux鏈接腳本學習--lds

一、概論

ld:

GNU的鏈接器.

用來把一定量的目標文件跟檔案文件鏈接在一起,並重新定位它們的數據,鏈接符號引用.

一般編譯一個程序時,最後一步就是運行ld進行鏈接

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

二、鏈接腳本

鏈接腳本的一個主要目的是描述輸入文件中的各個段(數據段,代碼段,堆,棧,bss)如何被映射到輸出文件中,並控制輸出文件的內存排布.

鏈接器總是使用鏈接腳本的,如果你不提供,則鏈接器會使用一個缺省的腳本,這個腳本是被編譯進鏈接器可執行文件的.

可以使用--verbose命令行顯示缺省的鏈接器腳本的內容.

你可以使用-T命令行來提供你自己的鏈接腳本來替換缺省的鏈接腳本.

三、簡單的鏈接腳本示例.

許多腳本是相當簡單的.

可能最簡單的腳本只含有一個命令:’SECTIONS’.

你可以使用’SECTIONS’來描述輸出文件的內存佈局.

‘SECTIONS’是一個功能很強大的命令.

假設你的程序只有代碼段,初始化過的數據段,和未初始化過的數據段.這些會存在於’.text’,’data’,’bss’段中.

對於這個例子,假設代碼應該被載入到地址0x1000處,而數據應該從0x8000000開始,如下是實現這個功能的腳本:

SECTIONS

{

.=0x1000;

.text:{*(.text)}

.=0x8000000;

.data:{*(.data)}

.bss:{*(.bss)}

}

具體分析:

關鍵字’SECTIONS’開始於這個配置.後面跟有一串放在花括號中的符號賦值和輸出端描述的內容.

第一行是對一個特殊的符號’.’賦值,這是一個定位標識器.如果你沒有以其他的方式制定輸出段的地址,那地址值就會被設爲定位標識器的現有值,即0x1000.

第二行定義一個輸出段,’.text’.冒號’:’是語法需要,現在可以被忽略.段後面的花括號中,應該列出所有應該放入這個輸出段中的輸入端的名字.’*’是通配符,匹配所有文件名.即將所有輸入文件中的.text段都保存在此段中.

餘下的是.data和.bss段,同理,鏈接器會把所有.data段從地址0x8000000開始處放置.

最後,定位標識器的值變爲0x8000000加上所有.data段的地址.此時鏈接器把所有.bss放在此處開始的地址.

 

四、簡單的鏈接腳本命令

設置入口點

在運行一個程序時,第一個被執行到的指令成爲”入口點”.你可以使用”ENTRY”鏈接腳本命令來設置入口點.參數是一個符號名,如下:

ENTRY(SYMBOL)

有很多不同的方法來設置入口點.鏈接器會通過按順序嘗試一下方法來設置入口點,如果成功了,就會停止.

1,’-e’ 入口命令行選項

2,鏈接腳本中的ENTRY(SYMBOL)命令

3,如果定義了start,就使用start的值

4,如果存在就使用’.text’段的首地址

5,地址’0’

 

 

 

五、命令行設置鏈接地址

ld用於將多個obj或者so(庫)文件鏈接成可執行文件.

使用-T選項可以指定數據段,代碼段,bss段起始位置.(-T只用於鏈接bootloader、內核等沒有底層軟件支持的軟件.鏈接運行於操作系統之上的應用程序時,一般使用默認方式鏈接).

1,直接指定代碼段、數據段、bss段起始地址

如下:

-Ttext startaddr

-Tdata startaddr

-Tbss  startaddr

例如:

ld –Ttext 0x00000000 –g led_on.o –o led_on_elf

2,直接使用鏈接腳本來設置起始地址

ld –Ttimer.lds –o timer_elf a.o b.o

鏈接腳本timer.lds內容如下:

SECTIONS{

.=0x30000000;

.text : {*(.text)}

.rodata ALIGN(4) : {*(.rodata)}

.data ALIGN(4) : {*(.data)}

.bss ALIGN(4) : {*.(.bss) *(COMMON)}

}

一個SECTIONS命令內部包含一個或多個段,段(section)是連接腳本的基本單元,它表示輸入文件中的某部分怎麼放置.

完整的鏈接腳本

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章