日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...

發(fā)布時(shí)間:2024/10/8 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

///

不需要牛刀,不需要閱讀源碼,如果只是為解決109的含義。樓主執(zhí)行的查詢命令readelf?-S??test2.o

[?8]?.symtab???????????SYMTAB??????????00000000?0002a8?0000c0?10?????????9???7??4

.symtab起始于2a8,保存了符號(hào)信息,根據(jù)樓主提供的test2.o,從2a8開始,讀到367:

00002a8:???????????? 0000?0000?0000?0000

00002b0:?0000?0000?0000?0000?0100?0000?0000?0000??................

00002c0:?0000?0000?0400?f1ff?0000?0000?0000?0000??................

00002d0:?0000?0000?0300?0100?0000?0000?0000?0000??................

00002e0:?0000?0000?0300?0300?0000?0000?0000?0000??................

00002f0:?0000?0000?0300?0400?0000?0000?0000?0000??................

0000300:?0000?0000?0300?0500?0000?0000?0000?0000??................

0000310:?0000?0000?0300?0600?0900?0000?0000?0000??................

0000320:?0400?0000?1100?0300?0b00?0000?0400?0000??................

0000330:?0400?0000?1100?0300?0d00?0000?0800?0000??................

0000340:?0400?0000?1100?0300?0f00?0000?0000?0000??................

0000350:?0e00?0000?1200?0100?1300?0000?0e00?0000??................

0000360:?5200?0000?1200?0100

我們按照8字節(jié)為一個(gè)整體,數(shù)7個(gè)(前6個(gè)是symtab頭不信息?),到了318:

0900?0000?0000?0000?0400?0000?1100?0300

其中0900就是符號(hào)的具體位置偏移,我們?cè)購(gòu)?68開始看.strtab:

0074?6573?7432?2e63?0061?0062?0063?0066?756e?006d?6169?6e00

自己數(shù)數(shù)09位置是什么?沒錯(cuò)就是61,它是“a”的asic的16進(jìn)制值。

以此類推,0b是“b”,0d是“c”。

講到這里,0109、0108、0107的秘密應(yīng)該大白天下了吧?二樓已經(jīng)講了01是object,你在1100中的第二個(gè)`1`指的就是這個(gè)。而09、08、07,指的就是.symtab按八字節(jié)為一整塊算時(shí)的塊號(hào)罷了!每個(gè)塊代表一個(gè)符號(hào),并給出了strtab中相應(yīng)字符串的位置偏移和屬性解釋!

以上結(jié)論純屬觀察,本人完全不懂編譯原理,哈哈^_^

//

不是搞編譯的,只是記得以前看過一些介紹的文章,嘗試解答一下。

.text+2a:

2a:???ff?35?00?00?00?00???????pushl??0x0

很明顯,這是在push一個(gè)參數(shù),只是在編譯的時(shí)候,由于不知道最后的地址,操作數(shù)暫時(shí)為0。

經(jīng)過了鏈接階段,所有變量的地址都確定了,就可以替換這些臨時(shí)的操作數(shù)了。

如樓主所言,這些信息是保留在elf文件的relcoation?section里的。

代碼中一共有8處引用全局變量

#fun(a,?b,?c)

[2a]:???ff?35?00?00?00?00???????pushl??0x0

[30]:???ff?35?00?00?00?00???????pushl??0x0

[36]:???ff?35?00?00?00?00???????pushl??0x0

[3c]:???e8?fc?ff?ff?ff??????????call???3d?

#func(c,?b,?a)

[44]:???ff?35?00?00?00?00???????pushl??0x0

[4a]:???ff?35?00?00?00?00???????pushl??0x0

[50]:???ff?35?00?00?00?00???????pushl??0x0

[56]:???e8?fc?ff?ff?ff??????????call???57?

.rel.text:

0000380:?[2c00]?0000?<0109>?0000?[3200]?0000?<0108>?0000??,.......2.......

0000390:?[3800]?0000?<0107>?0000?[3d00]?0000?<020a>?0000??8.......=.......

00003a0:?[4600]?0000?<0108>?0000?[4c00]?0000?<0107>?0000??F.......L.......

00003b0:?[5200]?0000?<0109>?0000?[5700]?0000?<020a>?0000??R.......W.......

00003c0:?0a

顯然,.rel.text需要描述這8個(gè)對(duì)全局變量的引用,并觀察到[]里的地址的相似性,

