連接腳本分析_第1頁
連接腳本分析_第2頁
連接腳本分析_第3頁
連接腳本分析_第4頁
連接腳本分析_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、鏈接腳本分析(2009-01-21 14:22:22)轉(zhuǎn)載Q標簽:雜談簡單腳本命令1 -ENTRY(SYMBOL):將符號SYMBOL的值設(shè)置成入口地址.入口地址(entry point):進程執(zhí)行的第一條用戶空間的指令在進程地址空間的 地址)ld有多種方法設(shè)置進程入口地址,按一下順序:(編號越前,優(yōu)先級越高)ld命令行的-e選項連接腳本的ENTRY(SYMBOL)命令如果定義了 start符號,使用start符號值如果存在.text section,使用.text section的第一字節(jié)的位置值使用值02 -INCLUDE filename :包含其他名為filename的鏈接腳本相當于c

2、程序內(nèi)的的#include指令,用以包含另一個鏈接腳本.腳本搜索路徑由-L選項指定.INCLUDE指令可以嵌套使用,最大深度為10.艮阡 文件1內(nèi)INCLUDE文件2,文件2內(nèi)INCLUDE文件3.,文件10內(nèi)INCLUDE 文件11.那么文件11內(nèi)不能再出現(xiàn)INCLUDE指令了.3 -INPUT(files):將括號內(nèi)的文件做為鏈接過程的輸入文件ld首先在當前目錄下尋找該文件,如果沒找到,則在由-L指定的搜索路徑下搜 索.file可以為-lfile形式,就象命令行的-l選項一樣.如果該命令出現(xiàn)在 暗含的腳本內(nèi),則該命令內(nèi)的file在鏈接過程中的順序由該暗含的腳本在命令 行內(nèi)的順序決定.4 -

3、GROUP(files):指定需要重復搜索符號定義的多個輸入文件file必須是庫文件,且file文件作為一組被ld重復掃描,直到不在有新的未 定義的引用出現(xiàn).5 -OUTPUT(FILENAME):定義輸出文件的名字同ld的-0選項,不過-o選項的優(yōu)先級更高.所以它可以用來定義默認的輸出文 件名.如a.out6 SEARCH_DIR(PATH):定義搜索路徑,同ld的-L選項,不過由-L指定的路徑要比它定義的優(yōu)先被搜索.-7 -STARTUP(filename):指定filename為第一個輸入文件在鏈接過程中,每個輸入文件是有順序的.此命令設(shè)置文件filename為第一個 輸入文件.8 OU

4、TPUT_FORMAT (BFDNAME):設(shè)置輸出文件使用的BFD格式同ld選項-o format BFDNAME,不過ld選項優(yōu)先級更高.-9 -OUTPUT_FORMAT(DEFAULT,BIG,LITTLE):定義三種輸出文件的格式(大小端)若有命令行選項-EB,則使用第2個BFD格式;若有命令行選項-EL,則使用第3 個BFD格式.否則默認選第一個BFD格式.TARGET(BFDNAME):設(shè)置輸入文件的BFD格式同ld選項-b BFDNAME.若使用了 TARGET命令,但未使用OUTPUT_FORMAT命令, 則最用一個TARGET命令設(shè)置的BFD格式將被作為輸出文件的BFD格式

5、.另外還有一些:ASSERT(EXP, MESSAGE):如果EXP不為真,終止連接過程EXTERN(SYMBOL SYMBOL .):在輸出文件中增加未定義的符號,如同連接器選 項-uFORCE_COMMON_ALLOCATION:為 common symbol(通用符號)分配空間,即使用了 -r連接選項也為其分配NOCROSSREFS(SECTION SECTION .):檢查列出的輸出section,如果發(fā)現(xiàn)他們 之間有相互引用,則報錯.對于某些系統(tǒng),特別是內(nèi)存較緊張的嵌入式系統(tǒng),某 些section是不能同時存在內(nèi)存中的,所以他們之間不能相互引用.OUTPUT_ARCH(BFDARCH

6、):設(shè)置輸出文件的 machine architecture(體系結(jié)構(gòu)), BFDARCH為被BFD庫使用的名字之一.可以用命令objdump -f查看.可通過man -S 1 ld查看ld的聯(lián)機幫助,里面也包括了對這些命令的介紹.對符號的賦值在目標文件內(nèi)定義的符號可以在鏈接腳本內(nèi)被賦值.(注意和C語言中賦值的不 同!)此時該符號被定義為全局的.每個符號都對應(yīng)了一個地址,此處的賦值是 更改這個符號對應(yīng)的地址.e.g.通過下面的程序查看變量a的地址:#include int a = 100;int main(void)(printf( &a=0 x%p , &a );return 0;a = 3

