鏈接腳本語(yǔ)言的編寫(xiě)_第1頁(yè)
鏈接腳本語(yǔ)言的編寫(xiě)_第2頁(yè)
鏈接腳本語(yǔ)言的編寫(xiě)_第3頁(yè)
鏈接腳本語(yǔ)言的編寫(xiě)_第4頁(yè)
鏈接腳本語(yǔ)言的編寫(xiě)_第5頁(yè)
已閱讀5頁(yè),還剩32頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

本文格式為Word版,下載可任意編輯——鏈接腳本語(yǔ)言的編寫(xiě)0.Contents1.概論2.基本概念3.腳本格式4.簡(jiǎn)單例子5.簡(jiǎn)單腳本命令6.對(duì)符號(hào)的賦值7.SECTIONS命令8.MEMORY命令9.PHDRS命令10.VERSION命令11.腳本內(nèi)的表達(dá)式12.暗含的連接腳本1.概論

編譯的過(guò)程得到的obj文件,是完全和地址無(wú)關(guān)的,例如,每個(gè)源文件對(duì)應(yīng)的obj文件,地址都是從0開(kāi)始的,它真正連接的時(shí)候才由連接器

linker分派真正運(yùn)行時(shí)候的地址,所以,你要想處理每個(gè)具體的代碼段運(yùn)行的時(shí)候應(yīng)當(dāng)在什么地方,就要注意學(xué)習(xí)link了。

每一個(gè)鏈接過(guò)程都由鏈接腳本(linkerscript,一般以lds作為文件的后綴名)控制.鏈接腳本主要用于規(guī)定如何把輸入文件內(nèi)的section放入輸出文件內(nèi),并控制輸出文件內(nèi)各部分在程序地址空間內(nèi)的布局.但你也可以用連接命令做一些其他事情.

連接器有個(gè)默認(rèn)的內(nèi)置連接腳本,可用ld--verbose查看.連接選項(xiàng)-r和-N可以影響默認(rèn)的連接腳本(如何影響?).

-T選項(xiàng)用以指定自己的鏈接腳本,它將代替默認(rèn)的連接腳本。你也可以使用以增加自定義的鏈接命令.

以下沒(méi)有特別說(shuō)明,連接器指的是靜態(tài)連接器.2.基本概念

鏈接器把一個(gè)或多個(gè)輸入文件合成一個(gè)輸出文件.輸入文件:目標(biāo)文件或鏈接腳本文件.輸出文件:目標(biāo)文件或可執(zhí)行文件.

目標(biāo)文件(包括可執(zhí)行文件)具有固定的格式,在UNIX或GNU/Linux平臺(tái)下,一般為ELF格式.若想了解更多,可參考UNIX/Linux平臺(tái)可執(zhí)行文件格式分析

有時(shí)把輸入文件內(nèi)的section稱(chēng)為輸入section(inputsection),把輸出文件內(nèi)的section稱(chēng)為輸出section(outputsectin).

目標(biāo)文件的每個(gè)section至少包含兩個(gè)信息:名字和大小.大部分section還包含與它相關(guān)聯(lián)的一塊數(shù)據(jù),稱(chēng)為sectioncontents(section內(nèi)容).一個(gè)section可被標(biāo)記為“l(fā)oadable(可加載的)〞或“allocatable(可分派的)〞.

loadablesection:在輸出文件運(yùn)行時(shí),相應(yīng)的section內(nèi)容將被載入進(jìn)程地址空間中.

allocatablesection:內(nèi)容為空的section可被標(biāo)記為“可分派的〞.在輸出文件運(yùn)行時(shí),在進(jìn)程地址空間中空出大小同section指定大小的部分.某些狀況下,這塊內(nèi)存必需被置零.

假使一個(gè)section不是“可加載的〞或“可分派的〞,那么該section尋常包含了調(diào)試信息.可用

objdump-h命令查看相關(guān)信息.

每個(gè)“可加載的〞或“可分派的〞輸出section尋常包含兩個(gè)地址:VMA(virtualmemoryaddress虛擬內(nèi)存地址或程序地址空間地址)和LMA(loadmemoryaddress加載內(nèi)存地址或進(jìn)程地址空間地址).尋常VMA和LMA是一致的.

在目標(biāo)文件中,loadable或allocatable的輸出section有兩種地址:VMA(virtualMemoryAddress)和LMA(LoadMemoryAddress).VMA是執(zhí)行輸出文件時(shí)section所在的地址,而LMA是加載輸出文件時(shí)section所在的地址.一般而言,某section的VMA==LMA.但在嵌入式系統(tǒng)中,經(jīng)常存在加載地址和執(zhí)行地址不同的狀況:譬如將輸出文件加載到開(kāi)發(fā)板的flash中(由LMA指定),而在運(yùn)行時(shí)將位于flash中的輸出文件復(fù)制到SDRAM中(由VMA指定).

可這樣來(lái)理解VMA和LMA,假設(shè):

(1).datasection對(duì)應(yīng)的VMA地址是0x08050000,該section內(nèi)包含了3個(gè)32位全局變量,i、j和k,分別為1,2,3.

(2).textsection內(nèi)包含由\程序片段產(chǎn)生的代碼.

連接時(shí)指定.datasection的VMA為0x08050000,產(chǎn)生的printf指令是將地址為0x08050004處的4字節(jié)內(nèi)容作為一個(gè)整數(shù)打印出來(lái)。

假使.datasection的LMA為0x08050000,顯然結(jié)果是j=2假使.datasection的LMA為0x08050004,顯然結(jié)果是j=1還可這樣理解LMA:

.textsection內(nèi)容的開(kāi)始處包含如下兩條指令(inteli386指令是10字節(jié),每行對(duì)應(yīng)5字節(jié)):jmp0x08048285movl$0x1,êx

假使.textsection的LMA為0x08048280,那么在進(jìn)程地址空間內(nèi)0x08048280處為“jmp0x08048285〞指令,0x08048285處為movl$0x1,êx指令.假設(shè)某指令跳轉(zhuǎn)到地址0x08048280,顯然它的執(zhí)行將導(dǎo)致êx寄放器被賦值為1.

