当前位置: 首页 > news >正文

目标文件的段结构及核心组件详解

目标文件(如 .o 或 .obj)是编译器生成的中间文件,其结构遵循 ELF(Linux)或 COFF(Windows)格式。以下是其核心段(Section)和关键机制的详细解析:


1. 目标文件的典型段结构

段名存储内容作用
.text可执行机器指令(函数代码)存放编译后的二进制指令(如成员函数、静态函数)
.data已初始化的全局/静态变量存储显式初始化的数据(如 int x = 5;
.bss未初始化的全局/静态变量(清零)仅记录变量大小,不占磁盘空间(运行时由系统初始化为0)
.rodata只读数据(字符串常量、虚表、RTTI)存储不可修改的数据(如 const char* str = "Hello";
.symtab符号表(函数、变量名及地址)记录符号的元信息,供链接器解析跨文件引用
.rel.text代码段的重定位信息标记 .text 中需要修正的指令(如 call 的目标地址)
.rel.data数据段的重定位信息标记 .data 中需要修正的指针(如跨文件的全局变量引用)
.debug调试信息(DWARF 格式)供调试器使用(如行号、变量类型),发布版可剥离
.eh_frame异常处理信息(栈展开)支持 C++ 异常机制(如 try/catch

2. 符号表(.symtab)详解

(1) 符号表的组成

符号表记录所有 函数、全局变量、静态变量 的信息,每条记录包含:

  • 符号名(如 _ZN7MyClass8funcEv,C++ 名称修饰后的名称)

  • 符号值(临时地址,通常是段内偏移)

  • 符号类型(函数 FUNC、数据 OBJECT、未定义 UND

  • 绑定属性(全局 GLOBAL、局部 LOCAL

  • 所属段(如 .text.data

(2) 符号表示例

bash

readelf -s example.o

输出:

Num:    Value  Size Type    Bind   Vis      Ndx Name1: 00000000    10 FUNC    GLOBAL DEFAULT    1 _ZN7MyClass8funcEv2: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND _Z3foov
  • Value=00000000:临时地址(链接后修正)。

  • Ndx=1:符号属于 .text 段(通过节头表索引确定)。

  • UND:未定义符号(需链接时解析)。

(3) 符号表的作用

  • 链接阶段:解析跨文件引用(如 main.o 调用 lib.o 的函数)。

  • 调试阶段:映射机器码到源码符号(如 addr2line 工具)。


3. 重定位表(.rel.text / .rel.data)详解

(1) 重定位的用途

  • 修正代码段(.text)和数据段(.data)中的 临时地址,使其指向正确的最终地址。

  • 解决跨文件引用问题(如调用其他 .o 文件的函数)。

(2) 重定位条目结构

每个条目包含:

  • 偏移量(Offset):需修正的指令/数据在段内的位置。

  • 类型(Type):如何修正(如绝对地址、相对偏移)。

  • 符号(Symbol):目标符号名。

(3) 重定位表示例

bash

readelf -r example.o

输出:

Relocation section '.rel.text':
OFFSET   TYPE           SYMBOL
00000005 R_X86_64_PC32  _Z3foov
  • OFFSET=0x05call 指令的操作数位于 .text 段偏移 0x05 处。

  • TYPE=R_X86_64_PC32:需修正为 相对地址(目标地址 - 下条指令地址)。

  • SYMBOL=_Z3foov:修正目标是函数 foo()

(4) 重定位过程

  1. 链接器 合并所有 .text 段,分配最终地址(如 foo() 的地址为 0x401200)。

  2. 计算修正值:

    • 对于 R_X86_64_PC32

      修正值 = 目标地址(0x401200) - 下条指令地址(0x401005 + 5 = 0x40100A) = 0x1F6
  3. 修改指令:

    asm

    ; 修正前(目标文件)
    call 0x00000000  
    ; 修正后(可执行文件)
    call 0x1F6        ; 实际编码为 E8 F6 01 00 00

4. 代码段(.text)与数据段(.data/.bss)

(1) 代码段(.text)

  • 内容:所有函数的机器码(如 main()MyClass::func())。

  • 特点

    • 只读可执行(防代码注入)。

    • 函数调用通过 call 指令实现(地址由重定位修正)。

(2) 数据段(.data)

  • 内容:已初始化的全局/静态变量(如 int x = 42;)。

  • 特点

    • 可读写,占用磁盘空间(存储初始值)。

    • 加载到内存的 数据段

(3) BSS 段(.bss)

  • 内容:未初始化的全局/静态变量(如 int y;)。

  • 特点

    • 不占用磁盘空间(仅记录大小)。

    • 运行时由系统初始化为0,加载到内存的 BSS 段


5. 动态链接的特殊处理

(1) 全局偏移表(GOT)

  • 存储动态库中符号的绝对地址(如 printf)。

  • 首次访问时由动态链接器填充。

(2) 过程链接表(PLT)

  • 实现 延迟绑定,首次调用函数时触发动态链接器解析地址。

    asm

    复制

    下载

    call printf@plt  ; 首次调用跳转到 PLT

6. 关键总结

组件作用示例工具命令
.text存储可执行指令(函数代码)objdump -d example.o
.data存储已初始化的全局/静态变量readelf -x .data example.o
.bss存储未初始化的全局/静态变量(运行时清零)size example.o
.symtab记录符号名、类型、地址(供链接器使用)readelf -s example.o
.rel.text标记代码段中需要修正的指令(如 callreadelf -r example.o
.rel.data标记数据段中需要修正的指针(如跨文件变量引用)objdump -r -j .data example.o

相关文章:

  • C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 17)
  • 【Shell 脚本编程】详细指南:第三章 - 运算符与条件判断
  • PostgreSQL:pgAdmin 4 使用教程
  • tiktok web X-Bogus X-Gnarly 分析
  • 【dify—8】Agent实战——占星师
  • L3-041 影响力
  • 艺华直播 5.0 |专注于提供港澳台及央视频道的电视直播应用,加载快,播放流畅
  • PMP-第九章 项目资源管理(一)
  • 嵌入式产品运行中数据丢失怎么办?
  • ES6异步编程中Promise与Proxy对象
  • centos7 离线安装python3 保留python2
  • 使用Set和Map解题思路
  • 25.4.30数据结构|并查集 路径压缩
  • 企业经营系统分类及功能详解
  • Java状态机实战:打造高扩展性的订单流程引擎(含源码详解与快照设计)
  • Memory Bank 不够用?Cline 全新 CRCT:省 token,依赖关系自行追踪
  • OpenGL-ES 学习(13) ---- Shader 编译和程序对象
  • 生产级RAG系统一些经验总结
  • 构建强大垂直领域AI数据能力
  • C++11新特性_自动类型推导_decltype
  • 《求是》杂志发表习近平总书记重要文章《激励新时代青年在中国式现代化建设中挺膺担当》
  • 摩根大通任命杜峯为亚太区副主席,加码中国市场业务布局
  • 深入贯彻中央八项规定精神学习教育中央指导组培训会议召开
  • 发挥全国劳模示范引领作用,加速汽车产业电智化转型
  • 探索演艺产业新路径,2万观众走进音乐科技融创节
  • 第1现场|无军用物资!伊朗港口爆炸已遇难40人伤1200人