計算機(jī)系統(tǒng)-從應(yīng)用程序到底層實現(xiàn) 課件 第17講 Link-3_第1頁
計算機(jī)系統(tǒng)-從應(yīng)用程序到底層實現(xiàn) 課件 第17講 Link-3_第2頁
計算機(jī)系統(tǒng)-從應(yīng)用程序到底層實現(xiàn) 課件 第17講 Link-3_第3頁
計算機(jī)系統(tǒng)-從應(yīng)用程序到底層實現(xiàn) 課件 第17講 Link-3_第4頁
計算機(jī)系統(tǒng)-從應(yīng)用程序到底層實現(xiàn) 課件 第17講 Link-3_第5頁
已閱讀5頁,還剩39頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

$

gcc–g–o–p

main.c

test.c繼續(xù)觀察可執(zhí)行文件p加載可執(zhí)行目標(biāo)文件ELFheaderProgramheadertable(requiredforexecutables).textsection.datasection.bsssection.symtab.debugSectionheadertable(requiredforrelocatables)ExecutableObjectFileKernelvirtualmemoryMemory-mappedregionforsharedlibrariesRun-timeheap(createdbymalloc)Userstack(createdatruntime)Unused%esp

(stackpointer)Memoryoutside32-bitaddressspacebrk0x1000000000x080480000xf7e9ddc0Read/writesegment(.data,.bss)Read-onlysegment(.init,.text,.rodata)Loadedfromtheexecutablefile.rodatasection.line.initsection.strtab《計算機(jī)系統(tǒng)》鏈接下篇《計算機(jī)系統(tǒng)》課程教學(xué)組2025年春季學(xué)期庫靜態(tài)庫共享庫鏈接器本講內(nèi)容鏈接的作用&意義鏈接器的輸入/出文件ELF細(xì)節(jié)鏈接器工作步驟符號屬性符號解析解析規(guī)則重定位類型與過程鏈接符號全局符號Global由模塊m定義并能被其他模塊引用的符號例:非靜態(tài)C函數(shù)和非靜態(tài)的全局變量

外部符號External由其他模塊定義并被模塊m引用的全局符號

本地符號Local由模塊m定義和引用的本地符號例:帶靜態(tài)屬性的C函數(shù)和變量本地鏈接符號不是本地程序變量符號解析intbuf[2]={1,2};

intmain(){swap();return0;}main.cexternintbuf[];

int*bufp0=&buf[0];staticint*bufp1;voidswap(){inttemp;bufp1=&buf[1];temp=*bufp0;*bufp0=*bufp1;*bufp1=temp;}swap.cGlobalExternalExternalLocalGlobalLinkerknowsnothingoftempGlobal符號解析示例編譯順利進(jìn)行,無報錯!然后,鏈接時……符號解析再示例編譯順利進(jìn)行,無報錯!然后,鏈接時……本地符號,同一文件中的同名本地符號//以下兩個函數(shù)在同一文件中intf(){statica=100;returna;}intg(){statica=-10;returna;}無誤編譯器在.data中為兩個同名整數(shù)分配空間,并引導(dǎo)出兩個唯一本地鏈接用符號,比如用a.1和a.2分別表示兩個函數(shù)中的定義的同名a/*test.c*/intadd1(inti,intj){staticinta=20;staticintb;intx=a++;returnx;}/*test1.c*/intadd(inti,intj){staticinta=1;staticintb=0;intx=a+b;returnx;}如右所示代碼,如下描述正確的是:f和g都是全局符號實際只有一個本地符號x若staticint變量不初始化,則缺省初值為0此代碼中無外部符號ABCDSubmit多選題50分為什么?1#include<stdio.h>2intd=100;3intx=200;4voidp1(void);5intmain()6{7p1();8printf(“d=%d,x=%d\n”,d,x);9return0;10}1doubled;23voidp1()4{5d=1.0;6}p1.cmain.c打印結(jié)果是d=0,x=1072693248

強(qiáng)/弱符號編譯時,編譯器向匯編器輸出的每個全局符號,或者是強(qiáng)符號或者是弱符號

Strong:函數(shù)和已初始化的全局變量

Weak:未初始化的全局變量intfoo=5;p1(){}intfoo;p2(){}p1.cp2.cstrongweakstrongstrong鏈接器的符號規(guī)則對于多重定義的全局符號——Rule1:不允許有多個強(qiáng)符號強(qiáng)符號只能被定義一次

否則:鏈接器產(chǎn)生錯誤信息Rule2:若有一個強(qiáng)符號和多個弱符號,則解析時選擇強(qiáng)符號定義

此時引用弱符號會導(dǎo)致解析強(qiáng)符號Rule3:若有多個弱符號,則從這些弱符號中任意選擇一個作為符號定義

使用gcc–fno-common選項調(diào)用鏈接器,在遇到多重定義的全局符號時,會有警告信息

出錯啦,錯在哪里?intx=0;p1(){}intx;p2(){

x=100}intx;inty;p1(){}doublex;p2(){}intx=7;inty=5;p1(){}doublex;p2(){}intx;p1(){}intx;p2(){}intx;p1(){}p1(){}Linktimeerror:twostrongsymbols(p1)Referencestoxwillrefertothesameuninitializedint.Isthiswhatyoureallywant?Writestoxinp2mightoverwritey!Evil!Writestoxinp2

willoverwritey!Nasty!Nightmarescenario:twoidenticalweakstructs,compiledbydifferentcompilerswithdifferentalignmentrules.Referencestoxwillrefertothesameinitializedvariable.d到底如何被定義?1#include<stdio.h>2intd=100;3intx=200;4voidp1(void);5intmain()6{7p1();8printf(“d=%d,x=%d\n”,d,x);9return0;10}1doubled;23voidp1()4{5d=1.0;6}p1.cmain.c為什么?1#include<stdio.h>2intd=100;3intx=200;4voidp1(void);5intmain()6{7p1();8printf(“d=%d,x=%d\n”,d,x);9return0;10}1doubled;23voidp1()4{5d=1.0;6}p1.cmain.c打印結(jié)果是d=0,x=1072693248

為什么?1#include<stdio.h>2intd=100;3intx=200;4voidp1(void);5intmain()6{7p1();8printf(“d=%d,x=%d\n”,d,x);9return0;10}1doubled;23voidp1()4{5d=1.0;6}p1.cmain.c打印結(jié)果是d=0,x=1072693248

1.0:0011111111110…0Binary=3FF0000000000000Hexadecimal悟了十個1則打印輸出:

[填空1]

,

[填空2]

作答//main.c#include<stdio.h>inty=100;intz;voidp1(void);intmain(){z=1000;p1();printf(“y=%d,z=%d\n”,y,z);return0;}//p1.cinty;intz;voidp1(){y=200;z=2000;}填空題15分則打印輸出:

[填空1]

[填空2]

[填空3]

作答//main.c#include<stdio.h>inty=100;intz=11;inta=99;voidp1(void);intmain(){z=1000;p1();printf(“y=%d\n”,y);printf(“z=%d\n”,z);printf(“a=%d\n”,a);return0;}//p1.cdoublez;inty;voidp1(){z=0.0;y=200;}填空題30分全局變量的使用若可以要盡量避免使用全局變量否則盡可能使用static定義全局變量時要初始化如果要使用外部全局變量需使用extern鏈接第一步符號定義符號引用符號解析將符號引用與符號定義連接起來鏈接第二步重定位……

重定位第1步:重定位節(jié)和符號定義相同類型的節(jié)合并形成新的聚合段

將運行時的存儲器地址賦給新的聚合段

使得每個指令和全局變量有唯一的運行時存儲器地址重定位第2步:重定位節(jié)中的符號引用修改代碼節(jié)和數(shù)據(jù)節(jié)中的每個符號的引用,使其指向相應(yīng)的符號定義的存儲器地址依賴重定位條目重定位

R_386_PC32:重定位一個使用32位PC相對地址的引用PC相對地址:指距程序計數(shù)器PC當(dāng)前運行值的偏移量PC總是指向下一條將要執(zhí)行的指令地址

總是與跨文件的函數(shù)調(diào)用有關(guān)