假使.textsection的LMA為0x08048285,那么在進(jìn)程地址空間內(nèi)0x08048285處為“jmp0x08048285〞指令,0x0804828a處為movl$0x1,êx指令.假設(shè)某指令跳轉(zhuǎn)到地址0x08048285,顯然它的執(zhí)行又跳轉(zhuǎn)到進(jìn)程地址空間內(nèi)0x08048285處,造成死循環(huán).

符號(hào)(symbol):每個(gè)目標(biāo)文件都有符號(hào)表(SYMBOLTABLE),包含已定義的符號(hào)(對(duì)應(yīng)全局變量和static變量和定義的函數(shù)的名字)和未定義符號(hào)(未定義的函數(shù)的名字和引用但沒(méi)定義的符號(hào))信息.

符號(hào)值:每個(gè)符號(hào)對(duì)應(yīng)一個(gè)地址,即符號(hào)值(這與c程序內(nèi)變量的值不一樣,某種狀況下可以把它看成變量的地址).可用nm命令查看它們.(nm的使用方法可參考本blog的GNUbinutils筆記)

3.腳本格式

鏈接腳本由一系列命令組成,每個(gè)命令由一個(gè)關(guān)鍵字(一般在其后緊跟相關(guān)參數(shù))或一條對(duì)符號(hào)的賦值語(yǔ)句組成.命令由分號(hào)?;?分隔開(kāi).

文件名或格式名內(nèi)假使包含分號(hào)';'或其他分隔符,則要用引號(hào)?\將名字全稱(chēng)引用起來(lái).無(wú)法處理含引號(hào)的文件名./**/之間的是解釋。4.簡(jiǎn)單例子

在介紹鏈接描述文件的命令之前,先看看下述的簡(jiǎn)單例子:

以下腳本將輸出文件的textsection定位在0x10000,datasection定位在0x8000000:SECTIONS{

.=0x10000;.text:{*(.text)}.=0x8000000;.data:{*(.data)}.bss:{*(.bss)}}

解釋一下上述的例子:

.=0x10000:把定位器符號(hào)置為0x10000(若不指定,則該符號(hào)的初始值為0).

.text:{*(.text)}:將所有(*符號(hào)代表任意輸入文件)輸入文件的.textsection合并成一個(gè).textsection,該section的地址由定位器符號(hào)的值指定,即0x10000..=0x8000000:把定位器符號(hào)置為0x8000000

.data:{*(.data)}:將所有輸入文件的.textsection合并成一個(gè).datasection,該section的地址被置為0x8000000.

.bss:{*(.bss)}:將所有輸入文件的.bsssection合并成一個(gè).bsssection,該section的地址被置為0x8000000+.datasection的大小.

連接器每讀完一個(gè)section描述后,將定位器符號(hào)的值*增加*該section的大小.注意:此處沒(méi)有考慮對(duì)齊約束.5.簡(jiǎn)單腳本命令

-1-

ENTRY(SYMBOL):將符號(hào)SYMBOL的值設(shè)置成入口地址。

入口地址(entrypoint):進(jìn)程執(zhí)行的第一條用戶(hù)空間的指令在進(jìn)程地址空間的地址)ld有多種方法設(shè)置進(jìn)程入口地址,按一下順序:(編號(hào)越前,優(yōu)先級(jí)越高)1,ld命令行的-e選項(xiàng)

2,連接腳本的ENTRY(SYMBOL)命令3,假使定義了start符號(hào),使用start符號(hào)值

4,假使存在.textsection,使用.textsection的第一字節(jié)的位置值5,使用值0-2-

INCLUDEfilename:包含其他名為filename的鏈接腳本

相當(dāng)于c程序內(nèi)的的#include指令,用以包含另一個(gè)鏈接腳本.

腳本探尋路徑由-L選項(xiàng)指定.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):將括號(hào)內(nèi)的文件做為鏈接過(guò)程的輸入文件

ld首先在當(dāng)前目錄下尋覓該文件,假使沒(méi)找到,則在由-L指定的探尋路徑下探尋.file可以為-lfile形式,就象命令行的-l選項(xiàng)一樣.假使該命令出現(xiàn)在暗含的腳本內(nèi),則該命令內(nèi)的file在鏈接過(guò)程中的順序由該暗含的腳本在命令行內(nèi)的順序決定.-4-

GROUP(files):指定需要重復(fù)探尋符號(hào)定義的多個(gè)輸入文件

file必需是庫(kù)文件,且file文件作為一組被ld重復(fù)掃描,直到不在有新的未定義的引用出現(xiàn)。-5-

OUTPUT(FILENAME):定義輸出文件的名字

同ld的-o選項(xiàng),不過(guò)-o選項(xiàng)的優(yōu)先級(jí)更高.所以它可以用來(lái)定義默認(rèn)的輸出文件名.如a.out-6-

SEARCH_DIR(PATH):定義探尋路徑,

同ld的-L選項(xiàng),不過(guò)由-L指定的路徑要比它定義的優(yōu)先被探尋。-7-

STARTUP(filename):指定filename為第一個(gè)輸入文件

在鏈接過(guò)程中,每個(gè)輸入文件是有順序的.此命令設(shè)置文件filename為第一個(gè)輸入文件。-8-

OUTPUT_FORMAT(BFDNAME):設(shè)置輸出文件使用的BFD格式

同ld選項(xiàng)-oformatBFDNAME,不過(guò)ld選項(xiàng)優(yōu)先級(jí)更高.-9-

OUTPUT_FORMAT(DEFAULT,BIG,LITTLE):定義三種輸出文件的格式(大小端)

若有命令行選項(xiàng)-EB,則使用第2個(gè)BFD格式;若有命令行選項(xiàng)-EL,則使用第3個(gè)BFD格式.否則默認(rèn)選第一個(gè)BFD格式.

TARGET(BFDNAME):設(shè)置輸入文件的BFD格式

同ld選項(xiàng)-bBFDNAME.若使用了TARGET命令,但未使用OUTPUT_FORMAT命令,則最用一個(gè)TARGET命令設(shè)置的BFD格式將被作為輸出文件的BFD格式.另外還有一些:

ASSERT(EXP,MESSAGE):假使EXP不為真,終止連接過(guò)程

EXTERN(SYMBOLSYMBOL...):在輸出文件中增加未定義的符號(hào),宛如連接器選項(xiàng)-uFORCE_COMMON_ALLOCATION:為commonsymbol(通用符號(hào))分派空間,即使用了-r連接選項(xiàng)也為其分派

