亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 129586 | 回復(fù): 13
打印 上一主題 下一主題

[內(nèi)核入門] 通過elf各種重定位類型,理解不同場合的鏈接過程 [復(fù)制鏈接]

論壇徽章:
13
15-16賽季CBA聯(lián)賽之八一
日期:2016-07-08 21:00:1415-16賽季CBA聯(lián)賽之同曦
日期:2017-02-15 14:26:1515-16賽季CBA聯(lián)賽之佛山
日期:2017-02-20 14:19:2615-16賽季CBA聯(lián)賽之青島
日期:2017-05-07 16:49:1115-16賽季CBA聯(lián)賽之廣夏
日期:2017-07-30 09:13:1215-16賽季CBA聯(lián)賽之廣東
日期:2018-07-05 22:34:3615-16賽季CBA聯(lián)賽之江蘇
日期:2018-09-03 12:10:2115-16賽季CBA聯(lián)賽之上海
日期:2018-09-25 03:49:2215-16賽季CBA聯(lián)賽之廣東
日期:2018-09-25 04:09:12
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2016-11-24 18:12 |只看該作者 |倒序瀏覽
本帖最后由 _nosay 于 2016-11-24 18:12 編輯

    最近為了理解elf格式規(guī)范中的各種重定位類型,暈了。跑出去玩了幾天,終于為每種重定位類型,找到了對應(yīng)的case。elf規(guī)范總共定義了10種重定位類型,之所以需要這么多種不同類型的重定位信息,是由于如下原因:
    ① 硬件對變量和函數(shù)的尋址方式不同,尋找變量要求絕對地址,尋找函數(shù)要求相對地址;
    ② 不同場合下,程序員對最終可執(zhí)行文件或動態(tài)庫的期望不一樣(位置無關(guān)、動態(tài)庫函數(shù)重定位延遲),從而加了不同的編譯選項(比如-fPIC、-Ox等);
    ③ C語言的static、extern特性,導(dǎo)致不同特性的變量或函數(shù)地址可以被確定的時機不同;
    ④ 內(nèi)核加載可執(zhí)行文件,約定從固定地址0x80480000開始,但加載.so的起始地址無法約定(一個可執(zhí)行程序只有一個main(),但可能依賴多個動態(tài)庫)。
    疑問:那整個系統(tǒng)中,可執(zhí)行程序也不只一個呀,都約定從相同的起始地址加載,不會沖突嗎?
    因為每個進(jìn)程訪問的都是虛擬地址,由內(nèi)核在背后負(fù)責(zé)將不同進(jìn)程的相同虛擬地址,映射到不同的實際物理地址(屬于內(nèi)核范疇,不理解沒關(guān)系,不影響對本貼關(guān)鍵內(nèi)容的理解)。

  • 靜態(tài)鏈接/動態(tài)鏈接簡單理解
    .c文件中的代碼最終被執(zhí)行,需要經(jīng)歷如下過程:
    ① 編譯:詞法解析 → 語法解析 → 靜態(tài)鏈接
    ② 加載:加載可執(zhí)行文件 → 可執(zhí)行文件啟動或執(zhí)行時,加載依賴的.so文件 → 動態(tài)鏈接

    本帖僅關(guān)注靜態(tài)鏈接、動態(tài)鏈接過程,靜態(tài)鏈接與動態(tài)鏈接區(qū)別:
    ① 靜態(tài)鏈接處于將1個或多個.o文件“拼湊”成可執(zhí)行文件階段,處理對象是文件,文件中的代碼區(qū)沒有只讀屬性,鏈接過程中可以直接修改;動態(tài)鏈接處于可執(zhí)行文件或.so文件已被加載到內(nèi)存階段,處理對象是內(nèi)存,內(nèi)核為代碼區(qū)所在的內(nèi)存區(qū)域設(shè)置了只讀屬性,如果代碼區(qū)有內(nèi)容需要重定位,需要在編譯或靜態(tài)鏈接時,事先準(zhǔn)備一個間接位置(加載到內(nèi)存不會被設(shè)置只讀屬性),動態(tài)鏈接是對該間接位置進(jìn)行重定位。
    ② 通過下圖可以看出,靜態(tài)鏈接將.o的各個節(jié)“撕開”,屬性相同的節(jié)“拼湊”為可執(zhí)行文件的段;動態(tài)鏈接是將“整個”.so文件安排在與可執(zhí)行文件鏡像相獨立的位置(圖中最簡化了.o、.so、可執(zhí)行文件的內(nèi)容,用于說明靜態(tài)鏈接與動態(tài)鏈接的區(qū)別,它們的內(nèi)容遠(yuǎn)遠(yuǎn)不止.data、.text)。
    另外,.so文件還涉及到位置無關(guān)(-fPIC)、延遲加載的選擇(應(yīng)該是跟優(yōu)化級別有關(guān)),接下來即將詳細(xì)總結(jié)。
   
    編譯階段,.o文件的全局變量位置不確定,因為這時無法確定還有其它哪些.o文件,以及鏈接器將來會按什么順序“排列”這些.o文件(見靜態(tài)鏈接示意圖),鏈接階段,.so文件的全局變量位置也不確定,是因為這時不知道.so文件將來被加載到進(jìn)程空間的什么位置(見動態(tài)鏈接示意圖)。既然不能確定,只能瞎寫,但計算機世界一是一、二是二,瞎寫完一定要留下一個“交待”(重定位項),等將來時機成熟時,再補上正確的值。

  • R_386_32
   
    R_386_32計算公式:S+A。
    S:對于.o文件,表示全局變量被鏈接器安排的位置或其所在xx節(jié)的起始位置;對于.so文件,表示全局變量被加載到的虛擬地址。
    A:被重定位處的原始值(4字節(jié),由重定位項offset指向)。

    暈了,沒關(guān)系,先看具體的case(看完R_386_32,再理解其它重定位類型就有感覺了):
    6處的指令“a1 00 00 00 00”,由于此時無法預(yù)測g1經(jīng)過加載后的地址,就先寫一個假地址0,16處指令“a1 04 00 00 00”,由于此時無法預(yù)測g3經(jīng)過鏈接后的位置,就先寫一個假地址4。但0、4都不是編譯器隨意寫上的,因為隨后做重定位計算時要將它們作為A值。
    另外,g4是未初始化的static全局變量,所以被“放在”.bss段,所以重定位項指定用.bss節(jié)位置作為S值(“放在”加了引號,是因為.bss在文件中不占空間,只有一個結(jié)構(gòu)用于指示加載到內(nèi)存時,它應(yīng)該處于的位置以及大小,比如一萬個0,在程序要執(zhí)行時,才需要為這些0分配內(nèi)存為它們所代表的變量占據(jù)位置,而在文件中不需要分配一萬個字節(jié),它只需要能提供一個簡短的信息,提供加載時能正確的分配一萬個字節(jié)并填充為0即可)。
   

    為了驗證圖中提出的問題,繼續(xù)分析鏈接該.o文件得到的.so文件:
   
    可以看出,對.o留下的不同類型重定位項,處理結(jié)果不一樣,暫時只關(guān)注g1、g3,鏈接器(ld)在.so文件中為g1仍然留了一條R_386_32重定位項,而為g3留了一條R_386_RELATIVE重定位項,再次處理這兩條重定位項,就已經(jīng)是加載到內(nèi)存后由動態(tài)鏈接器完成了(ld-linux.so.2),計算公式中的成員含義也會改變,比如S表示符號加載到的虛擬地址。
    不是說內(nèi)核會為代碼對應(yīng)的內(nèi)存區(qū)域設(shè)置只讀屬性么,加載到內(nèi)存后還能修改的了嗎?
    準(zhǔn)確的說,內(nèi)核將代碼加載到內(nèi)存,需要做很多處理,設(shè)置只讀只是其中一個,并且在完成重定位之后:“加載→重定位→設(shè)置只讀→執(zhí)行”。


    上述這種不加-fPIC選項編譯得到的.so文件,只是單純將一個完整的二進(jìn)制文件分隔成可執(zhí)行文件和.so文件,將重定位操作延遲到加載時了,并沒有發(fā)揮.so關(guān)鍵設(shè)計意圖:.so共享。
    因為各個進(jìn)程的虛擬空間使用情況不一樣,會導(dǎo)致這種情況:進(jìn)程A的100地址空閑,并將libc.so加載到100開始的虛擬空間,將.so鏡像中各個重定位處依據(jù)100地址計算重定位值,進(jìn)程B的200地址空閑,如果直接將內(nèi)存中已經(jīng)存在的libc.so鏡像映射到200位置,之前按100地址修改的重定位處,就不滿足進(jìn)程B的要求了,所以只能再加載一份libc.so并映射到自己的虛擬空間(稍后說明的位置無關(guān)就是為了解決這個問題)。

  • R_386_PC32
   
    R_386_PC32計算公式:S+A-P。
    S:對于.o文件,表示鏈接階段全局變量被安排的位置或其所在xx節(jié)起始位置;
         對于.so文件,表示全局變量被加載到的虛擬地址。
    A:被重定位處的原始值(4字節(jié),由重定位項offset指向)。
    P:重定位項中的offset值。對于.o、.so文件,表示被重定位處在.o、.so文件中的偏移;對于可執(zhí)行文件,表示被重定位處被加載到的虛擬地址。

    10處的指令“e8 fc ff ff ff”,由于此時無法預(yù)測f1()經(jīng)過加載后的地址,就先寫一個假地址-4,15處指令“e8 fc ff ff ff”,由于此時無法預(yù)測f2()經(jīng)過鏈接后的位置,就先寫一個假地址-4。
    -4-P解釋:首先P代表被重定位處位置(對于10處指令,P=11,對于15處指令,P=16),則P+4分別代表下一條指令位置15、1a(運行時就是下一條指令的虛擬地址),而硬件在處理機器碼e8(call指令)時,不是將緊接著后面的4字節(jié)直接作為跳轉(zhuǎn)地址,而是要加上下一條指令的地址,所以重定位時只好事先-(P+4)。
    對比說明R_386_32的case,g1的A值為0,g3的A值為4,而這里兩條重定位項的A值都是-4,因為它們的差距體現(xiàn)在這兩處,P值本身就不同。
   
    為什么f1()、f2()都有重定位項,fun()沒有?
    重定位項的生成是根據(jù)調(diào)用,而不是定義。

    另外,有了對R_386_32的理解基礎(chǔ),可以想象將該.o文件鏈接成.so文件,鏈接器會如何處理重定位項,并動手驗證一下(注意:有些電腦編譯.so文件必須加-fPIC選項,一方面可能跟系統(tǒng)是32/64位有關(guān),另一方面可能跟編譯器版本有關(guān))。
   
    非static函數(shù)fun()調(diào)用static函數(shù)f3(),為什么直接使用相對偏移即可
    當(dāng)前.so加載位置確定,f3()加載位置就確定了,不能確定fun()位置(同鏈接階段無法通過R_386_32重定位類型確定g1位置一個道理),那么此時計算的相對位置不也失效了嗎?

  • R_386_GOT32
   
    R_386_GOT32計算公式:G+A-P。
    G:鏈接階段生成的GOT表位置。
    A:被重定位處的原始值(4字節(jié),由重定位項offset指向)。
    P:重定位項中的offset值,表示被重定位處在.o文件中的偏移。

    對于G的解釋,提到GOT表,什么是GOT表?
    通過R_386_32、R_386_PC32的說明可知,不加-fPIC選項編譯得到的.so文件,并沒有給計算機帶來什么實惠,因為它的代碼根據(jù)前一個進(jìn)程對它的加載地址完成重定位后,之后其它進(jìn)程不能直接將它映射到自己的虛擬空間使用,因為它們對重定位計算的基準(zhǔn)不一樣。
    got表正是用于將需要重定位的內(nèi)容剝離出來,從大范圍(整個.so的代碼區(qū)域)匯聚到小范圍(.got表),即將加載地址對代碼區(qū)域的影響,轉(zhuǎn)移到對.got表的影響。所以說,.so共享并不是完全的共享,各個進(jìn)程仍然有一個.got表的副本,而.got表往往很小。

    主要利用兩個技巧:
    ① 在程序編寫階段,雖然不知道以下兩條指令真正執(zhí)行后ebx寄存會得到什么值,但能確定它的含義是當(dāng)時eip寄存器的值,那么跟這條指令相對位置固定的運行時地址,在邏輯上都能在編譯階段“獲知”:
        call L1
        L1: pop ebx
    ② 那么,在.so文件中相對于指令區(qū)域確定位置生成一個.got表,.so被執(zhí)行時.got表的絕對地址也是可以“獲知”的。這樣,就可以用.got表項的絕對地址,覆蓋原本在指令區(qū)域的重定位處,而.got表中存放將來才能確定的最終重定位的符號地址。

     一份代碼區(qū)域,多份.got表:
   

    理解mmap()函數(shù),有助于更深入理解上圖,在此只大概說明(涉及內(nèi)核的內(nèi)存管理和文件系統(tǒng)):
   
    ① 假設(shè)進(jìn)程A先將libc.so映射到自己的一塊虛擬空間,當(dāng)首次訪問這塊區(qū)間時發(fā)生缺頁異常,分配物理頁面并讀入內(nèi)容,然后建立映射。接著,進(jìn)程B也將libc.so映射到自己的一塊虛擬空間,首次訪問這塊區(qū)間仍然會發(fā)生缺頁異常,但與其建立映射的物理頁面,就不用再重新分配讀入了。從而,物理內(nèi)存只需要一份.so的內(nèi)容,就可以供A、B兩個進(jìn)程使用。
    ② 思維敏銳的可能會發(fā)現(xiàn)一個問題:.so文件中如果有全局變量,被多個進(jìn)程共享,不是會相互干擾嗎?
        COW(寫時復(fù)制):內(nèi)核為虛擬頁面、物理頁面都設(shè)置了一些屬性,比如如果對某個虛擬頁面進(jìn)行寫操作,就重新分配一個物理頁面,復(fù)制內(nèi)容并重新建立映射(為.so數(shù)據(jù)區(qū)分配的頁面,就具有這樣的屬性)。
    ③ 各個進(jìn)程將.so文件映射到自己的虛擬空間,數(shù)據(jù)區(qū)、代碼區(qū)的相對位置,仍然保持和剛鏈接過后一致,所以在代碼區(qū)向.got的重定位計算仍然有效,只不過動態(tài)鏈接器為不同進(jìn)程向.got表初始化全局變量的地址時,要向.got表進(jìn)行寫操作,導(dǎo)致每個進(jìn)程有一個.got副本。

    編譯說明R_386_32時使用的case代碼,加上-fPIC選項,就能看到編譯器為g1、g2變量在.o文件中生成了R_386_GOT32重定位項以及為g3、g4變量在.o文件中生成了R_386_GOTOFF重定位項,稍后說明)
   
    6、b處兩條指令執(zhí)行后,ecx寄存器會得到.got表加載地址,為什么?
    ① 前面已經(jīng)說明過R_386_PC32重定位類型,7處經(jīng)過這種類型重定位后,執(zhí)行時會跳轉(zhuǎn)到__x86.get_pc_thunk.cx,得到b處指令的加載地址(CPU沒有提供直接獲取當(dāng)前ip的指令,所以利用call會將返回地址壓棧的特點);
    ② R_386_GOTPC,提示鏈接器創(chuàng)建.got表,并修改d處的值,保證執(zhí)行時用它加ecx寄存器可以得到.got表地址(可以通過R_386_GLOB_DAT類型分析過程,編譯得到的.so驗證):
        通過①可能確定,執(zhí)行過6處指令后ecx得到的b處指令的加載地址,拿什么和它相加可以得到.got表位置呢?
        +A:從ecx所指位置往后推2字節(jié)(機器碼“81 c1”),就到了被重定位處(重定位項中的offset/規(guī)范文檔中的P);
        +G-P:再向后推.got表相對此處的距離,就到.got表了。
        注意:$0x2只是作為鏈接器計算重定位值的A,在執(zhí)行時就被G-P-2覆蓋了,不要疑惑為什么要從ecx減2,它的含義根本就不是減數(shù)。

  • R_386_GLOB_DAT
   
    R_386_GLOB_DAT計算公式:S。

    對比R_386_32、R_386_GOT32,就是在編譯.o文件時,加了-fPIC選項,R_386_GOT32重定位類型就是希望將重定位處從代碼區(qū)域轉(zhuǎn)移到.got表,鏈接階段創(chuàng)建.got表,完成代碼區(qū)域重定位,添加對.got表項的重定位項(轉(zhuǎn)移≠消除)。
    將說明R_386_GOT32時編譯得到的.o文件,鏈接成.so文件:
   
    ① 532、537處(對應(yīng).o文件中6、b處)指令,確實可以將.got表位置計算到ecx寄存器中(不過是結(jié)束位置,后面指令取.got表項地址時,用的是負(fù)偏移,可能不同編譯器不一樣吧,用開始位置、結(jié)束位置計算,道理是一樣的)
    ② g1、g2的重定位類型變成R_386_GLOB_DAT,它是用于告訴動態(tài)鏈接器,在確定g1、g2地址時,放到它們的.got表項里(0x1fe8、0x1ff4)。

  • R_386_PLT32
   
    R_386_PLT32計算公式:L+A-P

    與R_386_GOT32、R_386_GLOB_DAT道理相似,R_386_PLT32、R_386_JUMP_SLOT也是為支持PIC定義的重定位類型,前者面向的是全局變量,后者面向函數(shù)。
    不過由于為了支持“動態(tài)庫函數(shù)重定位延遲”,在.got.plt表跳轉(zhuǎn)前,還多了一層.plt表跳轉(zhuǎn),.plt表里是一些鏈接器為重定位函數(shù)生成的跳轉(zhuǎn)代碼片段,計算公式中的L表示為重定位函數(shù)生成的跳轉(zhuǎn)代碼片段在.so文件中的位置(可以通過R_386_JUMP_SLOT類型分析過程,編譯得到的.so驗證)。
   

  • R_386_JUMP_SLOT
   
    R_386_JUMP_SLOT計算公式:S

    相比鏈接器對R_386_GLOB_DAT重定位項的處理,R_386_JUMP_SLOT重定位項的處理過程更復(fù)雜,不光在.so文件中創(chuàng)建.got.plt表,還為f1()、f2()對應(yīng)生成了f1@plt、f2@plt代碼片段,并將代碼中對f1()、f2()的調(diào)用,分別替換成對f1@pltf2@plt的調(diào)用,同時對f1()、f2()的重定位類型變成了R_386_JUMP_SLOT,這個重定位類型不會在.so文件一加載時就被動態(tài)鏈接器處理,而是調(diào)用f1()、f2()的指令首次被執(zhí)行時,才進(jìn)行重定位操作(比如我喜歡學(xué)習(xí)內(nèi)核,但我目前的工作跟內(nèi)核并沒有多大關(guān)系,聰明的人都是等工作需要的時候,再學(xué))。

    不防看一下f1()首次被調(diào)用的過程:
    ① 562地址處的指令執(zhí)行后,ebx寄存器指向.got.plt表開始位置0x2000;
    ② 568、56d處原本對f1()、f2()的調(diào)用,被替換為對f1@plt、f2@plt的調(diào)用:
        <f1@plt>:
        410: jmp  *0x18(%ebx)    ;0x2018,f1()在.got.plt表中占據(jù)的表項位置,表項內(nèi)容初始值為0x416,即首次執(zhí)行這條指令時,相當(dāng)于“jmp 0x416”
        416: push $0x18
        41b: jmp  3d0 <_init+0x2c>

        有點奇怪,首次從410→416干嘛要特意繞個圈?
        這個圈只會在第一次執(zhí)行f1@plt時才會繞,當(dāng)416、41b處指令調(diào)用動態(tài)鏈接器,將f1()地址填到.got.plt表項0x2018后,以后再執(zhí)行410處指令時,就相當(dāng)于“jmp f1”了。即:
        第一次執(zhí)行f1@plt:410 → 416、41b → f1()
        第二次執(zhí)行f1@plt:410 → f1()
    而且鏈接器將所有調(diào)用f1()的地方都替換成調(diào)用f1@plt了,所以410→416這個圈,只會繞一次,不過即使這樣,每次調(diào)用f1(),也要先“call <fl@plt>”,所以延遲加載雖然“聰明”,但有得也有失。
   

  • R_386_COPY
   
    R_386_COPY計算公式:冇

    初始化的全局變量和未初始化全局變量,被安排的位置是不同的,分別在.data、.bss,那么,如果某個模塊通過extern引用了另外一個模塊中定義的全局變量,編譯階段是不知道這個變量是否被初始化了,因為它根本看不到其它.c文件,所以就暫時把該變量安排在.bss,等鏈接階段得知它如果有初始值的話,就依據(jù)此重定位項,修改一下.bss相應(yīng)位置的值。
   

  • R_386_RELATIVE
   
    R_386_RELATIVE計算公式:B+A
    B:.so文件加載地址。

    分析R_386_32類型時,已經(jīng)說明過R_386_RELATIVE,靜態(tài)變量位置在鏈接階段可以確定在.so文件中的偏移,那么計算它的加載地址,自然是加上.so文件的加載地址B就可以了。

  • R_386_GOTOFF
   
    R_386_GOTOFF計算公式:S+A-GOT

    編譯說明R_386_32時使用的case代碼,加上-fPIC選項,就能看到編譯器為g3、g4變量在.o文件中生成了R_386_GOTOFF重定位項(在分析R_386_GOT32類型時提到過,基于靜態(tài)變量相對于.so文件加載地址,距離固定,利用GOT表位置進(jìn)行重定位)。
   

  • R_386_GOTPC
   
    R_386_GOTPC計算公式:GOT+A-P

    分析R_386_GOT32類型時,已經(jīng)說明過R_386_GOTPC,它與R_386_32類似,只不過一個用于重定位變量位置,一個用于重定位.got表位置。

  • 總結(jié)
    把對各種重定位類型的理解放在同一張表格對比,它們之間的區(qū)別就暴露的赤裸裸,再也不撲朔迷離了:
  (為了xx,需要在xx階段xx,前一階段提供準(zhǔn)備,后一階段完成計算,或變換為另一種計算方式)
   

  • 參考
      http://www.cnblogs.com/catch/p/3857964.html
      http://blog.csdn.net/stonesharp/article/details/12943963
      http://blog.csdn.net/wuhui_gdnt/article/details/51035557
      http://blog.csdn.net/wuhui_gdnt/article/details/51094732
      http://blog.csdn.net/wuhui_gdnt/article/details/51160465
      http://jzhihui.iteye.com/blog/1447570
      http://blog.csdn.net/yuyin86/article/details/10239479