R_386_32:重定位一個使用32位地址的絕對地址的引用通過絕對尋址,直接使用編碼中的32位地址作為有效地址總是與使用跨文件的全局變量有關(guān)基本重定位類型重定位代碼與數(shù)據(jù)main()main.oint*bufp0=&buf[0]swap()swap.ointbuf[2]={1,2}Headersmain()swap()0Systemcodeint*bufp0=&buf[0]intbuf[2]={1,2}SystemdataMoresystemcodeSystemdata可重定位目標(biāo)文件可執(zhí)行目標(biāo)文件.text.text.data.text.data.text.data.symtab.debug.dataint*bufp1.bssSystemcodestaticint*bufp1.bssEventhoughprivatetoswap,requiresallocationin.bss回顧示例//main.cintbuf[2]={1,2};

intmain(){swap();return0;}//swap.cexternintbuf[];

int*bufp0=&buf[0];staticint*bufp1;voidswap(){inttemp;bufp1=&buf[1];temp=*bufp0;*bufp0=*bufp1;*bufp1=temp;}重定位信息mainintbuf[2]={1,2};

intmain(){swap();return0;}Disassemblyofsection.data:00000000<buf>:0:0100000002000000Source:objdump–r-dmain.cmain.o0000000<main>:0: 8d4c2404lea0x4(%esp),%ecx4: 83e4f0and$0xfffffff0,%esp7: ff71fcpushl0xfffffffc(%ecx)a: 55push%ebpb: 89e5mov%esp,%ebpd: 51push%ecxe: 83ec04sub$0x4,%esp11: e8fcffffffcall12<main+0x12>

12:R_386_PC32 swap16: 83c404add$0x4,%esp19: 31c0xor%eax,%eax1b: 59pop%ecx1c: 5dpop%ebp1d: 8d61fclea0xfffffffc(%ecx),%esp20: c3retELF重定位條目:重定位信息mainDisassemblyofsection.data:00000000<buf>:0:0100000002000000Source:objdump–r-dmain.o0000000<main>:0: 8d4c2404lea0x4(%esp),%ecx4: 83e4f0and$0xfffffff0,%esp7: ff71fcpushl0xfffffffc(%ecx)a: 55push%ebpb: 89e5mov%esp,%ebpd: 51push%ecxe: 83ec04sub$0x4,%esp11: e8fcffffffcall12<main+0x12>

12:R_386_PC32 swap16: 83c404add$0x4,%esp19: 31c0xor%eax,%eax1b: 59pop%ecx1c: 5dpop%ebp1d: 8d61fclea0xfffffffc(%ecx),%esp20: c3retELF重定位條目:假設(shè)發(fā)生重定位的當(dāng)前text節(jié)開始地址ADDR(.text)=0x8048380

swap的代碼段開始地址為ADDR(swap.text)=0x80483b0當(dāng)前PC值=0x8048380+0x12-init=0x8048392-(-4)10=0x8048396偏移地址:ADDR(swap)-當(dāng)前PC值=0X1aPC

原PC+0x1a080483b0<swap>:80483b0: 8b1520960408 mov0x8049620,%edx80483b6: a124960408 mov0x8049624,%eax80483bb: 55 push%ebp80483bc: 89e5 mov%esp,%ebp80483be: c7053096040824 movl$0x8049624,0x804963080483c5: 96040880483c8: 8b08 mov(%eax),%ecx80483ca: 8910 mov%edx,(%eax)80483cc: 5d pop%ebp80483cd: 890d24960408 mov%ecx,0x804962480483d3: c3 ret重定位信息swap的.textexternintbuf[];

int*bufp0=&buf[0];staticint*bufp1;voidswap(){inttemp;bufp1=&buf[1];temp=*bufp0;*bufp0=*bufp1;*bufp1=temp;}swap.cswap.oDisassemblyofsection.text:00000000<swap>:0: 8b1500000000 mov0x0,%edx

2:R_386_32 buf6: a104000000 mov0x4,%eax

7:R_386_32 bufb: 55 push%ebpc: 89e5 mov%esp,%ebpe: c7050000000004 movl$0x4,0x015: 000000

10:R_386_32 .bss

14:R_386_32 buf

18: 8b08 mov(%eax),%ecx1a: 8910 mov%edx,(%eax)1c: 5d pop%ebp1d: 890d04000000 mov%ecx,0x4

1f:R_386_32 buf23: c3 ret重定位信息swap,.textswap.oDisassemblyofsection.text:00000000<swap>:0: 8b1500000000 mov0x0,%edx

2:R_386_32 buf6: a104000000 mov0x4,%eax

