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

下載本文檔

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

文檔簡(jiǎn)介

《計(jì)算機(jī)系統(tǒng)》鏈接plus篇《計(jì)算機(jī)系統(tǒng)》課程教學(xué)組2025年春季學(xué)期可執(zhí)行文件vs.

進(jìn)程的存儲(chǔ)映射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可執(zhí)行文件的加載通過調(diào)用execve系統(tǒng)調(diào)用函數(shù)來調(diào)用加載器加載器(loader)根據(jù)可執(zhí)行文件的程序(段)頭表中的信息,將可執(zhí)行文件的代碼和數(shù)據(jù)從磁盤“拷貝”到存儲(chǔ)器中(實(shí)際上不會(huì)真正拷貝,僅建立一種映像,此處可以回憶一下OS的內(nèi)容,后續(xù)我們還會(huì)講VM)加載后,將PC(EIP)設(shè)定指向Entrypoint

(即符號(hào)_start處),最終執(zhí)行main函數(shù),以啟動(dòng)程序執(zhí)行。程序被啟動(dòng)如$./P調(diào)用fork()以構(gòu)造的argv和envp為參數(shù)調(diào)用execve()execve()調(diào)用加載器進(jìn)行可執(zhí)行文件加載,并最終轉(zhuǎn)去執(zhí)行main__libc_init_first_initatexitmain_exit_start:ELF文件信息示例ELF文件信息示例int__libc_start_main(int(*main)(int,char**,char**),intargc,char**ubp_av,void(*init)(void),void(*fini)(void),void(*rtld_fini)(void),void(*stack_end));//初始化程序運(yùn)行環(huán)境,并調(diào)用main()函數(shù)開始程序的執(zhí)行。ELF文件信息示例庫靜態(tài)庫共享庫鏈接器本講內(nèi)容打包常用函數(shù)如何打包編程者經(jīng)常使用的功能函數(shù)?Math,I/O,memorymanagement,stringmanipulation等不那么合適的待選方案:Option1:將所有函數(shù)寫入一個(gè)源代碼文件編程者需要將一個(gè)很大的目標(biāo)文件鏈接到其程序空間和時(shí)間性能都低Option2:每一個(gè)函數(shù)形成一個(gè)單獨(dú)的源文件編程者需將自己的程序顯示地鏈接到相應(yīng)的二進(jìn)制文件更有效,但對(duì)于編程者是額外負(fù)擔(dān)解決方法靜態(tài)庫靜態(tài)庫(.a

存檔文件集)一組連接起來的可重定位目標(biāo)文件集合,有一個(gè)頭部用來描述每個(gè)成員目標(biāo)文件的大小和位置增強(qiáng)了鏈接器,其可以通過在一個(gè)或多個(gè)存檔中查找符號(hào)來解析外部引用若一個(gè)存檔成員文件解析了引用,則可將其連接到可執(zhí)行文件

創(chuàng)建靜態(tài)庫Translatoratoi.catoi.oTranslatorprintf.cprintf.olibc.aArchiver(ar)...Translatorrandom.crandom.o$arrcslibc.aatoi.oprintf.o…random.oC標(biāo)準(zhǔn)庫存檔文件(Archiver)允許增量升級(jí)更新

重編譯的函數(shù)改變并替換存檔中的原有.o文件通用庫libc.a(theCstandardlibrary)8MBarchiveof1392objectfiles.I/O,memoryallocation,signalhandling,stringhandling,dataandtime,randomnumbers,integermathlibm.a(theCmathlibrary)1MBarchiveof401objectfiles.floatingpointmath(sin,cos,tan,log,exp,sqrt,…) $ar-t/usr/lib/libc.a|sort…fork.o…fprintf.ofpu_control.ofputc.ofreopen.ofscanf.ofseek.ofstab.o…$ar-t/usr/lib/libm.a|sort…e_acos.oe_acosf.oe_acosh.oe_acoshf.oe_acoshl.oe_acosl.oe_asin.oe_asinf.oe_asinl.o…鏈接中的靜態(tài)庫Translators(cpp,cc1,as)main2.cmain2.olibc.aLinker(ld)p2printf.oandanyothermodulescalledbyprintf.olibvector.aaddvec.oStaticlibrariesRelocatableobjectfilesFullylinkedexecutableobjectfilevector.hArchiver(ar)addvec.omultvec.o使用靜態(tài)庫解析外部引用的鏈接器算法:

E將被合并以組成可執(zhí)行文件的所有目標(biāo)文件集合,起初為Φ U當(dāng)前所有未解析的引用符號(hào)的集合,起初為Φ D當(dāng)前所有定義符號(hào)的集合,起初為Φ按照命令行順序掃描.o

目標(biāo)文件,加入E

,并將當(dāng)前未解析引用的符號(hào)入列表U