1-2008-07-25-TN05.ELF.Format.Summary.pdf

852.96 KB, 下載次數(shù): 271

評分

參與人數(shù) 1信譽積分 +10 收起 理由
nswcfd + 10 很給力!

查看全部評分

論壇徽章:
20
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-08-17 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-16 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-18 06:20:00每日論壇發(fā)貼之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16賽季CBA聯(lián)賽之江蘇
日期:2017-06-26 11:05:5615-16賽季CBA聯(lián)賽之上海
日期:2017-07-21 18:12:5015-16賽季CBA聯(lián)賽之青島
日期:2017-09-04 17:32:0515-16賽季CBA聯(lián)賽之吉林
日期:2018-03-26 10:02:16程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-15 06:20:0015-16賽季CBA聯(lián)賽之江蘇
日期:2016-07-07 18:37:512015亞冠之薩濟拖拉機
日期:2015-08-17 12:21:08
2 [報告]
發(fā)表于 2016-11-25 14:29 |只看該作者
下子寫帖子之前可以先把PS1修改一下,這樣就不用給每張圖打馬賽克了

也可以使用script命令來記錄程序的輸出;蛘呤褂胹creen/tmux等終端軟件的“截屏”功能。

論壇徽章:
13
15-16賽季CBA聯(lián)賽之八一
日期:2016-07-08 21:00:1415-16賽季CBA聯(lián)賽之同曦
日期:2017-02-15 14:26:1515-16賽季CBA聯(lián)賽之佛山
日期:2017-02-20 14:19:2615-16賽季CBA聯(lián)賽之青島
日期:2017-05-07 16:49:1115-16賽季CBA聯(lián)賽之廣夏
日期:2017-07-30 09:13:1215-16賽季CBA聯(lián)賽之廣東
日期:2018-07-05 22:34:3615-16賽季CBA聯(lián)賽之江蘇
日期:2018-09-03 12:10:2115-16賽季CBA聯(lián)賽之上海
日期:2018-09-25 03:49:2215-16賽季CBA聯(lián)賽之廣東
日期:2018-09-25 04:09:12
3 [報告]
發(fā)表于 2016-11-25 15:10 |只看該作者
回復(fù) 2# nswcfd