NOCROSSREFS(SECTIONSECTION...):檢查列出的輸出section,假使發(fā)現(xiàn)他們之間有相互引用,則報(bào)錯(cuò)。對(duì)于某些系統(tǒng),特別是內(nèi)存較緊張的嵌入式系統(tǒng),某些section是不能同時(shí)存在內(nèi)存中的,所以他們之間不能相互引用。

OUTPUT_ARCH(BFDARCH):設(shè)置輸出文件的machinearchitecture(體系結(jié)構(gòu)),BFDARCH為被BFD庫(kù)使用的名字之一。可以用命令objdump-f查看。

可通過(guò)man-S1ld查看ld的聯(lián)機(jī)幫助,里面也包括了對(duì)這些命令的介紹.6.對(duì)符號(hào)的賦值

在目標(biāo)文件內(nèi)定義的符號(hào)可以在鏈接腳本內(nèi)被賦值.(注意和C語(yǔ)言中賦值的不同!)此時(shí)該符號(hào)被定義為全局的.每個(gè)符號(hào)都對(duì)應(yīng)了一個(gè)地址,此處的賦值是更改這個(gè)符號(hào)對(duì)應(yīng)的地址.e.g.通過(guò)下面的程序查看變量a的地址:/*a.c*/

#includeinta=100;intmain(void){

printf(\return0;}

/*a.lds*/a=3;

$gcc-Wall-oa-without-ldsa.cSYMBOL+=EXPRESSION;SYMBOL-=EXPRESSION;SYMBOL*=EXPRESSION;SYMBOL/=EXPRESSION;SYMBOL>=EXPRESSION;SYMBOLSYMBOL|=EXPRESSION;

除了第一類(lèi)表達(dá)式外,使用其他表達(dá)式需要SYMBOL被定義于某目標(biāo)文件。.是一個(gè)特別的符號(hào),它是定位器,一個(gè)位置指針,指向程序地址空間內(nèi)的某位置(或某section內(nèi)的偏移,假使它在SECTIONS命令內(nèi)的某section描述內(nèi)),該符號(hào)只能在SECTIONS命令內(nèi)使用。

注意:賦值語(yǔ)句包含4個(gè)語(yǔ)法元素:符號(hào)名、操作符、表達(dá)式、分號(hào);一個(gè)也不能少。被賦值后,符號(hào)所屬的section被設(shè)值為表達(dá)式EXPRESSION所屬的SECTION(參看11.腳本內(nèi)的表達(dá)式)

賦值語(yǔ)句可以出現(xiàn)在連接腳本的三處地方:SECTIONS命令內(nèi),SECTIONS命令內(nèi)的section描述內(nèi)和全局位置;如下,

floating_point=0;/*全局位置*/SECTIONS

{.text:{

*(.text)

_etext=.;/*section描述內(nèi)*/}

_bdata=(.+3)/*SECTIONS命令內(nèi)*/.data:{*(.data)}}

PROVIDE關(guān)鍵字

該關(guān)鍵字用于定義這類(lèi)符號(hào):在目標(biāo)文件內(nèi)被引用,但沒(méi)有在任何目標(biāo)文件內(nèi)被定義的符號(hào)。例子:SECTIONS{.text:{

*(.text)_etext=.;

PROVIDE(etext=.);}}

當(dāng)目標(biāo)文件內(nèi)引用了etext符號(hào),確沒(méi)有定義它時(shí),etext符號(hào)對(duì)應(yīng)的地址被定義為.textsection之后的第一個(gè)字節(jié)的地址。7.SECTIONS命令

SECTIONS命令告訴ld如何把輸入文件的sections映射到輸出文件的各個(gè)section:如何將輸入section合為輸出section;如何把輸出section放入程序地址空間(VMA)和進(jìn)程地址空間(LMA).該命令格式如下:SECTIONS{

SECTIONS-COMMANDSECTIONS-COMMAND...}

SECTION-COMMAND有四種:(1)ENTRY命令(2)符號(hào)賦值語(yǔ)句

(3)一個(gè)輸出section的描述(outputsectiondescription)(4)一個(gè)section疊加描述(overlaydescription)

假使整個(gè)連接腳本內(nèi)沒(méi)有SECTIONS命令,那么ld將所有同名輸入section合成為一個(gè)輸出section內(nèi),各輸入section的順序?yàn)樗鼈儽贿B接器發(fā)現(xiàn)的順序.

假使某輸入section沒(méi)有在SECTIONS命令中提到,那么該section將被直接拷貝成輸出section。

輸出section描述

輸出section描述具有如下格式:

SECTION[ADDRESS][(TYPE)]:[AT(LMA)]{

OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND...

}[>REGION][AT>LMA_REGION][:PHDR:PHDR...][=FILLEXP][]內(nèi)的內(nèi)容為可選選項(xiàng),一般不需要.SECTION:section名字

SECTION左右的空白、圓括號(hào)、冒號(hào)是必需的,換行符和其他空格是可選的。每個(gè)OUTPUT-SECTION-COMMAND為以下四種之一,符號(hào)賦值語(yǔ)句

一個(gè)輸入section描述直接包含的數(shù)據(jù)值

一個(gè)特別的輸出section關(guān)鍵字輸出section名字(SECTION):

輸出section名字必需符合輸出文件格式要求,譬如:a.out格式的文件只允許存在.text、.data和.bsssection名。而有的格式只允許存在數(shù)字名字,那么此時(shí)應(yīng)當(dāng)用引號(hào)將所有名字內(nèi)的數(shù)字組合在一起;另外,還有一些格式允許任何序列的字符存在于section名字內(nèi),此時(shí)假使名字內(nèi)包含特別字符(譬如空格、逗號(hào)等),那么需要用引號(hào)將其組合在一起。輸出section地址(ADDRESS):

ADDRESS是一個(gè)表達(dá)式,它的值用于設(shè)置VMA。假使沒(méi)有該選項(xiàng)且有REGION選項(xiàng),那么連接器將根據(jù)REGION設(shè)置VMA;假使也沒(méi)有REGION選項(xiàng),那么連接器將根據(jù)定位符號(hào)?.?的值設(shè)置該section的VMA,將定位符號(hào)的值調(diào)整到滿(mǎn)足輸出section對(duì)齊要求后的值,輸出section的對(duì)齊要求為:該輸出section描述內(nèi)用到的所有輸入section的對(duì)齊要求中最嚴(yán)格的。例子:

.text.:{*(.text)}和

.text:{*(.text)}

這兩個(gè)描述是截然不同的,第一個(gè)將.textsection的VMA設(shè)置為定位符號(hào)的值,而其次個(gè)則是設(shè)置成定位符號(hào)的修調(diào)值,滿(mǎn)足對(duì)齊要求后的。ADDRESS可以是一個(gè)任意表達(dá)式,譬如ALIGN(0x10)這將把該section的VMA設(shè)置成定位符號(hào)的修調(diào)值,滿(mǎn)足16字節(jié)對(duì)齊后的。

注意:設(shè)置ADDRESS值,將更改定位符號(hào)的值。輸入section描述:

最常見(jiàn)的輸出section描述命令是輸入section描述。輸入section描述是最基本的連接腳本描述。輸入section描述基礎(chǔ):

基本語(yǔ)法:FILENAME([EXCLUDE_FILE(FILENAME1FILENAME2...)SECTION1SECTION2...)

FILENAME文件名,可以是一個(gè)特定的文件的名字,也可以是一個(gè)字符串模式。SECTION名字,可以是一個(gè)特定的section名字,也可以是一個(gè)字符串模式例子是最能說(shuō)明問(wèn)題的,

*(.text):表示所有輸入文件的.textsection

(*(EXCLUDE_FILE(*crtend.o*otherfile.o).ctors)):表示除crtend.o、otherfile.o文件外的所有輸入文件的.ctorssection。

data.o(.data):表示data.o文件的.datasectiondata.o:表示data.o文件的所有section*(.text.data):表示所有文件的.textsection和.datasection,順序是:第一個(gè)文件的.textsection,第一個(gè)文件的.datasection,其次個(gè)文件的.textsection,其次個(gè)文件的.datasection,...

*(.text)*(.data):表示所有文件的.textsection和.datasection,順序是:第一個(gè)文件的.textsection,其次個(gè)文件的.textsection,...,最終一個(gè)文件的.textsection,第一個(gè)文件的.datasection,其次個(gè)文件的.datasection,...,最終一個(gè)文件的.datasection下面看連接器是如何找到對(duì)應(yīng)的文件的。

當(dāng)FILENAME是一個(gè)特定的文件名時(shí),連接器會(huì)查看它是否在連接命令行內(nèi)出現(xiàn)或在INPUT命令中出現(xiàn)。

當(dāng)FILENAME是一個(gè)字符串模式時(shí),連接器僅僅只查看它是否在連接命令行內(nèi)出現(xiàn)。注意:假使連接器發(fā)現(xiàn)某文件在INPUT命令內(nèi)出現(xiàn),那么它會(huì)在-L指定的路徑內(nèi)搜尋該文件。

字符串模式內(nèi)可存在以下通配符:*:表示任意多個(gè)字符?:表示任意一個(gè)字符

[CHARS]:表示任意一個(gè)CHARS內(nèi)的字符,可用-號(hào)表示范圍,如:a-z:表示引用下一個(gè)緊跟的字符

在文件名內(nèi),通配符不匹配文件夾分隔符/,但當(dāng)字符串模式僅包含通配符*時(shí)除外。任何一個(gè)文件的任意section只能在SECTIONS命令內(nèi)出現(xiàn)一次??慈缦吕樱琒ECTIONS{.data:{*(.data)}

.data1:{data.o(.data)}}

data.o文件的.datasection在第一個(gè)OUTPUT-SECTION-COMMAND命令內(nèi)被使用了,那么在其次個(gè)OUTPUT-SECTION-COMMAND命令內(nèi)將不會(huì)再被使用,也就是說(shuō)即使連接器不報(bào)錯(cuò),輸出文件的.data1section的內(nèi)容也是空的。

再次強(qiáng)調(diào):連接器依次掃描每個(gè)OUTPUT-SECTION-COMMAND命令內(nèi)的文件名,任何一個(gè)文件的任何一個(gè)section都只能使用一次。

讀者可以用-M連接命令選項(xiàng)來(lái)產(chǎn)生一個(gè)map文件,它包含了所有輸入section到輸出section的組合信息。再看個(gè)例子,SECTIONS{.text:{*(.text)}

.DATA:{[A-Z]*(.data)}.data:{*(.data)}.bss:{*(.bss)}}

這個(gè)例子中說(shuō)明,所有文件的輸入.textsection組成輸出.textsection;所有以大寫(xiě)字母開(kāi)頭的文件的.datasection組成輸出.DATAsection,其他文件的.datasection組成輸出.datasection;所有文件的輸入.bsssection組成輸出.bsssection。

可以用SORT()關(guān)鍵字對(duì)滿(mǎn)足字符串模式的所有名字進(jìn)行遞增排序,如SORT(.text*)。通用符號(hào)(commonsymbol)的輸入section:

在大量目標(biāo)文件格式中,通用符號(hào)并沒(méi)有占用一個(gè)section。連接器認(rèn)為:輸入文件的所有通用符號(hào)在名為COMMON的section內(nèi)。例子,

.bss{*(.bss)*(COMMON)}

這個(gè)例子中將所有輸入文件的所有通用符號(hào)放入輸出.bsssection內(nèi)??梢钥吹紺OMMOMsection的使用方法跟其他section的使用方法是一樣的。

有些目標(biāo)文件格式把通用符號(hào)分成幾類(lèi)。例如,在MIPSelf目標(biāo)文件格式中,把通用符號(hào)分成standardcommonsymbols(標(biāo)準(zhǔn)通用符號(hào))和smallcommonsymbols(微通用符號(hào),不知道這么譯對(duì)不對(duì)?),此時(shí)連接器認(rèn)為所有standardcommonsymbols在COMMONsection內(nèi),而smallcommonsymbols在.scommonsection內(nèi)。

在一些以前的連接腳本內(nèi)可以看見(jiàn)[COMMON],相當(dāng)于*(COMMON),不建議繼續(xù)使用這種陳舊的方式。

輸入section和垃圾回收:

在連接命令行內(nèi)使用了選項(xiàng)--gc-sections后,連接器可能將某些它認(rèn)為沒(méi)用的section過(guò)濾掉,此時(shí)就有必要強(qiáng)制連接器保存一些特定的section,可用KEEP()關(guān)鍵字達(dá)此目的。如KEEP(*(.text))或KEEP(SORT(*)(.text))最終看個(gè)簡(jiǎn)單的輸入section相關(guān)例子:SECTIONS{outputa0x10000:{all.o

foo.o(.input1)}

outputb:{

foo.o(.input2)foo1.o(.input1)}

outputc:{

*(.input1)*(.input2)}}

本例中,將all.o文件的所有section和foo.o文件的所有(一個(gè)文件內(nèi)可以有多個(gè)同名section).input1section依次放入輸出outputasection內(nèi),該section的VMA是0x10000;將foo.o文件的所有.input2section和foo1.o文件的所有.input1section依次放入輸出outputbsection內(nèi),該section的VMA是當(dāng)前定位器符號(hào)的修調(diào)值(對(duì)齊后);將其他文件(非all.o、foo.o、foo1.o)文件的.input1section和.input2section放入輸出outputcsection內(nèi)。在輸出section存放數(shù)據(jù)命令:

能夠顯示地在輸出section內(nèi)填入你想要填入的信息(這樣是不是可以自己通過(guò)連接腳本寫(xiě)程序?當(dāng)然是簡(jiǎn)單的程序)。

BYTE(EXPRESSION)1字節(jié)SHORT(EXPRESSION)2字節(jié)LOGN(EXPRESSION)4字節(jié)QUAD(EXPRESSION)8字節(jié)

SQUAD(EXPRESSION)64位處理器的代碼時(shí),8字節(jié)

輸出文件的字節(jié)順序bigendianness或littleendianness,可以由輸出目標(biāo)文件的格式?jīng)Q定;假使輸出目標(biāo)文件的格式不能決定字節(jié)順序,那么字節(jié)順序與第一個(gè)輸入文件的字節(jié)順序一致。