7:R_386_32 bufb: 55 push%ebpc: 89e5 mov%esp,%ebpe: c7050000000004 movl$0x4,0x015: 000000

10:R_386_32 .bss

14:R_386_32 buf

18: 8b08 mov(%eax),%ecx1a: 8910 mov%edx,(%eax)1c: 5d pop%ebp1d: 890d04000000 mov%ecx,0x4

1f:R_386_32 buf23: c3 retELF重定位條目:這是一個絕對引用若符號buf的絕對地址ADDR(buf)=0x8049620繼續(xù)重定位絕對地址……

重定位信息swap,.textswap.oDisassemblyofsection.text:00000000<swap>:0: 8b1500000000 mov0x0,%edx

2:R_386_32 buf6: a104000000 mov0x4,%eax

7:R_386_32 bufb: 55 push%ebpc: 89e5 mov%esp,%ebpe: c7050000000004 movl$0x4,0x015: 000000

10:R_386_32 .bss

14:R_386_32 buf

18: 8b08 mov(%eax),%ecx1a: 8910 mov%edx,(%eax)1c: 5d pop%ebp1d: 890d04000000 mov%ecx,0x4

1f:R_386_32 buf23: c3 retELF重定位條目:這是一個絕對引用若符號buf的絕對地址ADDR(buf)=0x8049620繼續(xù)重定位絕對地址……

080483b0<swap>:80483b0: 8b1520960408 mov0x8049620,%edx80483b6: a124960408 mov0x8049624,%eax80483bb: 55 push%ebp80483bc: 89e5 mov%esp,%ebp80483be: c7053096040824 movl$0x8049624,0x804963080483c5: 96040880483c8: 8b08 mov(%eax),%ecx80483ca: 8910 mov%edx,(%eax)80483cc: 5d pop%ebp80483cd: 890d24960408 mov%ecx,0x804962480483d3: c3 retDisassemblyofsection.data:08049620<buf>:

8049620:010000000200000008049628<bufp0>:8049628:20960408重定位信息swap,.textDisassemblyofsection.text:00000000<swap>:0: 8b1500000000 mov0x0,%edx

2:R_386_32 buf6: a104000000 mov0x4,%eax

7:R_386_32 bufb: 55 push%ebpc: 89e5 mov%esp,%ebpe: c7050000000004 movl$0x4,0x015: 000000

10:R_386_32 .bss

14:R_386_32 buf

18: 8b08 mov(%eax),%ecx1a: 8910 mov%edx,(%eax)1c: 5d pop%ebp1d: 890d04000000 mov%ecx,0x4

1f:R_386_32 buf23: c3 retELF重定位條目:這是一個絕對引用若符號buf的絕對地址ADDR(buf)=0x8049620繼續(xù)重定位絕對地址……

080483b0<swap>:80483b0: 8b1520960408 mov0x8049620,%edx80483b6: a124960408 mov0x8049624,%eax80483bb: 55 push%ebp80483bc: 89e5 mov%esp,%ebp80483be: c7053096040824 movl$0x8049624,0x804963080483c5: 96040880483c8: 8b08 mov(%eax),%ecx80483ca: 8910 mov%edx,(%eax)80483cc: 5d pop%ebp80483cd: 890d24960408 mov%ecx,0x804962480483d3: c3 ret重定位前/后.data絕對地址引用重定位前/后你還能找到其他絕對地址重定位嗎?相對地址引用重定位前/后可執(zhí)行文件的存儲器映像%espbrk0xC000000000x080480000內(nèi)核虛存區(qū)共享庫區(qū)域堆(heap)動態(tài)生成)用戶棧動態(tài)生成未使用讀寫數(shù)據(jù)段(.data,.bss)只讀代碼段(.text,.rodata等)從可執(zhí)行文件裝入1GB可執(zhí)行目標(biāo)文件intbuf[2]={1,2}Headersmain()swap()0int

*bufp0=&buf[0]更多系統(tǒng)代碼系統(tǒng)數(shù)據(jù).text.symtab.debug.dataint*bufp1.bss系統(tǒng)代碼程序(段)頭表描述如何映射!可執(zhí)行文件中的程序頭表typedefstruct{Elf32_Wordp_type;Elf32_Offp_offset;Elf32_Addrp_vaddr;Elf32_Addr

溫馨提示

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

評論

0/150

提交評論