嗯嗯,我是遠(yuǎn)程別人電腦的,改成啥他不會怪我呢?

論壇徽章:
13
15-16賽季CBA聯(lián)賽之八一
日期:2016-07-08 21:00:1415-16賽季CBA聯(lián)賽之同曦
日期:2017-02-15 14:26:1515-16賽季CBA聯(lián)賽之佛山
日期:2017-02-20 14:19:2615-16賽季CBA聯(lián)賽之青島
日期:2017-05-07 16:49:1115-16賽季CBA聯(lián)賽之廣夏
日期:2017-07-30 09:13:1215-16賽季CBA聯(lián)賽之廣東
日期:2018-07-05 22:34:3615-16賽季CBA聯(lián)賽之江蘇
日期:2018-09-03 12:10:2115-16賽季CBA聯(lián)賽之上海
日期:2018-09-25 03:49:2215-16賽季CBA聯(lián)賽之廣東
日期:2018-09-25 04:09:12
4 [報告]
發(fā)表于 2016-11-25 19:04 |只看該作者

論壇徽章:
20
程序設(shè)計版塊每日發(fā)帖之星
日期:2015-08-17 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-16 06:20:00程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-18 06:20:00每日論壇發(fā)貼之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16賽季CBA聯(lián)賽之江蘇
日期:2017-06-26 11:05:5615-16賽季CBA聯(lián)賽之上海
日期:2017-07-21 18:12:5015-16賽季CBA聯(lián)賽之青島
日期:2017-09-04 17:32:0515-16賽季CBA聯(lián)賽之吉林
日期:2018-03-26 10:02:16程序設(shè)計版塊每日發(fā)帖之星
日期:2016-07-15 06:20:0015-16賽季CBA聯(lián)賽之江蘇
日期:2016-07-07 18:37:512015亞冠之薩濟拖拉機
日期:2015-08-17 12:21:08
5 [報告]
發(fā)表于 2016-12-02 11:50 |只看該作者
phrack.org, very good!

