Linux之鏈接腳本

1. 什麼是鏈接腳本

    鏈接器主要有兩個作用,一是將若干輸入文件(.o文件)根據一定規則合併爲一個輸出文件(例如ELF格式的可執行文件);是將符號與地址綁定。本文只關心它的第一個功能,即如何根據一定規則將一個或多個輸入文件合併成輸出文件。這裏的一定規則是通過鏈接腳本描述的。鏈接器有一個編譯到其二進制代碼中的默認鏈接腳本可以使用–verbose命令行顯示缺省的鏈接器腳本的內容,大多數情況下使用它鏈接輸入文件並生成目標文件。當然,我們也可以提供自定義的腳本以精確控制目標文件的格式,如同Linux內核做得那樣,鏈接器“- T”參數用於指定自定義的腳本文件。

2.簡單的鏈接腳本示例

鏈接腳本由一系列命令組成, 每個命令由一個關鍵字(一般在其後緊跟相關參數)或一條對符號的賦值語句組成. 命令由分號‘;’分隔開. 
假設你的程序只有代碼段,初始化過的數據段,和未初始化過的數據段.這些會存在於‘.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放在此處開始的地址.

3.簡單的鏈接腳本命令

設置入口點 

在運行一個程序時,第一個被執行到的指令成爲‘入口點’.你可以使用‘ENTRY’鏈接腳本命令來設置入口點.參數是一個符號名,如下: 
ENTRY(SYMBOL) 
有很多不同的方法來設置入口點.鏈接器會通過按順序嘗試一下方法來設置入口點. 
1,‘-e’入口命令行選項 
2,鏈接腳本中的ENTRY(SYMBOL)命令 
3,如果定義了start,就使用start的值 
4,如果存在就使用‘.text’段的首地址 
5,地址‘0’

4.基本概念

bss段: 

BSS段(bsssegment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文BlockStarted by Symbol的簡稱。BSS段屬於靜態內存分配。

data段: 

數據段(datasegment)通常是指用來存放程序中已初始化的全局變量的一塊內存區域。數據段屬於靜態內存分配。

text段: 

代碼段(codesegment/textsegment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀,某些架構也允許代碼段爲可寫,即允許修改程序。

rodata段: 

存放C中的字符串和#define定義的常量

heap堆: 

堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)

stack棧: 

是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{}”中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束後,函數的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來保存/恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

常量段: 

常量段一般包含編譯器產生的數據(與只讀段包含用戶定義的只讀數據不同)。比如說由一個語句a=2+3編譯器把2+3編譯就算出5,存成常量5在常量段中


text和data段都在可執行文件中(在嵌入式系統裏一般是固化在鏡像文件中),由系統從可執行文件中加載; 而bss段不在可執行文件中,由系統初始化。

一般情況下,一個程序本質上都是由 bss段、data段、text段三個組成的——本概念是當前的計算機程序設計中是很重要的一個基本概念。而且在嵌入式系統的設計中也非常重要,牽涉到嵌入式系統運行時的內存大小分配,存儲單元佔用空間大小的問題。

在採用段式內存管理的架構中(比如intel的80x86系統),bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域,一般在初始化時bss 段部分將會清零(bss段屬於靜態內存分配,即程序一開始就將其清零了)。

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