如:BYTE(1)、LANG(addr)。

注意,這些命令只能放在輸出section描述內(nèi),其他地方不行。錯(cuò)誤:SECTIONS{.text:{*(.text)}LONG(1).data:{*(.data)}}正確:SECTIONS{.text:{*(.text)LONG(1)}.data:{*(.data)}}

在當(dāng)前輸出section內(nèi)可能存在未描述的存儲(chǔ)區(qū)域(譬如由于對(duì)齊造成的空隙),可以用FILL(EXPRESSION)命令決定這些存儲(chǔ)區(qū)域的內(nèi)容,EXPRESSION的前兩字節(jié)有效,這兩字節(jié)在必要時(shí)可以重復(fù)被使用以填充這類(lèi)存儲(chǔ)區(qū)域。如FILE(0x9090)。在輸出section描述中可以有=FILEEXP屬性,它的作用宛如FILE()命令,但是FILE命令只作用于該FILE指令之后的section區(qū)域,而=FILEEXP屬性作用于整個(gè)輸出section區(qū)域,且FILE命令的優(yōu)先級(jí)更高?。?!

輸出section內(nèi)命令的關(guān)鍵字:CREATE_OBJECT_SYMBOLS:為每個(gè)輸入文件建立一個(gè)符號(hào),符號(hào)名為輸入文件的名字。每個(gè)符號(hào)所在的section是出現(xiàn)該關(guān)鍵字的section。

CONSTRUCTORS:與c++內(nèi)的(全局對(duì)象的)構(gòu)造函數(shù)和(全局對(duì)像的)析構(gòu)函數(shù)相關(guān),下面將它們簡(jiǎn)稱(chēng)為全局構(gòu)造和全局析構(gòu)。

對(duì)于a.out目標(biāo)文件格式,連接器用一些不尋常的方法實(shí)現(xiàn)c++的全局構(gòu)造和全局析構(gòu)。當(dāng)連接器生成的目標(biāo)文件格式不支持任意section名字時(shí),譬如說(shuō)ECOFF、XCOFF格式,連接器將通過(guò)名字來(lái)識(shí)別全局構(gòu)造和全局析構(gòu),對(duì)于這些文件格式,連接器把與全局構(gòu)造和全局析構(gòu)的相關(guān)信息放入出現(xiàn)CONSTRUCTORS關(guān)鍵字的輸出section內(nèi)。

符號(hào)__CTORS_LIST__表示全局構(gòu)造信息的的開(kāi)始處,__CTORS_END__表示全局構(gòu)造信息的終止處。

符號(hào)__DTORS_LIST__表示全局構(gòu)造信息的的開(kāi)始處,__DTORS_END__表示全局構(gòu)造信息的終止處。

這兩塊信息的開(kāi)始處是一字長(zhǎng)的信息,表示該塊信息有多少項(xiàng)數(shù)據(jù),然后以值為零的一字長(zhǎng)數(shù)據(jù)終止。

一般來(lái)說(shuō),GNUC++在函數(shù)__main內(nèi)安排全局構(gòu)造代碼的運(yùn)行,而__main函數(shù)被初始化代碼(在main函數(shù)調(diào)用之前執(zhí)行)調(diào)用。是不是對(duì)于某些目標(biāo)文件格式才這樣???

對(duì)于支持任意section名的目標(biāo)文件格式,譬如COFF、ELF格式,GNUC++將全局構(gòu)造和全局析構(gòu)信息分別放入.ctorssection和.dtorssection內(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__=.;

假使使用GNUC++提供的初始化優(yōu)先級(jí)支持(它能控制每個(gè)全局構(gòu)造函數(shù)調(diào)用的先后順序),那么請(qǐng)?jiān)谶B接腳本內(nèi)把CONSTRUCTORS替換成SORT(CONSTRUCTS),把*(.ctors)換成*(SORT(.ctors)),把*(.dtors)換成*(SORT(.dtors))。一般來(lái)說(shuō),默認(rèn)的連接腳本已作好的這些工作。

輸出section的丟棄:

例子,.foo{*(.foo)},假使沒(méi)有任何一個(gè)輸入文件包含.foosection,那么連接器將不會(huì)創(chuàng)立.foo輸出section。但是假使在這些輸出section描述內(nèi)包含了非輸入section描述命令(如符號(hào)賦值語(yǔ)句),那么連接器將總是創(chuàng)立該輸出section。

