首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

ELF 動態鏈接核心機制:.plt、.got、.got.plt、.rel.dyn、.rel.plt 交互關係圖解

     編輯:關於C語言

ELF 動態鏈接核心機制:.plt、.got、.got.plt、.rel.dyn、.rel.plt 交互關係圖解

ELF 動態鏈接透過 PLT (Procedure Linkage Table)、GOT (Global Offset Table) 與重定位表協作,實現「首次調用解析、後續直接跳轉」的延遲綁定。本文深度剖析五大段表交互流程,以 printf 為例演示完整調用鏈路。

五大關鍵段表角色

段表全稱核心功能
.pltProcedure Linkage Table跳板代碼:每個外部函數一個條目,首次調用觸發解析,後續直接跳轉 GOT
.gotGlobal Offset Table全域變數地址表:存放本模組全域/靜態變數在進程虛擬地址空間的實際地址
.got.pltGOT for PLT函數地址表:每個外部函數一個條目,初始指向 PLT 解析桩碼,解析後更新為真實函數地址
.rel.plt / .rela.pltRelocation Table for PLTPLT 相關重定位條目:記錄符號名、類型、GOT.plt 條目偏移,供動態鏈接器解析
.rel.dyn / .rela.dynRelocation Table for Data數據相關重定位:全域變數、函數指針等非 PLT 重定位

printf 首次調用完整流程

  1. 主程式調用:call printf@plt → 跳轉至 .plt 中 printf 條目
  2. PLT 桩碼執行:
    printf@plt:
        jmp *printf@GOTPCREL(%rip)   # 間接跳轉 .got.plt[printf]
        pushq $reloc_index           # 壓入重定位索引
        jmp .plt[0]                  # 跳轉通用解析入口
  3. 初始狀態:.got.plt[printf] 指向 PLT 條目第 2、3 行(即 pushq/jmp),形成「自迴路」
  4. 動態鏈接器介入(_dl_runtime_resolve):
    • 根據重定位索引查找 .rel.plt 條目
    • 從符號表 .dynsym 獲取符號名 "printf"
    • 在共享庫鏈中搜尋 printf 定義(如 libc.so.6)
    • 計算實際虛擬地址
    • 寫入 .got.plt[printf] = 真實地址
  5. 返回執行:jmp *printf@GOTPCREL(%rip) 現指向真實 printf,直接執行

第二次調用

call printf@plt
jmp *printf@GOTPCREL(%rip)  # 直接跳轉真實 printf,零開銷

關鍵數據結構關係圖

.plt[printf] ──jmp──→ .got.plt[printf] ──(初始)──→ .plt[printf]+6 (pushq/jmp)
                                    │
                                    └─(解析後)──→ libc!printf (真實地址)

.rel.plt[printf] : { r_offset=.got.plt[printf], r_info=SYM(printf)|R_JUMP_SLOT }
.dynsym[printf]  : { st_name="printf", st_value=0, st_shndx=SHN_UNDEF }

.got vs .got.plt 職責分離

  • .got:數據引用重定位。全域變數、靜態變數、函數指針初始化。對應 .rel.dyn 重定位類型 R_GLOB_DAT / R_COPY。
  • .got.plt:函數調用重定位。外部函數地址緩存。對應 .rel.plt 重定位類型 R_JUMP_SLOT。

延遲綁定 vs 立即綁定

  • 延遲綁定(預設):LD_BIND_NOW 未設。首次調用時解析,啟動快、未用函數不解析。
  • 立即綁定:LD_BIND_NOW=1 或連結時 -z now。程式載入階段解析所有 PLT 條目,啟動慢、運行穩定、利於安全強化(RELRO)。

安全機制:RELRO (Read-Only Relocations)

  • Partial RELRO:.got 只讀,.got.plt 可寫(支援延遲綁定)
  • Full RELRO:.got + .got.plt 全部只讀(需立即綁定),防止 GOT 劫持攻擊
  • 連結旗標:-Wl,-z,relro,-z,now

實用調試指令

# 查看 PLT/GOT
readelf -r a.out           # 重定位表
readelf -s a.out | grep printf  # 動態符號表
objdump -d -j .plt a.out   # 反組譯 PLT
gdb -ex "info file" -ex "maintenance info sections" ./a.out

ELF 動態鏈接機制以「分層間接」實現模組解耦與延遲解析,.plt/.got.plt/.rel.plt 三位一體完成函數綁定,.got/.rel.dyn 處理數據重定位,配合 RELRO 強化運行時安全。透徹理解此機制,是逆向分析、效能調優、安全加固的核心前提。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved