天天看點

Linux連結腳本學習--lds

l一、概論

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)是連接配接腳本的基本單元,它表示輸入檔案中的某部分怎麼放置.

完整的連結腳本

繼續閱讀