7、;$ gcc -Wall -o a-without-lds a.c&a = 0 x8049598$ gcc -Wall -o a-with-lds a.c a.lds&a = 0 x3注意:對符號的賦值只對全局變量起作用!一些簡單的賦值語句能使用任何c語言內(nèi)的賦值操作:SYMBOL = EXPRESSION ;SYMBOL += EXPRESSION ;SYMBOL -= EXPRESSION ;SYMBOL *= EXPRESSION ;SYMBOL /= EXPRESSION ;SYMBOL = EXPRESSION ;SYMBOL &= EXPRESSION ;SYMBOL |= EXP

8、RESSION ;除了第一類表達式外,使用其他表達式需要SYMBOL被定義于某目標文件.是一個特殊的符號,它是定位器,一個位置指針,指向程序地址空間內(nèi)的某位 置(或某section內(nèi)的偏移,如果它在SECTIONS命令內(nèi)的某section描述內(nèi)), 該符號只能在SECTIONS命令內(nèi)使用.注意:賦值語句包含4個語法元素:符號名、操作符、表達式、分號;一個也不 能少.被賦值后,符號所屬的section被設(shè)值為表達式EXPRESSION所屬的SECTION(參 看11.腳本內(nèi)的表達式)賦值語句可以出現(xiàn)在連接腳本的三處地方:SECTIONS命令內(nèi),SECTIONS命令內(nèi) 的section描述內(nèi)和全局