,已解析符號(hào)入列表D;再掃描.a文件,將U中的符號(hào)與靜態(tài)庫中定義的符號(hào)依次匹配,匹配成功,則將符號(hào)從U移出,放入D;若在掃描結(jié)束時(shí),未解析列表U中仍有條目存在,則報(bào)錯(cuò)

;否則合并和重定位E中目標(biāo)文件,形成可執(zhí)行文件。存在問題:此時(shí),命令行中的順序很重要!原則上應(yīng)將庫文件放在命令行的末尾

$gcc-static

main.c./libvector.a

$gcc–static./libvector.amain.c…….o:Infunction`main':…….o(.text+0x18):undefinedreferenceto`addvec'共享庫靜態(tài)庫存在如下缺點(diǎn):在存儲(chǔ)中的可執(zhí)行文件中有多個(gè)副本(每一個(gè)函數(shù)均需要靜態(tài)庫文件)在運(yùn)行中的可執(zhí)行文件中存在多個(gè)副本

即便是對(duì)系統(tǒng)庫進(jìn)行小bug的修復(fù),也需要對(duì)使用到這個(gè)庫的所有應(yīng)用顯示地重新鏈接

更好的解決方案:共享庫包含代碼和數(shù)據(jù)的目標(biāo)文件,或者在加載時(shí),或者在執(zhí)行時(shí),被動(dòng)態(tài)加載和鏈接到應(yīng)用中

也被稱為:動(dòng)態(tài)鏈接庫,DLLs,.so文件使用共享庫在內(nèi)存中只有一個(gè)備份,被所有進(jìn)程共享(調(diào)用),節(jié)省內(nèi)存空間一個(gè)共享庫目標(biāo)文件被所有程序共享鏈接,節(jié)省硬盤空間共享庫升級(jí)時(shí),被自動(dòng)加載到內(nèi)存和程序動(dòng)態(tài)鏈接,使用方便共享庫可分模塊、獨(dú)立、用不同編程語言進(jìn)行開發(fā),效率高第三方開發(fā)的共享庫可作為程序插件,使程序功能易于擴(kuò)展加載時(shí)的動(dòng)態(tài)鏈接Translators(cpp,cc1,as)main2.cmain2.olibc.solibvector.soLinker(ld)p2Dynamiclinker(ld-linux.so)Relocationandsymboltableinfolibc.solibvector.soCodeanddata部分鏈接的可執(zhí)行目標(biāo)文件