因此可以推測(cè),每個(gè)引用占8個(gè)字節(jié)。

并且,<>里面的部分可以分為兩類:6個(gè)傳參的屬于一類01**,函數(shù)調(diào)用屬于一類02**。

猜測(cè)**是變量/函數(shù)名在符號(hào)表中的id。

觀察其中一組01類型的:

.text:

[2a]:???ff?35?[00?00?00?00]???????pushl??0x0

.rel.text:

0000380:?[2c00]?0000?<0109>?0000

2c正好是2a(push指令的地址)+2(push操作碼ff35的長(zhǎng)度),這就告訴ld,

在連接的時(shí)候,需要把2c的內(nèi)容(就是push指令的參數(shù))替換掉(當(dāng)前為0)。

替換成什么內(nèi)容,由<0109>決定。01是一種類型,09應(yīng)該是變量在symbol表中的id。

由于樓主沒有貼出test.o經(jīng)過linker鏈接后的結(jié)果,手頭也沒有32bit的機(jī)器,所以就不太好猜了……

最簡(jiǎn)單的可能性是,linker直接替換為變量的絕對(duì)地址。

至于02類型的:

3c:???e8?fc?ff?ff?ff??????????call???3d?

0000398:?[3d00]?0000?<020a>?0000

分析同上,3d=3c(call指定的地址)+1(call操作碼的長(zhǎng)度),就是call的參數(shù)的地址。

我手頭有64bit的機(jī)器,傳參和函數(shù)調(diào)用都被編譯為02類型的,通過readelf可以看到,02屬于R_X86_64_PC32類型。

實(shí)際上,這個(gè)call是個(gè)相對(duì)jmp,參數(shù)是相對(duì)于當(dāng)前ip/pc的偏移,在.o文件里,目的地址是-4(0xfffffffc),就是這條指令本身。

可以想象,在ld階段,-4會(huì)被替換為func函數(shù)跟call指令之間的地址差值。

(實(shí)際上,由于func是編譯單元內(nèi)部的函數(shù)調(diào)用,這個(gè)差值在編譯階段也可以確定的。)

由于<02>是相對(duì)偏移,因此[3c]和[56]雖然都是call?$func,它們的偏移值是不一樣的,所以兩條指令并不相同。

作為對(duì)比,30和4a都是push?$b,如果<01>類型是絕對(duì)地址的話,那么兩條指令就完全一樣。

以上,啰啰嗦嗦的,不知道有沒有說清楚。

1,調(diào)用fun前,將a,b,c作為參數(shù)壓棧,我們只看到連續(xù)push三個(gè)0,因?yàn)榫幾g階段,a,b,c的地址都不確定,暫時(shí)用0代替。

2,到了鏈接階段,linker會(huì)搜集所有.o文件中的符號(hào),并放到一張全局符號(hào)表里。像a,b,c,它們就有名字“a","b","c",并算出了對(duì)應(yīng)的地址,就這樣存到全局符號(hào)表里。

3,之前說到的,那三條push?0的指令,它們對(duì)應(yīng)的機(jī)器碼,是存儲(chǔ)在test2.o的.text段的,這時(shí)候當(dāng)然要把那三個(gè)零換成a,b,c的地址。

4,linker是根據(jù)test.o的.rel.text段來完成這個(gè)重定位的。.rel.text段是一個(gè)表,每個(gè)entry(表項(xiàng))8個(gè)字節(jié),數(shù)據(jù)結(jié)構(gòu)是這樣:

struct{

unsigned??????r_offset;

usnigned??????r_info;

}

linker根據(jù)r_offset知道,要修正的位置相對(duì)于.text段的偏移。就這樣定位到那三個(gè)0的位置。

根據(jù)r_info知道要修正的是哪個(gè)符號(hào)。再說細(xì)點(diǎn):linker根據(jù)r_info的高24位在全局符號(hào)表里索引到這個(gè)符號(hào),這樣,符號(hào)的地址就

順藤摸瓜的出來了。把它寫入r_offset處。

這樣重定位就完成了。

----------------以上是就32位elf來說的,某些敘述有簡(jiǎn)化。你可以去看《程序員的自我修養(yǎng)》

總結(jié)

以上是生活随笔為你收集整理的linux内核全局变量重定位,关于可重定位文件中全局变量的一个重定位疑惑,借各位牛刀一用^...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。