娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

GCC編譯器原理(二)------編譯原理一:ELF文件(3)

發(fā)布者:WhisperingWinds最新更新時(shí)間:2024-08-22 來(lái)源: cnblogs關(guān)鍵字:GCC編譯器  編譯原理  ELF文件 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

4.5 String Table:字符串表

字符串表節(jié)區(qū)包含以 NULL( ASCII 碼 0) 結(jié)尾的字符序列, 通常稱為字符串。 ELF 目標(biāo)文件通常使用字符串來(lái)表示符號(hào)和節(jié)區(qū)名稱。 對(duì)字符串的引用通常以字符串在字符串表中的下標(biāo)給出。

一般, 第一個(gè)字節(jié)(索引為 0)定義為一個(gè)空字符串。類似的,字符串表的最后一個(gè)字節(jié)也定義為 NULL,以確保所有的字符串都以 NULL 結(jié)尾。索引為 0 的字符串在不同的上下文中可以表示無(wú)名或者名字為 NULL 的字符串。

允許存在空的字符串表節(jié)區(qū),其節(jié)區(qū)頭部的 sh_size 成員應(yīng)該為 0。對(duì)空的字符串表而言,非 0 的索引值是非法的。

例如:對(duì)于各個(gè)節(jié)區(qū)而言,節(jié)區(qū)頭部的 sh_name 成員包含其對(duì)應(yīng)的節(jié)區(qū)頭部字符串表節(jié)區(qū)的索引,此節(jié)區(qū)由 ELF 頭的 e_shstrndx 成員給出。下圖給出了包含 25 個(gè)字節(jié)的一個(gè)字符串表,以及與不同索引相關(guān)的字符串。

上表中包含的字符串如下:

  • 在使用、分析字符串表時(shí),要注意以下幾點(diǎn):

    • 字符串表索引可以引用節(jié)區(qū)中任意字節(jié)。

    • 字符串可以出現(xiàn)多次

    • 可以存在對(duì)子字符串的引用

    • 同一個(gè)字符串可以被引用多次。

    • 字符串表中也可以存在未引用的字符串。

4.6 Symbol Table:符號(hào)表

目標(biāo)文件的符號(hào)表中包含用來(lái)定位、 重定位程序中符號(hào)定義和引用的信息。 符號(hào)表索引是對(duì)此數(shù)組的索引。索引 0 表示表中的第一表項(xiàng),同時(shí)也作為未定義符號(hào)的索引(即 STN_UNDEF)。

目標(biāo)文件中的符號(hào)表通常是文件中的一個(gè)段,段名一般叫做'.symtab'。符號(hào)表的結(jié)構(gòu)是 Elf32_sym,每個(gè) Elf32_sym 結(jié)構(gòu)對(duì)應(yīng)一個(gè)符號(hào),最后組成一個(gè)結(jié)構(gòu)體數(shù)組。

1 typedef struct {

2     Elf32_Word st_name;         /* 符號(hào)名 */

3     Elf32_Addr st_value;        /* 符號(hào)相對(duì)應(yīng)的值 */

4     Elf32_Word st_size;         /* 符號(hào)大小 */

5     unsigned char st_info;      /* 符號(hào)類型和綁定信息 */

6     unsigned char st_other;     /* 未使用 */

7     Elf32_Half st_shndx;        /* 符號(hào)所在的段 */

8 } Elf32_sym;

 

各個(gè)字段的含義如下:

字段

說(shuō)明

st_name

包含目標(biāo)文件符號(hào)字符串表的索引, 其中包含符號(hào)名的字符串表示。 如果該值非 0, 則它表示了給出符號(hào)名的字符串表索引, 否則符號(hào)表項(xiàng)沒(méi)有名稱。

注:外部 C 符號(hào)在 C 語(yǔ)言和目標(biāo)文件的符號(hào)表中具有相同的名稱。

st_value

此成員給出相關(guān)聯(lián)的符號(hào)的取值。依賴于具體的上下文,它可能是一個(gè)絕對(duì)值、一個(gè)地址等等。

st_size

很多符號(hào)具有相關(guān)的尺寸大小。 例如一個(gè)數(shù)據(jù)對(duì)象的大小是對(duì)象中包含的字節(jié)數(shù)。如果符號(hào)沒(méi)有大小或者大小未知,則此成員為 0。