可重定位目標(biāo)文件存儲(chǔ)器中完全鏈接的可執(zhí)行文件vector.hLoader(execve)$gcc-shared-olibvector.soaddvec.cmultvec.c-fPIC動(dòng)態(tài)鏈接用到一個(gè)重要概念:位置無關(guān)代碼(Position-IndependentCode,PIC)GCC選項(xiàng)-fPIC指示生成PIC代碼共享庫代碼是一種PIC共享庫代碼的位置可以是不確定的即使共享庫代碼的長(zhǎng)度發(fā)生變化,也不影響調(diào)用它的程序引入PIC的目的鏈接器無需修改代碼即可將共享庫加載到任意地址運(yùn)行要實(shí)現(xiàn)動(dòng)態(tài)鏈接,必須生成PIC代碼動(dòng)態(tài)鏈接用到一個(gè)重要概念:位置無關(guān)代碼(Position-IndependentCode,PIC)GCC選項(xiàng)-fPIC指示生成PIC代碼共享庫代碼是一種PIC共享庫代碼的位置可以是不確定的即使共享庫代碼的長(zhǎng)度發(fā)生變化,也不影響調(diào)用它的程序引入PIC的目的鏈接器無需修改代碼即可將共享庫加載到任意地址運(yùn)行先來看看所有可能出現(xiàn)的符號(hào)引用情況(1)模塊內(nèi)的過程調(diào)用、跳轉(zhuǎn),采用PC相對(duì)偏移尋址(2)模塊內(nèi)數(shù)據(jù)訪問,如模塊內(nèi)的全局變量和靜態(tài)變量(3)模塊外的過程調(diào)用、跳轉(zhuǎn)(4)模塊外的數(shù)據(jù)訪問,如外部變量的訪問要實(shí)現(xiàn)動(dòng)態(tài)鏈接,必須生成PIC代碼調(diào)用或跳轉(zhuǎn)源與目的地都在同一個(gè)模塊,相對(duì)位置固定,只要用相對(duì)偏移尋址即可。call的目標(biāo)地址為:0x8048369+0xffffffdb=0x8048344模塊內(nèi)的過程調(diào)用、跳轉(zhuǎn),采用PC相對(duì)偏移尋址動(dòng)態(tài)鏈接用到一個(gè)重要概念:位置無關(guān)代碼(Position-IndependentCode,PIC)GCC選項(xiàng)-fPIC指示生成PIC代碼共享庫代碼是一種PIC共享庫代碼的位置可以是不確定的即使共享庫代碼的長(zhǎng)度發(fā)生變化,也不影響調(diào)用它的程序引入PIC的目的鏈接器無需修改代碼即可將共享庫加載到任意地址運(yùn)行先來看看所有可能出現(xiàn)的符號(hào)引用情況(1)模塊內(nèi)的過程調(diào)用、跳轉(zhuǎn),采用PC相對(duì)偏移尋址(2)模塊內(nèi)數(shù)據(jù)訪問,如模塊內(nèi)的全局變量和靜態(tài)變量(3)模塊外的過程調(diào)用、跳轉(zhuǎn)(4)模塊外的數(shù)據(jù)訪問,如外部變量的訪問要實(shí)現(xiàn)動(dòng)態(tài)鏈接,必須生成PIC代碼voidtest(){a=1;……}模塊內(nèi)數(shù)據(jù)訪問,如模塊內(nèi)的全局變量和靜態(tài)變量動(dòng)態(tài)鏈接用到一個(gè)重要概念:位置無關(guān)代碼(Position-IndependentCode,PIC)GCC選項(xiàng)-fPIC指示生成PIC代碼共享庫代碼是一種PIC共享庫代碼的位置可以是不確定的即使共享庫代碼的長(zhǎng)度發(fā)生變化,也不影響調(diào)用它的程序引入PIC的目的鏈接器無需修改代碼即可將共享庫加載到任意地址運(yùn)行庫內(nèi)定義的符號(hào),庫外用戶程序進(jìn)行符號(hào)引用模塊外的數(shù)據(jù)訪問,如外部變量的訪問模塊外的過程調(diào)用、跳轉(zhuǎn)要實(shí)現(xiàn)動(dòng)態(tài)鏈接,必須生成PIC代碼要生成PIC代碼,主要解決這兩個(gè)問題位置無關(guān)代碼的實(shí)現(xiàn)原理是基于以下事實(shí):可執(zhí)行文件的代碼段中指令和數(shù)據(jù)段中的變量之間,相對(duì)地址偏移是固定的即與絕對(duì)存儲(chǔ)器位置無關(guān)的數(shù)據(jù)段總是緊跟著代碼段之后!全局變量引用位置無關(guān)全局偏移量表GOT在數(shù)據(jù)段:為每個(gè)全局變量引用增加一個(gè)條目每個(gè)條目有一個(gè)重定位記錄可執(zhí)行文件加載時(shí),對(duì)全局變量進(jìn)行重定位GOT[0]~GOT[3]是內(nèi)置的表項(xiàng)設(shè)若addvec函數(shù)引用全局變量addcntGOT全局偏移表(GlobalOffsetTable,GOT)主要作用就是支持動(dòng)態(tài)鏈接共享庫和位置無關(guān)代碼GOT本質(zhì)是一個(gè)地址數(shù)組,其每一個(gè)條目(“槽”)包含一個(gè)指向函數(shù)或變量的地址鏈接時(shí):鏈接器在創(chuàng)建可執(zhí)行文件時(shí)會(huì)創(chuàng)建GOT。加載時(shí):當(dāng)程序被加載到內(nèi)存中時(shí),動(dòng)態(tài)鏈接器會(huì)更新GOT中的某些條目。這包括解析外部函數(shù)和變量的地址,并將這些地址寫入相應(yīng)的GOT槽中。運(yùn)行時(shí):程序在運(yùn)行時(shí)可能會(huì)通過GOT表來訪問外部函數(shù)和變量。通過間接尋址實(shí)現(xiàn)的——代碼不是直接跳轉(zhuǎn)到目標(biāo)地址,而是跳轉(zhuǎn)到GOT中相應(yīng)的條目,然后從該條目中讀取實(shí)際地址并跳轉(zhuǎn)到該地址。GOT全局偏移表(GlobalOffsetTable,GOT)主要作用就是支持動(dòng)態(tài)鏈接共享庫和位置無關(guān)代碼GOT本質(zhì)是一個(gè)地址數(shù)組,其每一個(gè)條目(“槽”)包含一個(gè)指向函數(shù)或變量的地址鏈接時(shí):鏈接器在創(chuàng)建可執(zhí)行文件時(shí)會(huì)創(chuàng)建GOT。加載時(shí):當(dāng)程序被加載到內(nèi)存中時(shí),動(dòng)態(tài)鏈接器會(huì)更新GOT中的某些條目。這包括解析外部函數(shù)和變量的地址,并將這些地址寫入相應(yīng)的GOT槽中。運(yùn)行時(shí):程序在運(yùn)行時(shí)可能會(huì)通過GOT表來訪問外部函數(shù)和變量。通過間接尋址實(shí)現(xiàn)的——代碼不是直接跳轉(zhuǎn)到目標(biāo)地址,而是跳轉(zhuǎn)到GOT中相應(yīng)的條目,然后從該條目中讀取實(shí)際地址并跳轉(zhuǎn)到該地址。.dynamic段里面保存:動(dòng)態(tài)鏈接器所需要的基本信息,比如依賴于哪些共享對(duì)象、動(dòng)態(tài)鏈接符號(hào)表的位置、動(dòng)態(tài)鏈接重定位表的位置、共享對(duì)象初始化代碼的地址等R_386_GLOB_DAT是一個(gè)x86架構(gòu)下的重定位類型,用于在程序運(yùn)行時(shí)將全局符號(hào)與其定義綁定。當(dāng)使用該重定位類型時(shí),鏈接器會(huì)在可執(zhí)行文件中創(chuàng)建一個(gè)GOT(GlobalOffsetTable)表項(xiàng),并將該表項(xiàng)的值設(shè)置為指向該全局符號(hào)的地址R_386_JUMP_SLOT是一個(gè)x86架構(gòu)下的重定位類型,用于在程序運(yùn)行時(shí)將PLT(ProcedureLinkageTable)表項(xiàng)與它們的定義綁定。當(dāng)使用該重定位類型時(shí),鏈接器會(huì)在可執(zhí)行文件中創(chuàng)建一個(gè)PLT表項(xiàng),并將該表項(xiàng)的值設(shè)置為跳轉(zhuǎn)指令,用于調(diào)用相應(yīng)的函數(shù)名(符號(hào))。函數(shù)引用位置無關(guān)過程鏈接表(PLT)由編譯器創(chuàng)建,處于代碼段中:PLT[0]用于調(diào)用動(dòng)態(tài)鏈接器;PLT[1]用于跳轉(zhuǎn)到__libc_start_main函數(shù)執(zhí)行初始化工作;從PLT[2]開始為函數(shù)引用的表項(xiàng),每個(gè)函數(shù)引用對(duì)應(yīng)一個(gè)表項(xiàng).got用來保存全局變量引用的地址;.got.plt用來保存函數(shù)引用的地址,即對(duì)于外部函數(shù)的引用全部被分離出來放到了“.got.plt”中調(diào)用函數(shù)addvec()函數(shù)引用位置無關(guān)訪問PLT[n],n>1將待重定位符號(hào)(此處為共享庫內(nèi)定義放入函數(shù)名)id(查看.rel.plt內(nèi)容可知)入棧跳轉(zhuǎn)到PLT[0],入棧.dynamic

