動態庫和靜態庫詳解

庫其實就是個文件

下面是文件后綴

靜態庫:.a(linux)? ?.lib(windows)

動態庫:.so(linux) .dll(windows)

靜態庫的制作

ar? ?-rc? ?libmystdio.a? ?my_stdio.o? ?my_string.o

ar是歸檔工具,rc表示replace和create,ar跟tar有點像,把.o文件打包到一塊,其他啥也不干

ar? -tv??libmystdio.a?

t: 列出靜態庫中的?件 ,v:詳細信息,查看靜態庫

動態庫的制作

libmystdio.so:my_stdio.o my_string.o
????????gcc -o $@ $^ -shared
%.o:%.c
????????gcc -fPIC -c $<
制作動態庫的目標文件必須是源文件-fPIC編譯成的,pic意思是位置無關編碼,pic編譯和普通的編譯有什么區別呢?
正常的編譯如果你調用一個函數,編出來的指令是call 臨時地址,那pic編譯呢,call pc+臨時偏移量,這個偏移量是目標函數和pc之間的相對距離。因為動態庫的加載位置是共享區,起始位置不固定,所以不能用絕對地址
生成動態庫的過程其實就是把pic編譯的目標文件給鏈接起來,要加-shared選項,表示不是鏈接出一個可執行文件而是動態庫

?

庫的使用

庫這個文件的用處,就是和其他目標文件一起鏈接得到可執行程序
引?庫的名稱:去掉前綴 lib ,去掉后綴 .so , .a ,如: libc.so -> c
gcc main.c -I 頭?件路徑 -L 庫?件路徑 -lmymath
先編譯main.c成目標文件,再和mymath庫鏈接,得到最后的同名可執行文件main

ELF文件

那些文件是ELF文件?

.o目標文件

.exe可執行文件

.so動態庫文件

核心轉儲文件

ELF文件的格式

ELF(ELF header)