st_info

此成員給出符號(hào)的類型和綁定屬性。 下面給出若干取值和含義的綁定關(guān)系。

st_other

該成員當(dāng)前包含 0,其含義沒(méi)有定義。

st_shndx

每個(gè)符號(hào)表項(xiàng)都以和其他節(jié)區(qū)間的關(guān)系的方式給出定義。此成員給出相關(guān)的節(jié)區(qū)頭部表索引。某些索引具有特殊含義。

4.6.1 st_info符號(hào)類型和綁定信息

該成員的低 4 位表示符號(hào)的類型(Symbol Type),高 28 位表示符號(hào)綁定信息(Symbol Binding),符號(hào)表項(xiàng) st_info 字段合成如下:

/usr/include/elf.h

低 4 位表示符號(hào)綁定,用于確定鏈接可見(jiàn)性和行為,具體綁定類型如下:

名稱

取值

說(shuō)明

STB_LOCAL

0

局部符號(hào)在包含該符號(hào)定義的目標(biāo)文件以外不可見(jiàn)。 相同名稱的局部符號(hào)可以存在于多個(gè)文件中,互不影響。

STB_GLOBAL

1

全局符號(hào)對(duì)所有將組合的目標(biāo)文件都是可見(jiàn)的。一個(gè)文件中對(duì)某個(gè)全局符號(hào)的定義將滿足另一個(gè)文件對(duì)相同全局符號(hào)的未定義引用。

STB_WEAK

2

弱符號(hào)與全局符號(hào)類似,不過(guò)他們的定義優(yōu)先級(jí)比較低。

STB_LOPROC

13

處于這個(gè)范圍的取值是保留給處理器專用語(yǔ)義的。

STB_HIPROC

15

在每個(gè)符號(hào)表中,所有具有 STB_LOCAL 綁定的符號(hào)都優(yōu)先于弱符號(hào)和全局符號(hào)。符號(hào)表節(jié)區(qū)中的 sh_info 頭部成員包含第一個(gè)非局部符號(hào)的符號(hào)表索引。

符號(hào)類型( ELF32_ST_TYPE)定義如下:

名稱

取值

說(shuō)明

STT_NOTYPE

0

符號(hào)的類型沒(méi)有指定

STT_OBJECT

1

符號(hào)與某個(gè)數(shù)據(jù)對(duì)象相關(guān),比如一個(gè)變量、數(shù)組等等

STT_FUNC

2

符號(hào)與某個(gè)函數(shù)或者其他可執(zhí)行代碼相關(guān)

STT_SECTION

3

符號(hào)與某個(gè)節(jié)區(qū)相關(guān)。 這種類型的符號(hào)表項(xiàng)主要用于重定位,通常具有 STB_LOCAL 綁定。

STT_FILE

4

傳統(tǒng)上, 符號(hào)的名稱給出了與目標(biāo)文件相關(guān)的源文件的名稱。文件符號(hào)具有 STB_LOCAL 綁定,其節(jié)區(qū)索引是 SHN_ABS, 并且它優(yōu)先于文件的其他 STB_LOCAL 符號(hào)(如果有的話)

STT_LOPROC

13

此范圍的符號(hào)類型值保留給處理器專用語(yǔ)義用途。

STT_HIPROC

15

在共享目標(biāo)文件中的函數(shù)符號(hào)(類型為 STT_FUNC)具有特別的重要性。當(dāng)其他目標(biāo)文件引用了來(lái)自某個(gè)共享目標(biāo)中的函數(shù)時(shí), 鏈接編輯器自動(dòng)為所引用的符號(hào)創(chuàng)建過(guò)程鏈接表項(xiàng)。類型不是 STT_FUNC 的共享目標(biāo)符號(hào)不會(huì)自動(dòng)通過(guò)過(guò)程鏈接表進(jìn)行引用。

如果一個(gè)符號(hào)的取值引用了某個(gè)節(jié)區(qū)中的特定位置,那么它的節(jié)區(qū)索引成員(st_shndx)包含了其在節(jié)區(qū)頭部表中的索引。當(dāng)節(jié)區(qū)在重定位過(guò)程中被移動(dòng)時(shí),符號(hào)的取值也會(huì)隨之變化,對(duì)符號(hào)的引用始終會(huì) '指向' 程序中的相同位置。

【1】弱符號(hào)與強(qiáng)符號(hào)

在編程中經(jīng)常碰到一種情況叫符號(hào)重復(fù)定義。多個(gè)目標(biāo)文件中含有相同名字全局符號(hào)的定義,在這些目標(biāo)文件鏈接的時(shí)候?qū)?huì)出現(xiàn)符號(hào)重復(fù)定義的錯(cuò)誤。

強(qiáng)符號(hào)(Strong Symbol):對(duì)于C/C++ 語(yǔ)言來(lái)說(shuō),編譯器默認(rèn)函數(shù)和初始化了的全局變量為強(qiáng)符號(hào)

弱符號(hào)(Weak Symbol):未初始化的全局變量為弱符號(hào)

可以通過(guò) GCC 的 '__attribute__((weak))' 來(lái)定義任何一個(gè)強(qiáng)符號(hào)為弱符號(hào)。需要注意的是,強(qiáng)符號(hào)和弱符號(hào)都是針對(duì)定義來(lái)說(shuō)的,不是針對(duì)符號(hào)引用。

  • 鏈接器處理強(qiáng)弱符號(hào)的規(guī)則如下:

    • 規(guī)則1:不允許強(qiáng)符號(hào)被多次定義(即不同的目標(biāo)文件中不能有同名的強(qiáng)符號(hào));如果有多個(gè)強(qiáng)符號(hào)定義,則鏈接器報(bào)符號(hào)重復(fù)定義錯(cuò)誤

    • 規(guī)則2:如果一個(gè)符號(hào)在某個(gè)目標(biāo)文件中是強(qiáng)符號(hào),在其他文件中都是弱符號(hào),那么選擇強(qiáng)符號(hào)

    • 規(guī)則3:如果一個(gè)符號(hào)在所有目標(biāo)文件中都是弱符號(hào),那么選擇其中占用空間最大的一個(gè)

【2】弱引用和強(qiáng)引用

強(qiáng)引用(Strong Reference):我們所看到的對(duì)外部目標(biāo)文件的符號(hào)引用在目標(biāo)文件被最終鏈接成可執(zhí)行文件時(shí),它們必須要被正確決議,如果沒(méi)有找到該符號(hào)的定義,鏈接器就會(huì)報(bào)符號(hào)未定義錯(cuò)誤,這種就稱為強(qiáng)引用。

弱引用(Weak Reference):在處理弱引用的時(shí)候,如果該符號(hào)有定義,則鏈接器將該符號(hào)的引用決議;如果該符號(hào)未定義,則鏈接器對(duì)于該引用不報(bào)錯(cuò)。

弱引用和強(qiáng)引用主要用于庫(kù)的鏈接過(guò)程。

在 GCC 中,可以通過(guò)符號(hào) '__attribute__((weakref))' 這個(gè)擴(kuò)展關(guān)鍵字來(lái)聲明對(duì)一個(gè)外部函數(shù)的引用為弱引用。例如:

1 __attribute__ ((weakref)) void foo();

3 int main()

4 {

5     if(foo) foo();

6 }


4.6.2 st_shndx:節(jié)區(qū)索引

  • 某些特殊的節(jié)區(qū)索引具有不同的語(yǔ)義:

    • SHN_ABS:符號(hào)具有絕對(duì)取值,不會(huì)因?yàn)橹囟ㄎ欢l(fā)生變化。

    • SHN_COMMON:符號(hào)標(biāo)注了一個(gè)尚未分配的公共塊。符號(hào)的取值給出了對(duì)齊約束,與節(jié)區(qū)的 sh_addralign 成員類似。就是說(shuō),鏈接編輯器將為符號(hào)分配存儲(chǔ)空間,地址位于 st_value 的倍數(shù)處。 符號(hào)的大小給出了所需要的字節(jié)數(shù)。

    • SHN_UNDEF: 此節(jié)區(qū)表索引值意味著符號(hào)沒(méi)有定義。當(dāng)鏈接編輯器將此目標(biāo)文件與其他定義了該符號(hào)的目標(biāo)文件進(jìn)行組合時(shí), 此文件中對(duì)該符號(hào)的引用將被鏈接到實(shí)際定義的位置。

4.6.3 STN_UNDEF 符號(hào)