section內(nèi)容根據(jù)重定位表和重定位函數(shù)找到所需函數(shù)名對(duì)應(yīng)的符號(hào)值(地址)改寫對(duì)應(yīng).plt.got內(nèi)容為函數(shù)地址調(diào)用函數(shù)addvec()函數(shù)引用位置無關(guān)過程鏈接表(PLT)由編譯器創(chuàng)建,處于代碼段中:PLT[0]用于調(diào)用動(dòng)態(tài)鏈接器;PLT[1]用于跳轉(zhuǎn)到__libc_start_main函數(shù)執(zhí)行初始化工作;從PLT[2]開始為函數(shù)引用的表項(xiàng),每個(gè)函數(shù)引用對(duì)應(yīng)一個(gè)表項(xiàng).got用來保存全局變量引用的地址;.got.plt用來保存函數(shù)引用的地址,即對(duì)于外部函數(shù)的引用全部被分離出來放到了“.got.plt”中調(diào)用函數(shù)addvec()&addvec第二次調(diào)用addvec()時(shí),直接控制傳遞到PLT[2],通過GOT[4]間接跳轉(zhuǎn)控制轉(zhuǎn)移到addvec()函數(shù)動(dòng)態(tài)鏈接器本身是動(dòng)態(tài)鏈接還是靜態(tài)鏈接?動(dòng)態(tài)鏈接器本身是用來幫助其他ELF文件解決共享對(duì)象依賴問題的,必須不能依賴于其他共享對(duì)象!可執(zhí)行文件PLT表GOT表

庫中函數(shù)

加載時(shí)動(dòng)態(tài)鏈接程序頭表中有一個(gè)特殊的段:INTERP其中記錄了動(dòng)態(tài)鏈接器目錄及文件名ld-linux.so運(yùn)行時(shí)的動(dòng)態(tài)鏈接#include<stdio.h>#include<dlfcn.h>intx[2]={1,2};inty[2]={3,4};intz[2];intmain(){void*handle;void(*addvec)(int*,int*,int*,int);char*error;

/*dynamicallyloadthesharedlibthatcontainsaddvec()*/handle=dlopen("./libvector.so",RTLD_LAZY);if(!handle){ fprintf(stderr,"%s\n",dlerror());

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論