程序頭表 (Program header table)
節( Section
節頭表 (Section header table)

1. 節頭表(Section Header Table)??

  • ??描述目標文件(.o)中的各個??節(section)??(如?.text.data.symtab?等),供??靜態鏈接器??(ld)使用
  • 鏈接時,鏈接器會合并不同目標文件中的??同名節??(如將所有?.text?合并到代碼段)成段。
  • ??動態庫/可執行文件可以沒有節頭表??。

??2. 程序頭表(Program Header Table,段頭表)??

  • ??描述可執行文件或動態庫中的??段(segment)??(如代碼段、數據段),供操作系統??加載器??(execve/ld.so)使用。
  • ??加載時,操作系統根據程序頭表將段映射到內存(如?LOAD?類型的段)
  • ?動態庫和可執行文件必須有程序頭表??(否則無法加載),可以沒有節頭表。

??3. ELF 頭?

  • ??e_entry?字段??:指定程序執行的起始地址(即?_start?函數的地址),加載后會將此地址賦給 ??PC/RIP?? 寄存器。

目標文件的節詳解

1. 代碼與數據節??

??節名????作用????常見屬性??
.text存儲??代碼??(函數、指令)AX(可執行、只讀)
.data存儲??已初始化的全局/靜態變量??WA(可寫、已初始化)
.bss存儲??未初始化的全局/靜態變量??(實際不占文件空間)WA(可寫、未初始化)
.rodata存儲??只讀數據??(如字符串常量、const變量)A(只讀)

鏈接后.text節和.rodata節會合并為代碼段,.data節合并為數據段,.bss節合并為bss段


??2. 符號與重定位節??

??節名????作用????鏈接階段關鍵性??
.symtab??符號表??(函數、變量名及其地址/大小)? 靜態鏈接必需
.rel.text.text節的??重定位條目??(修正代碼中的地址引用)? 必需
.rel.data.data節的??重定位條目??(修正數據中的地址引用)

? 必需

符號表的作用:

1.記錄符號定義,符號是變量還是函數,以及對應地址

2.標記未定義符號

3.輔助重定位

重定位表的作用:

目標文件中代碼和數據中對符號(函數/變量)的引用地址是臨時的。重定位表指導鏈接器如何將這些臨時地址替換為??最終的虛擬地址??。


??3.?動態鏈接相關節??(僅當啟用-fPIC編譯時存在)

??節名????作用????動態庫必需??
.got全局偏移表(Global Offset Table)? 動態庫需要
.plt過程鏈接表(Procedure Linkage Table)? 動態庫需要

靜態鏈接的?過程

??(1) 輸入文件準備??
  • ??目標文件(.o)??:含main的目標文件
  • ??靜態庫(.a)??:本質是多個目標文件的打包(通過ar工具生成),例如:ar rcs libfoo.a foo.o bar.o # 將foo.o和bar.o打包為libfoo.a
??(2) 鏈接器(ld)的工作流程??
  1. ??符號解析(Symbol Resolution)??

    • 合并所有目標文件的符號表(.symtab),檢查是否存在??未定義符號??(標記為U)。
    • ??若存在未定義符號??:直接報錯(如undefined reference to 'printf'),鏈接失敗。
  2. ??節合并(Section Merging)??

    • 將同名節(如.text.data)從不同目標文件合并為??段(Segment)??:
      • 所有.text?→ 代碼段(可執行)
      • 所有.data?→ 數據段(可讀寫)
      • 所有.bss?→ BSS段(未初始化數據,不占文件空間)
  3. ??分配虛擬地址(Address Assignment)??

    • 鏈接器為每個段分配??最終的虛擬地址??。例如:

      .text 0x400000 (代碼段基地址) .data 0x600000 (數據段基地址)

  4. ??重定位(Relocation)??

    • 根據重定位表(.rel.text/.rel.data)修正代碼和數據中對符號的引用:
      • ??修正代碼中的地址??:如call 0x0?→?call 0x400100(函數foo的最終地址)。
      • ??修正數據中的指針??:如mov rax, [0x0]?→?mov rax, [0x600020](變量var的地址)。
  5. ??生成可執行文件??

    輸出一個完整的ELF可執行文件(a.out),包含程序頭表(描述如何加載段到內存)。

動態鏈接的過程?

??1.生成可執行文件時的鏈接??

  • ??輸入文件??:
    • 目標文件(main.o
    • 動態庫(.so,如?libc.so
  • ??靜態鏈接器(ld)的操作??:
    1. ??符號解析??:檢查?main.o?中的未定義符號(如?printf)是否在動態庫的?.dynsym?中。
    2. ??生成 PLT/GOT??:
      • 在可執行文件中創建?.plt?和?.got.plt?節。
      • 將對動態庫函數的調用(如?call printf)改為?call printf@plt
    3. ??記錄依賴關系??:在可執行文件的?.dynamic?段中注明依賴的動態庫(如?libc.so.6)。

??2. 運行時動態加載流程??

??(1) 加載可執行文件??
  • ??操作系統??:
    1. 讀取可執行文件的 ??程序頭表??(Program Header Table),將代碼段(.text)和數據段(.data)映射到進程的虛擬地址空間。
    2. 從ELF頭中讀程序入口,將?PC?寄存器設為?e_entry(入口地址,通常是?_start)。
??(2) 加載動態庫??
  • ??動態鏈接器(ld.so)??:
    1. 根據 可執行文件的.dynamic?段加載所有依賴的動態庫(如?libc.so)到 ??隨機地址??(ASLR)。
    2. 重定位got表的里變量的地址,函數地址不重定位,有另一套機制

got表和plt表說明

1.當動態庫加載進地址空間,ld.so重定位got表中變量的地址,而代碼段中對動態庫中變量的訪問,編譯的指令為訪問got表中目標變量的地址,如何做到,就是mov eax【pc+偏移量】,偏移量是pc到目標變量GOT條目的偏移??

2.動態庫加載進地址空間,動態鏈接器不會重定位got表中函數項,因為

在鏈接時會符號解析,如果main.o中使用了動態庫的函數,那么調用函數的指令會從call printf被換成call printf@plt,去跳轉plt表對應函數條目

printf@plt:
? jmp func@got?; 跳轉got項
? pushq $index ? ? ? ; 壓入重定位表索引(如 printf 在 .rela.plt 中的位置)
? jmp .plt ? ? ? ? ? ; 跳轉到動態鏈接器(ld.so),重定位函數

plt表是在代碼段,因為plt是不可更改的,而got在數據段,因為函數項是要動態重定位的,got表中函數項在編譯時被編譯成plt表中對應函數條目的push指令

第一次調用庫函數時,call func@plt 跳轉plt對應函數條目,跳轉到got項,然后pushq 重定位表索引到隊列,調用動態鏈接器去重定位庫函數,將地址寫進got,然后調用函數

第二次調用庫函數,call func@plt? 跳轉plt表對應函數條目,跳轉got項,然后直接調用函數

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81990.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81990.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81990.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

PDF 文檔結構化工具對比:Marker 與 MinerU

模型訓練數據-MinerU一款Pdf轉Markdown軟件 https://codeyuan.blog.csdn.net/article/details/144315141 在當前大模型&#xff08;LLM&#xff09;和自然語言處理&#xff08;NLP&#xff09;應用快速發展的背景下&#xff0c;如何高效地將 PDF 等非結構化文檔轉換為結構化數…

shp2pgsql 導入 Shp 到 PostGIS 空間數據庫

前言 ? shp2pgsql是PostGIS自帶的命令行工具&#xff0c;用于將Shapefile文件聲稱SQL腳本導入到PostGIS空間數據庫。 1. 安裝 PostGIS 通過Application Stack Builder或者下載單獨的PostGIS包進行安裝。而shp2pgsql則是與PostGIS工具集成在一起&#xff0c;無需單獨下載。該命…

【ISP算法精粹】什么是global tone mapping和local tone mapping?

1. 簡介 全局色調映射&#xff08;Global Tone Mapping&#xff09;和局部色調映射&#xff08;Local Tone Mapping&#xff09;是高動態范圍&#xff08;HDR&#xff09;圖像處理中的兩種關鍵技術&#xff0c;用于將高動態范圍圖像的亮度值映射到標準動態范圍&#xff08;LDR…

虛擬環境中VSCode運行jupyter文件

用VS Code打開jupyter文件&#xff0c;點擊右上角 Select Kernel 在正上方會出現這個選擇框&#xff0c;選擇 Python Environment 會出來所有的虛擬環境&#xff0c;選擇要用的環境行

如何計算VLLM本地部署Qwen3-4B的GPU最小配置應該是多少?多人并發訪問本地大模型的GPU配置應該怎么分配?

本文一定要閱讀我上篇文章&#xff01;&#xff01;&#xff01; 超詳細VLLM框架部署qwen3-4B加混合推理探索&#xff01;&#xff01;&#xff01;-CSDN博客 本文是基于上篇文章遺留下的問題進行說明的。 一、本文解決的問題 問題1&#xff1a;我明明只部署了qwen3-4B的模型…

antv/g6 圖譜封裝配置(二)

繼上次實現圖譜后&#xff0c;后續發現如果要繼續加入不同樣式的圖譜實現起來太過麻煩&#xff0c;因此考慮將配置項全部提取封裝到js文件中&#xff0c;圖譜組件只專注于實現各種不同的組件&#xff0c;其中主要封裝的點就是各個節點的橫坐標&#xff08;x&#xff09;,縱坐標…

從芯片互連到機器人革命:英偉達雙線出擊,NVLink開放生態+GR00T模型定義AI計算新時代

5月19日&#xff0c;在臺灣舉辦的Computex 2025上&#xff0c;英偉達推出新技術“NVLink Fusion”&#xff0c;允許非英偉達CPU和GPU&#xff0c;同英偉達產品以及高速GPU互連技術NVLink結合使用&#xff0c;加速AI芯片連接。新技術的推出旨在保持英偉達在人工智能開發和計算領…

Qt window frame + windowTitle + windowIcon屬性(3)

文章目錄 window frame屬性window frame的概念1. window frame的影響2. 圖片演示3. 代碼演示 API接口widget.cpp&#xff08;測試代碼&#xff09; windowTitle屬性API接口問題 注意點widget.cpp&#xff08;屬性用法&#xff09; windowIcon屬性API接口啥是窗口圖標玩法1. 先…

Git 分支管理:merge、rebase、cherry-pick 的用法與規范

Git 分支管理&#xff1a;merge、rebase、cherry-pick 的用法與規范 在團隊開發和個人項目中&#xff0c;合理管理 Git 分支至關重要。merge、rebase 和 cherry-pick 是最常用的三種分支操作命令。本文將介紹它們的基本用法、適用場景及最佳實踐規范&#xff0c;幫助大家更高效…

VR全景制作方法都有哪些?需要注意什么?

VR全景制作是將線下實景場景轉化為具有沉浸式體驗的全景圖像的相關技術流程。通過圖像處理和軟件拼接等手段及技術&#xff0c;可以制作出VR全景圖。后面&#xff0c;我們科普詳細的VR全景制作方法指南&#xff0c;順便介紹眾趣科技在相關領域提供的支持方案。 選定拍攝地點與準…

計算機系統結構1-3章節 期末背誦內容

Amdahl定律: 加快某部件執行速度所能獲得的系統性能加速比&#xff0c;受限于該部件的執行時間占系統中總執行時間的百分比。 加速比依賴于: 可改進比例&#xff1a;在改進前的系統中&#xff0c;可改進部分的執行時間在總的執行時間中所占的比例。 部件加速比&#xff1a;可改…

JS實現直接下載PDF文件

pdf文件通過a標簽直接下載會打開頁面&#xff0c;所以&#xff0c;請求該文件的blob文件流數據&#xff0c;再通過window.URL.createObjectURL轉成鏈接&#xff0c;就可以直接下載了。 只需要替換url和文件名稱就行&#xff0c;文件名的后綴記得要寫上pdf&#xff0c;不然會變成…

深度解析Pytest中Fixture機制與實戰案例

一、為什么我們需要Fixture&#xff1f; 在某次金融系統重構項目中&#xff0c;我們的測試團隊曾遇到這樣的困境&#xff1a;隨著測試用例增長到500&#xff0c;使用unittest框架編寫的測試代碼出現了嚴重的維護問題——setup方法臃腫不堪&#xff0c;測試數據混亂&#xff0c…

文檔結構化專家:數字化轉型的核心力量

文檔結構化專家:定義、職責與行業應用的全方位解析 一、文檔結構化的定義與核心價值 文檔結構化是將非結構化或半結構化文檔(如文本、圖像、表格)轉換為計算機可處理的規范化數據形式的過程。其核心在于通過語義解析、信息單元劃分和標準化格式(如XML/JSON),實現信息的…

Linux系統管理與編程16番外篇:PXE自動化安裝部署OpenEuler24.03LTS

蘭生幽谷&#xff0c;不為莫服而不芳&#xff1b; 君子行義&#xff0c;不為莫知而止休。 Preboot Execution Environment 本機服務器操作系統&#xff1a;CentOS7.9.2207 目標服務器安裝系統&#xff1a;openEuler-24.03-LTS-SP1-everything-x86_64-dvd.iso 虛擬機&#xff1…

Enhanced RTMP H.265(HEVC)技術規格解析:流媒體協議的新突破

Enhanced RTMP H.265&#xff08;HEVC&#xff09;技術規格解析&#xff1a;流媒體協議的新突破 “每一幀畫面都是時間的映射&#xff0c;壓縮之后的靈魂&#xff0c;依然能栩栩如生。” 隨著流媒體技術的快速發展&#xff0c;視頻編碼標準不斷推陳出新。H.264/AVC雖然已經成為…

Visual Studio Code 改成中文模式(漢化)

1、打開工具軟件&#xff08;雙擊打開&#xff09; 2、軟件左邊圖標點開 3、在搜索框&#xff0c;搜索 chinese 出現的第一個 就是簡體中文 4、點擊第一個簡體中文&#xff0c;右邊會出來基本信息 點擊 install 就可以安裝了&#xff08;記得聯網&#xff09;。 5、安裝完右…

Linux--初識文件系統fd

01. C/系統調用文件操作 C/系統調用文件操作 02. 文件系統(ext2)結構 Linux ext2文件系統&#xff0c;上圖為磁盤文件系統圖&#xff08;內核內存映像肯定有所不同&#xff09;&#xff0c;磁盤是典型的塊設備&#xff0c;硬盤分區被劃分為一個個的block。一個塊的大小(有1MB,…

算法中的數學:歐拉函數

1.相關定義 互質&#xff1a;a與b的最大公約數為1 歐拉函數&#xff1a;在1~n中&#xff0c;與n互質的數的個數就是歐拉函數的值 eg&#xff1a; n1時&#xff0c;歐拉函數的值為1&#xff0c;因為1和1是互質的 n2是&#xff0c;值為2&#xff0c;因為1和2都是互質的 積性函數&…

BaseDao指南

1. BaseDao類 import java.sql.*;/*** 通用的工具類 ,負責連接數據&#xff0c; 執行增刪改查的通用方法*/ public class BaseDao {private Connection connection;private PreparedStatement pstm;private ResultSet rs;/*** 建立數據庫連接** return*/public Boolean getCon…