9、位置;如下, floating_point = 0;SECTIONS(.text :(*(.text)_etext = .;_bdata = (. + 3) & 4;.data : *(.data) PROVIDE關(guān)鍵字該關(guān)鍵字用于定義這類符號:在目標文件內(nèi)被引用,但沒有在任何目標文件內(nèi)被 定義的符號.例子:SECTIONS(.text :(*(.text)_etext =.;PROVIDE(etext =.);當目標文件內(nèi)引用了 etext符號,確沒有定義它時,etext符號對應(yīng)的地址被定 義為.text section之后的第一個字節(jié)的地址.SECTIONS 命令SECTIONS命令告訴l

10、d如何把輸入文件的sections映射到輸出文件的各個 section:如何將輸入section合為輸出section;如何把輸出section放入程 序地址空間(VMA)和進程地址空間(LMA).該命令格式如下:SECTIONS (SECTIONS-COMMANDSECTIONS-COMMAND.SECTION-COMMAND 有四種:ENTRY 命令符號賦值語句一個輸出 section 的描述(output section description)一個 section 疊加描述(overlay description)如果整個連接腳本內(nèi)沒有SECTIONS命令,那么ld將所有同名輸入sec

11、tion合成 為一個輸出section內(nèi),各輸入section的順序為它們被連接器發(fā)現(xiàn)的順序.如果某輸入section沒有在SECTIONS命令中提到,那么該section將被直接拷 貝成輸出section.輸出section描述輸出section描述具有如下格式:SECTION ADDRESS (TYPE) : AT(LMA) (OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND REGION ATLMA_REGION :PHDR :PHDR . =FILLEXP內(nèi)的內(nèi)容為可選選項,一般不需要.SECTION: section 名字SECTION左右的空

12、白、圓括號、冒號是必須的,換行符和其他空格是可選的.每個OUTPUT-SECTION-COMMAND為以下四種之一,符號賦值語句一個輸入section描述直接包含的數(shù)據(jù)值一個特殊的輸出section關(guān)鍵字輸出 section 名字(SECTION):輸出section名字必須符合輸出文件格式要求,比如:a.out格式的文件只允許 存在.text、.data和.bss section名.而有的格式只允許存在數(shù)字名字,那么此 時應(yīng)該用引號將所有名字內(nèi)的數(shù)字組合在一起;另外,還有一些格式允許任何序 列的字符存在于section名字內(nèi),此時如果名字內(nèi)包含特殊字符(比如空格、逗 號等),那么需要用引號將

13、其組合在一起.輸出 section 地址(ADDRESS):ADDRESS是一個表達式,它的值用于設(shè)置VMA.如果沒有該選項且有REGION選項, 那么連接器將根據(jù)REGION設(shè)置VMA;如果也沒有REGION選項,那么連接器將根 據(jù)定位符號.的值設(shè)置該section的VMA,將定位符號的值調(diào)整到滿足輸出 section對齊要求后的值,輸出section的對齊要求為:該輸出section描述內(nèi) 用到的所有輸入section的對齊要求中最嚴格的.例子:.text . : *(.text) 和.text : *(.text) 這兩個描述是截然不同的,第一個將.text section的VMA設(shè)置為

14、定位符號的值, 而第二個則是設(shè)置成定位符號的修調(diào)值,滿足對齊要求后的.ADDRESS可以是一個任意表達式,比如ALIGN(0 x10)這將把該section的VMA設(shè) 置成定位符號的修調(diào)值,滿足16字節(jié)對齊后的.注意:設(shè)置ADDRESS值,將更改定位符號的值.輸入section描述:最常見的輸出section描述命令是輸入section描述.輸入section描述是最基本的連接腳本描述.輸入section描述基礎(chǔ):基本語法:FILENAME(EXCLUDE_FILE (FILENAME1 FILENAME2 .) SECTION1 SECTION2 .)FILENAME文件名,可以是一個特定的

15、文件的名字,也可以是一個字符串模式.SECTION名字,可以是一個特定的section名字,也可以是一個字符串模式 例子是最能說明問題的,*(.text):表示所有輸入文件的.text section(*(EXCLUDE_FILE (*crtend.o *otherfile.o) .ctors):表示除 crtend.o、 otherfile.o文件外的所有輸入文件的.ctors section.data.o(.data):表示 data.o 文件的.data sectiondata.o :表示data.o文件的所有section*(.text .data):表示所有文件的.text sect

16、ion 和.data section,順序是: 第一個文件的.text section,第一個文件的.data section,第二個文件的.text section,第二個文件的.data section, .*(.text) *(.data):表示所有文件的.text section 和.data section,順序 是:第一個文件的.text section,第二個文件的.text section, .,最后一 個文件的.text section,第一個文件的.data section,第二個文件的.data section, .,最后一個文件的.data section下面看連接器是

17、如何找到對應(yīng)的文件的.當FILENAME是一個特定的文件名時,連接器會查看它是否在連接命令行內(nèi)出現(xiàn) 或在INPUT命令中出現(xiàn).當FILENAME是一個字符串模式時,連接器僅僅只查看它是否在連接命令行內(nèi)出 現(xiàn).注意:如果連接器發(fā)現(xiàn)某文件在INPUT命令內(nèi)出現(xiàn),那么它會在-L指定的路徑 內(nèi)搜尋該文件.字符串模式內(nèi)可存在以下通配符:* :表示任意多個字符?:表示任意一個字符CHARS:表示任意一個CHARS內(nèi)的字符,可用-號表示范圍,如:a-z:表示引用下一個緊跟的字符在文件名內(nèi),通配符不匹配文件夾分隔符/,但當字符串模式僅包含通配符*時除 外.任何一個文件的任意section只能在SECTIONS

18、命令內(nèi)出現(xiàn)一次.看如下例子, SECTIONS (.data : *(.data) .data1 : ( data.o(.data) data.o 文件的.data section 在第一個 OUTPUT-SECTION-COMMAND 命令內(nèi)被使用 了,那么在第二個OUTPUT-SECTION-COMMAND命令內(nèi)將不會再被使用,也就是說 即使連接器不報錯,輸出文件的.data1 section的內(nèi)容也是空的.再次強調(diào):連接器依次掃描每個OUTPUT-SECTION-COMMAND命令內(nèi)的文件名,任 何一個文件的任何一個section都只能使用一次.讀者可以用-M連接命令選項來產(chǎn)生一個map

19、文件,它包含了所有輸入section 到輸出section的組合信息.再看個例子,SECTIONS (.text : *(.text) .DATA : ( A-Z*(.data) .data : *(.data) .bss : *(.bss) 這個例子中說明,所有文件的輸入.text section組成輸出.text section ;所 有以大寫字母開頭的文件的.data section組成輸出.DATA section,其他文件 的.data section組成輸出.data section;所有文件的輸入.bss section組成 輸出.bss section.可以用SORT()關(guān)鍵字

20、對滿足字符串模式的所有名字進行遞增排序,如 SORT(.text*).通用符 號(common symbol)的輸入 section:在許多目標文件格式中,通用符號并沒有占用一個section.連接器認為:輸入 文件的所有通用符號在名為COMMON的section內(nèi).例子,.bss *(.bss) *(COMMON) 這個例子中將所有輸入文件的所有通用符號放入輸出.bss section內(nèi).可以看到 COMMOM section的使用方法跟其他section的使用方法是一樣的.有些目標文件格式把通用符號分成幾類.例如,在MIPS elf目標文件格式中,把 通用符號分成standard comm

21、on symbols(標準通用符號)和small common symbols(微通用符號,不知道這么譯對不對?),此時連接器認為所有standard common symbols 在 COMMON section 內(nèi),而 small common symbols 在.scommon section 內(nèi).在一些以前的連接腳本內(nèi)可以看見COMMON,相當于*(COMMON),不建議繼續(xù)使 用這種陳舊的方式.輸入section和垃圾回收:在連接命令行內(nèi)使用了選項-gc-sections后,連接器可能將某些它認為沒用的 section過濾掉,此時就有必要強制連接器保留一些特定的section,可用K

22、EEP() 關(guān)鍵字達此目的.如 KEEP(*(.text)或 KEEP(SORT(*)(.text) 最后看個簡單的輸入section相關(guān)例子: SECTIONS (outputa 0 x10000 :(all.ofoo.o (.input1)outputb :(foo.o (.input2)foo1.o (.input1)outputc :(*(.input1)*(.input2)本例中,將all.o文件的所有section和foo.o文件的所有(一個文件內(nèi)可以有 多個同名 section).input1 section 依次放入輸出 outputa section 內(nèi),該 section

23、的 VMA 是 0 x10000;將 foo.o 文件的所有.input2 section 和 foo1.o 文 件的所有.input1 section依次放入輸出outputb section內(nèi),該section的VMA 是當前定位器符號的修調(diào)值(對齊后);將其他文件(非all.o、foo.o、fool.o) 文件的.inputl section 和.input2 section 放入輸出 outputc section 內(nèi). 在輸出section存放數(shù)據(jù)命令:能夠顯示地在輸出section內(nèi)填入你想要填入的信息(這樣是不是可以自己通過 連接腳本寫程序?當然是簡單的程序).BYTE(EXPR

24、ESSION) 1 字節(jié)SHORT(EXPRESSION) 2 字節(jié)LOGN(EXPRESSION) 4 字節(jié)QUAD(EXPRESSION) 8 字節(jié)SQUAD(EXPRESSION) 64位處理器的代碼時,8字節(jié)輸出文件的字節(jié)順序big endianness或little endianness,可以由輸出目標 文件的格式?jīng)Q定;如果輸出目標文件的格式不能決定字節(jié)順序,那么字節(jié)順序與 第一個輸入文件的字節(jié)順序相同.如:BYTE(1)、LANG(addr).注意,這些命令只能放在輸出section描述內(nèi),其他地方不行.錯誤:SECTIONS .text : *(.text) LONG(1) .d

25、ata : *(.data) 正確:SECTIONS .text : *(.text) LONG(1) .data : *(.data) 在當前輸出section內(nèi)可能存在未描述的存儲區(qū)域(比如由于對齊造成的空隙), 可以用FILL(EXPRESSION)命令決定這些存儲區(qū)域的內(nèi)容,EXPRESSION的前兩字 節(jié)有效,這兩字節(jié)在必要時可以重復被使用以填充這類存儲區(qū)域.如 FILE(0 x9090).在輸出section描述中可以有二FILEEXP屬性,它的作用如同F(xiàn)ILE() 命令,但是FILE命令只作用于該FILE指令之后的section區(qū)域,而二FILEEXP 屬性作用于整個輸出sect

26、ion區(qū)域,且FILE命令的優(yōu)先級更高! !輸出section內(nèi)命令的關(guān)鍵字:CREATE_OBJECT_SYMBOLS :為每個輸入文件建立一個符號,符號名為輸入文件的 名字.每個符號所在的section是出現(xiàn)該關(guān)鍵字的section.CONSTRUCTORS :與c+內(nèi)的(全局對象的)構(gòu)造函數(shù)和(全局對像的)析構(gòu)函數(shù)相 關(guān),下面將它們簡稱為全局構(gòu)造和全局析構(gòu).對于a.out目標文件格式,連接器用一些不尋常的方法實現(xiàn)c+的全局構(gòu)造和全 局析構(gòu).當連接器生成的目標文件格式不支持任意section名字時,比如說 ECOFF、XCOFF格式,連接器將通過名字來識別全局構(gòu)造和全局析構(gòu),對于這些 文件

27、格式,連接器把與全局構(gòu)造和全局析構(gòu)的相關(guān)信息放入出現(xiàn)CONSTRUCTORS 關(guān)鍵字的輸出section內(nèi).符號_CTORS_LIST_表示全局構(gòu)造信息的的開始處,_CTORS_END_表示全局構(gòu) 造信息的結(jié)束處.符號_DTORS_LIST_表示全局構(gòu)造信息的的開始處,_DTORS_END_表示全局構(gòu) 造信息的結(jié)束處.這兩塊信息的開始處是一字長的信息,表示該塊信息有多少項數(shù)據(jù),然后以值為 零的一字長數(shù)據(jù)結(jié)束.一般來說,GNU C+在函數(shù)_main內(nèi)安排全局構(gòu)造代碼的運行,而_main函數(shù)被 初始化代碼(在main函數(shù)調(diào)用之前執(zhí)行)調(diào)用.是不是對于某些目標文件格式才 這樣?對于支持任意secti

28、on名的目標文件格式,比如COFF、ELF格式,GNU C+將全 局構(gòu)造和全局析構(gòu)信息分別放入.ctors section和.dtors section內(nèi),然后在連接腳本內(nèi)加入如下,_CTOR_LIST_ =.;LONG(_CTOR_END_ - _CTOR_LIST_) / 4 - 2)*(.ctors)LONG(0)_CTOR_END_ =.;_DTOR_LIST_ =.;LONG(_DTOR_END_ - _DTOR_LIST_) / 4 - 2)*(.dtors)LONG(0)_DTOR_END_ =.;如果使用GNU C+提供的初始化優(yōu)先級支持(它能控制每個全局構(gòu)造函數(shù)調(diào)用的 先后順

29、序),那么請在連接腳本內(nèi)把CONSTRUCTORS替換成SORT (CONSTRUCTS), 把*(.ctors)換成*(SORT(.ctors),把*(.dtors)換成*(SORT(.dtors). 一般來 說,默認的連接腳本已作好的這些工作.輸出section的丟棄:例子,.foo *(.foo) ,如果沒有任何一個輸入文件包含.foo section,那么 連接器將不會創(chuàng)建.foo輸出section .但是如果在這些輸出section描述內(nèi)包含 了非輸入section描述命令(如符號賦值語句),那么連接器將總是創(chuàng)建該輸出 section.有一個特殊的輸出section,名為/DISCA

30、RD/,被該section引用的任何輸入 section將不會出現(xiàn)在輸出文件內(nèi),這就是DISCARD的意思吧.如果/DISCARD/ section被它自己引用呢?想想看.輸出section屬性:終于講到這里了,呵呵.我們再回顧以下輸出section描述的文法:SECTION ADDRESS (TYPE) : AT(LMA)(OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND. REGION ATLMA_REGION :PHDR :PHDR . =FILLEXP前面我們?yōu)g覽了 SECTION、ADDRESS OUTPUT-SECTION-COMMAND 相

31、關(guān)信息,下面 我們將瀏覽其他屬性.TYPE :每個輸出section都有一個類型,如果沒有指定TYPE類型,那么連接器 根據(jù)輸出section引用的輸入section的類型設(shè)置該輸出section的類型.它可 以為以下五種值,NOLOAD :該section在程序運行時,不被載入內(nèi)存.DSECT,COPY,INFO,OVERLAY :這些類型很少被使用,為了向后兼容才被保留下來. 這種類型的section必須被標記為“不可加載的”,以便在程序運行不為它們分 配內(nèi)存.輸出section的LMA :默認情況下,LMA等于VMA,但可以通過關(guān)鍵字AT()指定 LMA.用關(guān)鍵字AT()指定,括號內(nèi)包含

32、表達式,表達式的值用于設(shè)置LMA.如果不用AT() 關(guān)鍵字,那么可用ATLMA_REGION表達式設(shè)置指定該section加載地址的范圍. 這個屬性主要用于構(gòu)件ROM境象.例子,SECTIONS(.text 0 x1000 : *(.text) _etext = . ; .mdata 0 x2000 :AT ( ADDR (.text) + SIZEOF (.text) ( _data = . ; *(.data); _edata = . ; .bss 0 x3000 :( _bstart = . ; *(.bss) *(COMMON) ; _bend = . ;程序如下,extern cha

33、r _etext, _data, _edata, _bstart, _bend;char *src = &_etext;char *dst = &_data;while (dst &_edata) (*dst+ = *src+;for (dst = &_bstart; dstrom 輸出section所在的程序段:可以將輸出section放入預先定義的程序段(program segment)內(nèi).如果某個輸出section設(shè)置了它所在的一個或多個程序 段,那么接下來定義的輸出section的默認程序段與該輸出section的相同.除 非再次顯示地指定.例子,PHDRS ( text PT_LOAD ; SECTIONS .text : *(.text) :text 可以通過:NONE指定連接器不把該section放入任何程序段內(nèi).詳情請查看PHDRS 命令輸出section的填充模版:這個在前面提到過,任何輸出section描述內(nèi)的未指 定的內(nèi)存區(qū)域,連接器用該模版填充該區(qū)域.用法:=FILEEXP,前兩字節(jié)有效, 當區(qū)域大于兩字節(jié)時,重復使用這兩字節(jié)以將

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論