有一個(gè)特別的輸出section,名為/DISCARD/,被該section引用的任何輸入section將不會(huì)出現(xiàn)在輸出文件內(nèi),這就是DISCARD的意思吧。假使/DISCARD/section被它自己引用呢?想想看。

輸出section屬性:

終究講到這里了,呵呵。

我們?cè)倩叵胍韵螺敵鰏ection描述的文法:SECTION[ADDRESS][(TYPE)]:[AT(LMA)]{

OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND...

}[>REGION][AT>LMA_REGION][:PHDR:PHDR...][=FILLEXP]

前面我們?yōu)g覽了SECTION、ADDRESS、OUTPUT-SECTION-COMMAND相關(guān)信息,下面我們將瀏覽其他屬性。

TYPE:每個(gè)輸出section都有一個(gè)類(lèi)型,假使沒(méi)有指定TYPE類(lèi)型,那么連接器根據(jù)輸出section引用的輸入section的類(lèi)型設(shè)置該輸出section的類(lèi)型。它可以為以下五種值,NOLOAD:該section在程序運(yùn)行時(shí),不被載入內(nèi)存。

DSECT,COPY,INFO,OVERLAY:這些類(lèi)型很少被使用,為了向后兼容才被保存下來(lái)。這種類(lèi)型的section必需被標(biāo)記為“不可加載的〞,以便在程序運(yùn)行不為它們分派內(nèi)存。

輸出section的LMA:默認(rèn)狀況下,LMA等于VMA,但可以通過(guò)關(guān)鍵字AT()指定LMA。用關(guān)鍵字AT()指定,括號(hào)內(nèi)包含表達(dá)式,表達(dá)式的值用于設(shè)置LMA。假使不用AT()關(guān)鍵字,那么可用AT>LMA_REGION表達(dá)式設(shè)置指定該section加載地址的范圍。這個(gè)屬性主要用于構(gòu)件ROM境象。例子,SECTIONS{

.text0x1000:{*(.text)_etext=.;}.mdata0x2000:

AT(ADDR(.text)+SIZEOF(.text)){_data=.;*(.data);_edata=.;}.bss0x3000:

{_bstart=.;*(.bss)*(COMMON);_bend=.;}}

程序如下,

externchar_etext,_data,_edata,_bstart,_bend;char*src=char*dst=

/*ROMhasdataatendoftext;copyit.*/while(dstrom}輸出section所在的程序段:可以將輸出section放入預(yù)先定義的程序段(programsegment)內(nèi)。假使某個(gè)輸出section設(shè)置了它所在的一個(gè)或多個(gè)程序段,那么接下來(lái)定義的輸出section的默認(rèn)程序段與該輸出section的一致。除非再次顯示地指定。例子,PHDRS{textPT_LOAD;}

SECTIONS{.text:{*(.text)}:text}

可以通過(guò):NONE指定連接器不把該section放入任何程序段內(nèi)。詳情請(qǐng)查看PHDRS命令輸出section的填充模版:這個(gè)在前面提到過(guò),任何輸出section描述內(nèi)的未指定的內(nèi)存區(qū)域,連接器用該模版填充該區(qū)域。用法:=FILEEXP,前兩字節(jié)有效,當(dāng)區(qū)域大于兩字節(jié)時(shí),重復(fù)使用這兩字節(jié)以將其填滿(mǎn)。例子,SECTIONS{.text:{*(.text)}=0x9090}覆蓋圖(overlay)描述:

覆蓋圖描述使兩個(gè)或多個(gè)不同的section占用同一塊程序地址空間。覆蓋圖管理代碼負(fù)責(zé)將section的拷入和拷出。考慮這種狀況,當(dāng)某存儲(chǔ)塊的訪問(wèn)速度比其他存儲(chǔ)塊要快時(shí),那么假使將section拷到該存儲(chǔ)塊來(lái)執(zhí)行或訪問(wèn),那么速度將會(huì)有所提高,覆蓋圖描述就很適合這種情形。文法如下,SECTIONS{...

OVERLAY[START]:[NOCROSSREFS][AT(LDADDR)]{

SECNAME1{

OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND...

}[:PHDR...][=FILL]SECNAME2{

OUTPUT-SECTION-COMMANDOUTPUT-SECTION-COMMAND...

}[:PHDR...][=FILL]...

}[>REGION][:PHDR...][=FILL]...}

由以上文法可以看出,同一覆蓋圖內(nèi)的section具有一致的VMA。SECNAME2的LMA為SECTNAME1的LMA加上SECNAME1的大小,同理計(jì)算SECNAME2,3,4...的LMA。SECNAME1的LMA由LDADDR決定,假使它沒(méi)有被指定,那么由START決定,假使它也沒(méi)有被指定,那么由當(dāng)前定位符號(hào)的值決定。

NOCROSSREFS關(guān)鍵字指定各section之間不能交織引用,否則報(bào)錯(cuò)。

對(duì)于OVERLAY描述的每個(gè)section,連接器將定義兩個(gè)符號(hào)__load_start_SECNAME和__load_stop_SECNAME,這兩個(gè)符號(hào)的值分別代表SECNAMEsection的LMA地址的開(kāi)始和終止。

連接器處理完OVERLAY描述語(yǔ)句后,將定位符號(hào)的值加上所有覆蓋圖內(nèi)section大小的最大值。

