鏈結指令碼(1)

2021-06-06 13:30:40 字數 3057 閱讀 3441

1、什麼是ld?它有什麼作用?

ld是gnu binutils工具集中的乙個,是眾多linkers(鏈結器)的一種。完成的功能自然也就是鏈結器的基本功能:把各種目標檔案和庫檔案鏈結起來,並重定向它們的資料,完成符號解析。linking其實主要就是完成四個方面的工作:storage allocation、symbol management、libraries、relocation。

ld可以識別一種linker command language表示的linker scriopt檔案來顯式的控制鏈結的過程。通過bfd(binary format description)庫,ld可以讀取和操作coff(common object file format)、elf(executable and linking format)、a.out等各種格式的目標檔案。

2、常用的選項

-b target  設定目標檔案的檔案格式

-e address 設定目標檔案的開始位址

-eb  鏈結big-endian的目標檔案

-el  鏈結small-endian的目標檔案

-l libname    建立執行程式時要鏈結的庫檔案(比如某個庫為test,則可以為-ltest)

-l directory  尋找要鏈結的庫檔案時搜尋的檔案路徑

-o file  設定輸出檔案的名字

-s  去除輸出檔案中的所有符號資訊

-s  去除輸出檔案中的除錯符號資訊

-v  輸出ld的版本資訊

-x  去除所有的區域性符號資訊

-x  去除臨時的區域性符號資訊,預設情況下會設定這個選項

-bstatic   建立的輸出檔案鏈結靜態鏈結庫

-bdynamic  建立的輸出檔案鏈結動態鏈結庫

-tbss address  設定section bss的起始位址

-tdata address 設定section data的起始位址

-ttext address 設定section text的起始位址

3、鏈結描述指令碼

鏈結描述指令碼描述了各個輸入檔案的各個section如何對映到輸出檔案的各section中,並控制輸出檔案中section和符號的記憶體布局。

每個有loadable或allocatable標識的輸出section有兩種位址,一種是vma(virtual memory address),這種位址是輸出檔案執行時section的執行位址;一種是lma(load memory address),這種位址是載入輸出檔案時section的載入位址。一般,這兩種位址相同。但在嵌入式系統中,經常存在執行位址和載入位址不一致的情況。如把輸出檔案載入到開發板的flash儲存器中(位址由lma指定),但執行時,要把flash儲存器中的輸出檔案複製到sdram中執行(位址有 vma指定)。

在鏈結指令碼中使用注釋,可以用「/*...*/」。

每個目標檔案有許多符號,每個符號有乙個名字和乙個位址,乙個符號可以是定義的,也可以是未定義的。對於普通符號,需要乙個特殊的標識,因為在目標檔案中,普通符號沒有乙個特定的輸入section。鏈結器會把普通符號處理成好像它們都在乙個叫做common的section中。

下面給出vivi的ld script的內容及分析。

(1)[makefile]

linkflags =

-tarch/vivi.

lds-bstatic

可見,鏈結的指令碼是arch/vivi.lds,而且鏈結靜態庫。但是在arch下沒有vivi.lds,而是有vivi.lds.in。看了一下vivi.lds.in的內容,

sections

.data align(4)

:.bss align(4):}

很明顯,這個就是原始的vivi的鏈結指令碼。但是存在乙個變數textaddr沒有賦值,也就是說,這個量根據配置的不同是不同的,所以肯定就在makefile中執行了生成方法。下一步就要看[arch/makefile]

(2)[arch/makefile]

ldscript = arch/vivi.lds.in

ifeq (

$(config_arch_s3c2410)

,y)machine = s3c2410

ifeq (

$(config_s3c2410_nand_boot)

,y)textaddr = 0x33f00000

else

textaddr = 0x00000000

endif

endif

vivi: $(head) arch/vivi.lds

arch/vivi.lds: $(ldscript)

@sed s/textaddr/

$(textaddr)

/ $(ldscript)

>$@

很明顯,這步主要完成的工作就是要把vivi.lds.in檔案中的textaddr用配置後的實際值來代替。根據我的配置,這裡我的textaddr就是0x33f00000.

sections

.data align(4)

:.bss align(4):}

sections表示段。第一行表示當前位址為0x33f00000,就是vma,同時也是text段的起始位址。第二行用了萬用字元*表示所有字元,這裡的意思就是說指定的每個目標檔案的text section的內容都放到同乙個.text中。第三行表示指定的每個目標檔案的data section的內容都放到同乙個.data中,而且要四位元組邊界對齊。第四行表示指定的每個目標檔案的bss section的內容都放到同乙個.bss中,所有的普通符號都放到common中,而且要四位元組邊界對齊。

這算是最為簡單的ld scripts,不過也夠用了。如果不考慮對齊等因素,則可以直接在命令列中指定-ttext 0x33f00000,就可以完成了。當然,對linux kernel等,ld scripts要處理複雜的記憶體分配等操作,相應的要複雜一些,讀那些的方法就是查閱using ld手冊,同時還要研究mcu的記憶體分配,這樣才能作出合理的安排

鏈結指令碼(1)

分類 鏈結指令碼 makefile 2012 05 17 20 49 1126人閱讀收藏 舉報 指令碼linker makefile allocation file flash 1 什麼是ld?它有什麼作用?ld是gnu binutils工具集中的乙個,是眾多linkers 鏈結器 的一種。完成的功...

Linker script 鏈結器指令碼(1)

每個鏈結都由鏈結指令碼控制著,指令碼由鏈結器命令語言組成。指令碼的主要目的是描述如何把輸入檔案中的節 sections 對映到輸出檔案中,並控制輸出檔案的儲存布局。大多數的鏈結指令碼就是做這些事情的,但在有必要時,指令碼也可以指導鏈結器執行一些其他的操作。鏈結器總是使用鏈結器指令碼,如果你沒有提供乙...

GNU鏈結指令碼學習(1)

最簡單的鏈結指令碼只有乙個命令 sections 使用 sections 命令描述輸出檔案記憶體布局。sections 命令是非常強大的,在這我們將解釋它的簡單用法。現在假設你的程式只是由單一 段 初始化數段和未初始化資料段,分別對應 text data bss 的段名。再假設輸入檔案中也只出現這些...