符號(hào)表中下標(biāo)為 0(STN_UNDEF)的表項(xiàng)被保留。其中包含如下數(shù)值:

名稱

取值

說(shuō)明

st_name

0

無(wú)名稱

st_value

0

0 值

st_size

0

無(wú)大小

st_info

0

無(wú)類型,局部綁定

st_other

0

無(wú)附加信息

st_shndx

0

無(wú)節(jié)區(qū)

4.6.4 st_value:符號(hào)取值

  • 不同的目標(biāo)文件類型中符號(hào)表項(xiàng)對(duì) st_value 成員具有不同的解釋:

    • 在可重定位文件中, st_value 中遵從了節(jié)區(qū)索引為 SHN_COMMON 的符號(hào)的對(duì)齊約束。

    • 在可重定位的文件中, st_value 中包含已定義符號(hào)的節(jié)區(qū)偏移。 就是說(shuō),st_value 是從 st_shndx 所標(biāo)識(shí)的節(jié)區(qū)頭部開(kāi)始計(jì)算,到符號(hào)位置的偏移。

    • 在可執(zhí)行和共享目標(biāo)文件中, st_value 包含一個(gè)虛地址。為了使得這些文件的符號(hào)對(duì)動(dòng)態(tài)鏈接器更有用,節(jié)區(qū)偏移( 針對(duì)文 件的解釋)讓位于虛擬地址(針對(duì)內(nèi)存的解釋),因?yàn)檫@時(shí)與節(jié)區(qū)號(hào)無(wú)關(guān)。

盡管符號(hào)表取值在不同的目標(biāo)文件中具有相似的含義, 適當(dāng)?shù)某绦蚩梢圆扇「咝У臄?shù)據(jù)訪問(wèn)方式。

4.7 重定位信息

重定位是將符號(hào)引用與符號(hào)定義進(jìn)行連接的過(guò)程。例如,當(dāng)程序調(diào)用了一個(gè)函數(shù)時(shí),相關(guān)的調(diào)用指令必須把控制傳輸?shù)竭m當(dāng)?shù)哪繕?biāo)執(zhí)行地址。

4.7.1 重定位表

成員

說(shuō)明

r_offset

此成員給出了重定位動(dòng)作所適用的位置。對(duì)于一個(gè)可重定位文件而言,此值是從節(jié)區(qū)頭部開(kāi)始到將被重定位影響的存儲(chǔ)單位之間的字節(jié)偏移。對(duì)于可執(zhí)行文件或者共享目標(biāo)文件而言, 其取值是被重定位影響到的存儲(chǔ)單元的虛擬地址。

r_info

此成員給出要進(jìn)行重定位的符號(hào)表索引, 以及將實(shí)施的重定位類型。

例如一個(gè)調(diào)用指令的重定位項(xiàng)將包含被調(diào)用函數(shù)的符號(hào)表索引。 如果索引是 STN_UNDEF, 那么重定位使用 0 作為'符號(hào)值'。重定位類型是和處理器相關(guān)的。當(dāng)程序代碼引用一個(gè)重定位項(xiàng)的重定位類型或者符號(hào)表索引, 則表示對(duì)表項(xiàng)的 r_info 成員應(yīng)用 ELF32_R_TYPE 或者 ELF32_R_SYM 的結(jié)果。

#define ELF32_R_SYM(i) ((i)>>8)

#define ELF32_R_TYPE(i)((unsigned char)(i))

#define ELF32_R_INFO(s, t) (((s)<<8) + (unsigned char)(t)

r_addend

此成員給出一個(gè)常量補(bǔ)齊, 用來(lái)計(jì)算將被填充到可重定位字段的數(shù)值。

如上所述,只有 Elf32_Rela 項(xiàng)目可以明確包含補(bǔ)齊信息。類型為 Elf32_Rel 的表項(xiàng)在將被修改的位置保存隱式的補(bǔ)齊信息。依賴于處理器體系結(jié)構(gòu),各種形式都可能存在, 甚至是必需的。 因此, 對(duì)特定機(jī)器的實(shí)現(xiàn)可以僅使用一種形式, 也可以根據(jù)上下文使用不同的形式。

重定位節(jié)區(qū)會(huì)引用兩個(gè)其它節(jié)區(qū):符號(hào)表、要修改的節(jié)區(qū)。節(jié)區(qū)頭部的 sh_info 和 sh_link 成員給出這些關(guān)系。不同目標(biāo)文件的重定位表項(xiàng)對(duì) r_offset 成員具有略微不同的解釋。

  • 在可重定位文件中, r_offset 中包含節(jié)區(qū)偏移。就是說(shuō)重定位節(jié)區(qū)自身描述了如何修改文件中的其他節(jié)區(qū);重定位偏移 指定了被修改節(jié)區(qū)中的一個(gè)存儲(chǔ)單元。

  • 在可執(zhí)行文件和共享的目標(biāo)文件中, r_offset 中包含一個(gè)虛擬地址。為了使得這些文件的重定位表項(xiàng)對(duì)動(dòng)態(tài)鏈接器更為有用,節(jié)區(qū)偏移(針對(duì)文件的解釋)讓位于虛地址(針對(duì)內(nèi)存的解釋)。

盡管對(duì) r_offset 的解釋會(huì)有少許不同,重定位類型的含義始終不變。

4.7.2 重定位類型

重定位表項(xiàng)描述如何修改后面的指令和數(shù)據(jù)字段。一般,共享目標(biāo)文件在創(chuàng)建時(shí),其基本虛擬地址是 0,不過(guò)執(zhí)行地址將隨著動(dòng)態(tài)加載而發(fā)生變化。

  • 重定位的過(guò)程,按照如下標(biāo)記:

    • A 用來(lái)計(jì)算可重定位字段的取值的補(bǔ)齊。

    • B 共享目標(biāo)在執(zhí)行過(guò)程中被加載到內(nèi)存中的位置(基地址)。

    • G 在執(zhí)行過(guò)程中, 重定位項(xiàng)的符號(hào)的地址所處的位置 —— 全局偏移表的索引。

    • GOT 全局偏移表( GOT)的地址。

    • L 某個(gè)符號(hào)的過(guò)程鏈接表項(xiàng)的位置(節(jié)區(qū)偏移/地址)。過(guò)程鏈接表項(xiàng)把函數(shù)調(diào)用重定位到正確的目標(biāo)位置。鏈接編輯器構(gòu)造初始的過(guò)程鏈接表,動(dòng)態(tài)鏈接器在執(zhí)行過(guò)程中修改這些項(xiàng)目。

    • P 存儲(chǔ)單位被重定位(用 r_offset 計(jì)算) 到的位置(節(jié)區(qū)偏移或者地址)。

    • S 其索引位于重定位項(xiàng)中的符號(hào)的取值。

重定位項(xiàng)的 r_offset 取值給定受影響的存儲(chǔ)單位的第一個(gè)字節(jié)的偏移或者虛擬地址。重定位類型給出那些位需要修改以及如何計(jì)算它們的取值。


關(guān)鍵字:GCC編譯器  編譯原理  ELF文件 引用地址:GCC編譯器原理(二)------編譯原理一:ELF文件(3)

上一篇:GCC編譯器原理(三)------編譯原理三:編譯過(guò)程---預(yù)處理
下一篇:GCC編譯器原理(二)------編譯原理一:ELF文件(2)

小廣播
設(shè)計(jì)資源 培訓(xùn) 開(kāi)發(fā)板 精華推薦

最新單片機(jī)文章

 
EEWorld訂閱號(hào)

 
EEWorld服務(wù)號(hào)

 
汽車開(kāi)發(fā)圈

 
機(jī)器人開(kāi)發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號(hào) 京ICP備10001474號(hào)-1 電信業(yè)務(wù)審批[2006]字第258號(hào)函 京公網(wǎng)安備 11010802033920號(hào) Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 威远县| 阿巴嘎旗| 武平县| 贵溪市| 阿勒泰市| 射阳县| 尉犁县| 抚州市| 辽阳县| 盐城市| 万源市| 潜山县| 通江县| 吉木萨尔县| 城步| 嫩江县| 揭东县| 廊坊市| 高安市| 东兴市| 延长县| 尚志市| 无为县| 宿松县| 依兰县| 闻喜县| 宁化县| 湖口县| 西华县| 荆州市| 登封市| 通许县| 蚌埠市| 灌云县| 克山县| 澳门| 华阴市| 湘西| 忻城县| 新邵县| 长汀县|