看個(gè)例子吧,SECTIONS{...

OVERLAY0x1000:AT(0x4000){

.text0{o1/*.o(.text)}.text1{o2/*.o(.text)}}...}

.text0section和.text1section的VMA地址是0x1000,.text0section加載于地址0x4000,.text1section緊跟在其后。

程序代碼,拷貝.text1section代碼,

externchar__load_start_text1,__load_stop_text1;memcpy((char*)0x1000,8.內(nèi)存區(qū)域命令

注意:以下存儲(chǔ)區(qū)域指的是在程序地址空間內(nèi)的。

在默認(rèn)情形下,連接器可以為section分派任意位置的存儲(chǔ)區(qū)域。你也可以用MEMORY命令定義存儲(chǔ)區(qū)域,并通過(guò)輸出section描述的>REGION屬性顯示地將該輸出section限定于某塊存儲(chǔ)區(qū)域,當(dāng)存儲(chǔ)區(qū)域大小不能滿(mǎn)足要求時(shí),連接器會(huì)報(bào)告該錯(cuò)誤。MEMORY命令的文法如下,MEMORY{

NAME1[(ATTR)]:ORIGIN=ORIGIN1,LENGTH=LEN2NAME2[(ATTR)]:ORIGIN=ORIGIN2,LENGTH=LEN2

...}

NAME:存儲(chǔ)區(qū)域的名字,這個(gè)名字可以與符號(hào)名、文件名、section名重復(fù),由于它處于一個(gè)獨(dú)立的名字空間。

ATTR:定義該存儲(chǔ)區(qū)域的屬性,在陳述SECTIONS命令時(shí)提到,當(dāng)某輸入section沒(méi)有在SECTIONS命令內(nèi)引用時(shí),連接器會(huì)把該輸入section直接拷貝成輸出section,然后將該輸出section放入內(nèi)存區(qū)域內(nèi)。假使設(shè)置了內(nèi)存區(qū)域設(shè)置了ATTR屬性,那么該區(qū)域只接受滿(mǎn)足該屬性的section(怎么判斷該section是否滿(mǎn)足?輸出section描述內(nèi)好象沒(méi)有記錄該section的讀寫(xiě)執(zhí)行屬性)。ATTR屬性?xún)?nèi)可以出現(xiàn)以下7個(gè)字符,R只讀sectionW讀/寫(xiě)sectionX可執(zhí)行sectionA?可分派的?sectionI初始化了的sectionL同I

!不滿(mǎn)足該字符之后的任何一個(gè)屬性的section

ORIGIN:關(guān)鍵字,區(qū)域的開(kāi)始地址,可簡(jiǎn)寫(xiě)成org或oLENGTH:關(guān)鍵字,區(qū)域的大小,可簡(jiǎn)寫(xiě)成len或l例子,MEMORY{

rom(rx):ORIGIN=0,LENGTH=256Kram(!rx):org=0x40000000,l=4M}

此例中,把在SECTIONS命令內(nèi)*未*引用的且具有讀屬性或?qū)憣傩缘妮斎雜ection放入rom區(qū)域內(nèi),把其他未引用的輸入section放入ram。假使某輸出section要被放入某內(nèi)存區(qū)域內(nèi),而該輸出section又沒(méi)有指明ADDRESS屬性,那么連接器將該輸出section放在該區(qū)域內(nèi)下一個(gè)能使用位置。9.PHDRS命令

該命令僅在產(chǎn)生ELF目標(biāo)文件時(shí)有效。

ELF目標(biāo)文件格式用programheaders程序頭(程序頭內(nèi)包含一個(gè)或多個(gè)segment程序段描述)來(lái)描述程序如何被載入內(nèi)存??梢杂胦bjdump-p命令查看。

當(dāng)在本地ELF系統(tǒng)運(yùn)行ELF目標(biāo)文件格式的程序時(shí),系統(tǒng)加載器通過(guò)讀取程序頭信息以知道如何將程序加載到內(nèi)存。要了解系統(tǒng)加載器如何解析程序頭,請(qǐng)參考ELFABI文檔。在連接腳本內(nèi)不指定PHDRS命令時(shí),連接器能夠很好的創(chuàng)立程序頭,但是有時(shí)需要更確切的描述程序頭,那么PAHDRS命令就派上用場(chǎng)了。

注意:一旦在連接腳本內(nèi)使用了PHDRS命令,那么連接器**僅會(huì)**創(chuàng)立PHDRS命令指定的信息,所以使用時(shí)須提防。PHDRS命令文法如下,PHDRS{

NAMETYPE[FILEHDR][PHDRS][AT(ADDRESS)][FLAGS(FLAGS)];

}

其中FILEHDR、PHDRS、AT、FLAGS為關(guān)鍵字。

NAME:為程序段名,此名字可以與符號(hào)名、section名、文件名重復(fù),由于它在一個(gè)獨(dú)立的名字空間內(nèi)。此名字只能在SECTIONS命令內(nèi)使用。

一個(gè)程序段可以由多個(gè)?可加載?的section組成。通過(guò)輸出section描述的屬性:PHDRS可以將輸出section參與一個(gè)程序段,:PHDRS中的PHDRS為程序段名。在一個(gè)輸出section描述內(nèi)可以屢屢使用:PHDRS命令,也即可以將一個(gè)section參與多個(gè)程序段。

假使在一個(gè)輸出section描述內(nèi)指定了:PHDRS屬性,那么其后的輸出section描述將默認(rèn)使用該屬性,除非它也定義了:PHDRS屬性。顯然當(dāng)多個(gè)輸出section屬于同一程序段時(shí)可簡(jiǎn)化書(shū)寫(xiě)。

在TYPE屬性后存在FILEHDR關(guān)鍵字,表示該段包含ELF文件頭信息;存在PHDRS關(guān)鍵字,表示該段包含ELF程序頭信息。TYPE可以是以下八種形式,PT_NULL0

表示未被使用的程序段PT_LOAD1

表示該程序段在程序運(yùn)行時(shí)應(yīng)當(dāng)被加載PT_DYNAMIC2

表示該程序段包含動(dòng)態(tài)連接信息PT_INTERP3

表示該程序段內(nèi)包含程序加載器的名字,在linux下常見(jiàn)的程序加載器是ld-linux.so.2PT_NOTE4

表示該程序段內(nèi)包含程序的說(shuō)明信息PT_SHLIB5

一個(gè)保存的程序頭類(lèi)型,沒(méi)有在ELFABI文檔內(nèi)定義PT_PHDR6

表示該程序段包含程序頭信息。EXPRESSION表達(dá)式值

以上每個(gè)類(lèi)型都對(duì)應(yīng)一個(gè)數(shù)字,該表達(dá)式定義一個(gè)用戶(hù)自定的程序頭。

AT(ADDRESS)屬性定義該程序段的加載位置(LMA),該屬性將**覆蓋**該程序段內(nèi)的section的AT()屬性。

默認(rèn)狀況下,連接器會(huì)根據(jù)該程序段包含的section的屬性(什么屬性?好象在輸出section描述內(nèi)沒(méi)有看到)設(shè)置FLAGS標(biāo)志,該標(biāo)志用于設(shè)置程序段描述的p_flags域。下面看一個(gè)典型的PHDRS設(shè)置,PHDRS{

headersPT_PHDRPHDRS;interpPT_INTERP;

textPT_LOADFILEHDRPHDRS;dataPT_LOAD;

dynamicPT_DYNAMIC;}

SECTIONS{

.=SIZEOF_HEADERS;

.interp:{*(.interp)}:text:interp.text:{*(.text)}:text

.rodata:{*(.rodata)}/*defaultsto:text*/...

.=.+0x1000;/*movetoanewpageinmemory*/.data:{*(.data)}:data

.dynamic:{*(.dynamic)}:data:dynamic...}

10.版本號(hào)命令

當(dāng)使用ELF目標(biāo)文件格式時(shí),連接器支持帶版本號(hào)的符號(hào)。讀者可以發(fā)現(xiàn)僅僅在共享庫(kù)中,符號(hào)的版本號(hào)屬性才有意義。

動(dòng)態(tài)加載器使用符號(hào)的版本號(hào)為應(yīng)用程序選擇共享庫(kù)內(nèi)的一個(gè)函數(shù)的特定實(shí)現(xiàn)版本。可以在連接腳本內(nèi)直接使用版本號(hào)命令,也可以將版本號(hào)命令實(shí)現(xiàn)于一個(gè)特定版本號(hào)描述文件(用連接選項(xiàng)--version-script指定該文件)。該命令的文法如下,

VERSION{version-script-commands}以下內(nèi)容直接拷貝于以前的文檔,

=====================開(kāi)始==================================內(nèi)容簡(jiǎn)介0前提

1帶版本號(hào)的符號(hào)的定義2連接到帶版本的符號(hào)3GNU擴(kuò)展4我的疑問(wèn)

5英文探尋關(guān)鍵字6我的參考0.前提

--只限于ELF文件格式--以下探討用gcc

1.帶版本號(hào)的符號(hào)的定義(共享庫(kù)內(nèi))文件b.c內(nèi)容如下,intold_true(){

return1;}

intnew_true(){

return2;}

寫(xiě)連接器的版本控制腳本,本例中為b.lds,內(nèi)容如下

VER1.0{new_true;};

VER2.0{};

$gcc-cb.c

$gcc-shared-Wl,--version-script=b.lds-olibb.sob.o

可以在{}內(nèi)填入要綁定的符號(hào),本例中new_true符號(hào)就與VER1.0綁定了。

那么假使有一個(gè)應(yīng)用程序連接到該庫(kù)的new_true符號(hào),那么它連接的就是VER1.0版本的new_true符號(hào)

假使把b.lds更改為,VER1.0{};

VER2.0{new_true;};

然后在生成libb.so文件,在運(yùn)行那個(gè)連接到VER1.0版本的new_true符號(hào)的應(yīng)用程序,可以發(fā)現(xiàn)該應(yīng)用程序不能運(yùn)行了,

由于庫(kù)內(nèi)沒(méi)有VER1.0版本的new_true,只有VER2.0版本的new_true。2.連接到帶版本的符號(hào)

寫(xiě)一個(gè)簡(jiǎn)單的應(yīng)用(名為app)連接到libb.so,應(yīng)用符號(hào)new_true假設(shè)libb.so的版本控制文件為,VER1.0{};

VER2.0{new_true;};

$nmapp|grepnew_trueUnew_true@@VER1.0$

用nm命令發(fā)現(xiàn)app連接到VER1.0版本的new_true3.GNU的擴(kuò)展

它允許在程序文件內(nèi)綁定*符號(hào)*到*帶版本號(hào)的別名符號(hào)*文件b.c內(nèi)容如下,intold_true(){

return1;}

intnew_true(){

return2;}

__asm__(\__asm__(\

其中,帶版本號(hào)的別名符號(hào)是true,其默認(rèn)的版本號(hào)為VER2.0供連接器用的版本控制腳本b.lds內(nèi)容如下,VER1.0{};

VER2.0{};

版本控制文件內(nèi)必需包含版本VER1.0和版本VER2.0的定義,由于在b.c文件內(nèi)有對(duì)他們的引用

******假定libb.so與app.c在同一目錄下********以下應(yīng)用程序app.c連接到該庫(kù),inttrue();intmain(){

printf(\}

$gccapp.clibb.so

$LD_LIBRARY_PATH=../app2

$nmapp|greptrueUtrue@@VER2.0$

很明顯,程序app使用的是VER2.0版本的別名符號(hào)true,假使在b.c內(nèi)沒(méi)有指明別名符號(hào)true的默認(rèn)版本,

那么gccapp.clibb.so將出現(xiàn)連接錯(cuò)誤,提醒true沒(méi)有定義。也可以在程序內(nèi)指定特定版本的別名符號(hào)true,程序如下,__asm__(\inttrue();intmain(){

printf(\}

$gccapp.clibb.so

$LD_LIBRARY_PATH=../app1

$nmapp|greptrueUtrue@VER1.0$

顯然,連接到了版本號(hào)為VER1.0的別名符號(hào)true。其中只有一個(gè)@表示,該版本不是默認(rèn)的版本我的疑問(wèn):

版本控制腳本文件中,各版本號(hào)節(jié)點(diǎn)之間的依靠關(guān)系英文探尋關(guān)鍵字:.symver

versionedsymbol

versionasharedlibrary參考:

infold,Scriptsnode

=====================終止==================================11.表達(dá)式

表達(dá)式的文法與C語(yǔ)言的表達(dá)式文法一致,表達(dá)式的值都是整型,假使ld的運(yùn)行主機(jī)和生成文件的目標(biāo)機(jī)都是32位,則表達(dá)式是32位數(shù)據(jù),否則是64位數(shù)據(jù)。能夠在表達(dá)式內(nèi)使用符號(hào)的值,設(shè)置符號(hào)的值。下面看六項(xiàng)表達(dá)式相關(guān)內(nèi)容,常表達(dá)式:

_fourk_1=4K;/*K、M單位*/_fourk_2=4096;/*整數(shù)*/

_fourk_3=0x1000;/*16進(jìn)位

溫馨提示

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

評(píng)論

0/150

提交評(píng)論