論壇徽章:
6
2015年辭舊歲徽章
日期:2015-03-05 16:13:092015年迎新春徽章
日期:2015-03-05 16:13:092015小元宵徽章
日期:2015-03-06 15:58:1815-16賽季CBA聯(lián)賽之浙江
日期:2016-11-05 14:38:4115-16賽季CBA聯(lián)賽之新疆
日期:2016-11-11 18:38:06
6 [報告]
發(fā)表于 2016-12-06 21:43 |只看該作者
不同的軟硬件平臺會有不同的重定位類型,基本的就兩種:絕對定位與相對定位。如x64平臺上有64位的絕對定位與32位的相對定位

論壇徽章:
0
7 [報告]
發(fā)表于 2017-02-23 00:23 |只看該作者
這篇真!把芯慷疾欢,看這篇就懂了

論壇徽章:
0
8 [報告]
發(fā)表于 2017-02-26 22:04 |只看該作者
good summary, thanks!

論壇徽章:
13
15-16賽季CBA聯(lián)賽之八一
日期:2016-07-08 21:00:1415-16賽季CBA聯(lián)賽之同曦
日期:2017-02-15 14:26:1515-16賽季CBA聯(lián)賽之佛山
日期:2017-02-20 14:19:2615-16賽季CBA聯(lián)賽之青島
日期:2017-05-07 16:49:1115-16賽季CBA聯(lián)賽之廣夏
日期:2017-07-30 09:13:1215-16賽季CBA聯(lián)賽之廣東
日期:2018-07-05 22:34:3615-16賽季CBA聯(lián)賽之江蘇
日期:2018-09-03 12:10:2115-16賽季CBA聯(lián)賽之上海
日期:2018-09-25 03:49:2215-16賽季CBA聯(lián)賽之廣東
日期:2018-09-25 04:09:12
9 [報告]
發(fā)表于 2018-02-08 16:29 |只看該作者
回復(fù) 1# _nosay

https://stackoverflow.com/questi ... bjdump-symbol-table



論壇徽章:
13
15-16賽季CBA聯(lián)賽之八一
日期:2016-07-08 21:00:1415-16賽季CBA聯(lián)賽之同曦
日期:2017-02-15 14:26:1515-16賽季CBA聯(lián)賽之佛山
日期:2017-02-20 14:19:2615-16賽季CBA聯(lián)賽之青島
日期:2017-05-07 16:49:1115-16賽季CBA聯(lián)賽之廣夏
日期:2017-07-30 09:13:1215-16賽季CBA聯(lián)賽之廣東
日期:2018-07-05 22:34:3615-16賽季CBA聯(lián)賽之江蘇
日期:2018-09-03 12:10:2115-16賽季CBA聯(lián)賽之上海
日期:2018-09-25 03:49:2215-16賽季CBA聯(lián)賽之廣東
日期:2018-09-25 04:09:12
10 [報告]
發(fā)表于 2018-07-08 01:22 |只看該作者
關(guān)于R_386_PC32,帖子里提了一個問題,表示當(dāng)時我對這種重定位類型的理解有錯誤。
f2()的調(diào)用處,需要對應(yīng)一個R_386_PC32重定位項,這是很容易理解的,因為它是extern的,鏈接的時候才知道f2()指令塊的開始位置,相應(yīng)的,call指令中的偏移值,也必須等鏈接時才可以確定。
疑惑在f1()和f3(),它們的指令塊都在f.o的.text節(jié),而鏈接是將各個.o文件的.text節(jié)整個搬到最終的目標(biāo)文件中,不是被打碎了再搬進(jìn)去的,所以f1()同f3()一樣,與fun()的相對位置,在編譯階段就能確定下來,即使f1()可以被別的模塊調(diào)用,也影響不了這一點,那憑什么對f3()的調(diào)用不需要設(shè)置重定位項,f1()的調(diào)用卻需要?
那是因為R_386_PC32這種重定位原本只是用于extern函數(shù)調(diào)用的,而非static函數(shù)默認(rèn)也有extern屬性,所以就多此一舉的為f1()調(diào)用處加了重定位項,將call指令中相對位移的計算推遲到了鏈接時,雖然不影響正確性,但是對學(xué)習(xí)的人好有干擾性,很容易讓人覺得是由于static非static的區(qū)別,卻又不能完全解釋的通,因為本質(zhì)是根據(jù)extern非extern的區(qū)別來的,直到今天才發(fā)現(xiàn)!
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP