Linux_ELF文件

[复制链接]
发表于 2025-8-21 14:30:35 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目录
前言: 
一、ELF文件的类型
二、ELF文件的构成格式 
1. ELF头部(ELF Header)
2. 节头表(Section Header Table)
3. 程序头表(Program Header Table)
4. 节(Sections)与段(Segments)
 三、ELF文件从形成到加载轮廓
1、ELF可执行文件形成过程
2、 可执行文件从磁盘加载到内存section的变化
1、Section与Segment的基本关系
2、合并机制与内存优化
四、明确动静态库链接和加载 
​编辑
1. 动态链接焦点原理
2. 程序启动与动态链接流程
动态链接器:
1. 位置无关代码(PIC)基础原理


前言: 

   ELF(Executable and Linkable Format):
  是Unix/Linux系统下的尺度可执行文件、目的文件和共享库格式。
  是一种文件格式的名称
  一、ELF文件的类型

ELF文件根据用途可分为以下几种主要类型:

  • ‌可重定位文件(Relocatable File)‌

    • 文件扩展名通常为.o
    • 由编译器生成,包含代码和数据但未指定绝对地点
    • 用于与其他目的文件链接生成可执行文件或共享库
    • 在Linux系统中通过gcc -c命令生成

  • ‌可执行文件(Executable File)‌

    • 通常没有特定扩展名(如Linux中的a.out)
    • 包含可直接执行的程序代码和数据
    • 由链接器处置处罚可重定位文件后生成
    • 包含程序入口点,可直接被操纵系统加载执行

  • ‌共享目的文件(Shared Object File)‌

    • 文件扩展名通常为.so
    • 包含可共享的代码和数据,用于动态链接
    • 可在两种环境下使用:

      • 链接时与其他文件链接生成新目的文件
      • 运行时与可执行文件结互助为进程映像的一部门


  • ‌焦点转储文件(Core Dump File)‌

    • 由操纵系统在程序瓦解时生成
    • 包含程序瓦解时的内存状态和寄存器信息
    • 用于调试和故障排除

类型扩展名主要用途生成方式使用场景可重定位文件.o链接编译器生成链接阶段可执行文件无/.out执行链接器生成运行阶段共享目的文件.so动态链接链接器生成链接和运行阶段焦点转储文件core调试系统生成调试阶段 二、ELF文件的构成格式 

 基本信息如图:

1. ELF头部(ELF Header)



  • 位于文件起始位置,固定巨细(32位系统52字节,64位系统64字节)
  • 包含文件的基本信息:

    • 魔数(Magic Number):0x7f 0x45 0x4c 0x46(ASCII为"ELF")
    • 文件类型(可执行/可重定位/共享库等)
    • 目的体系结构(如x86、ARM)
    • 程序入口地点(可执行文件)
    • 节头表和程序头表的位置和巨细信息

2. 节头表(Section Header Table)



  • 包含多个节头表条目,每个条目形貌一个节(section)的信息
  • 主要作用:

    • 纪录各节的名称、类型、文件偏移、巨细、读写权限等
    • 主要用于链接过程(链接视图)
    • 对于可重定位文件是必须的,对于可执行文件是可选的

3. 程序头表(Program Header Table)



  • 包含多个程序头表条目,每个条目形貌一个段(segment)的信息
  • 主要作用:

    • 形貌怎样将文件中的段加载到内存
    • 主要用于执行过程(执行视图)
    • 对于可执行文件和共享库是必须的,对于可重定位文件大概为空

4. 节(Sections)与段(Segments)



  • ‌节(Section)‌:

    • 链接视图的基本单位
    • 常见节包括:

      • .text:可执行代码
      • .data:已初始化的全局/静态变量
      • .bss:未初始化的全局/静态变量
      • .rodata:只读数据
      • .symtab:符号表
      • .strtab:字符串表
      • .rel.text/.rel.data:重定位信息


  • ‌段(Segment)‌:

    • 执行视图的基本单位
    • 由多个具有相同权限的连续节构成
    • 常见段类型:

      • LOAD:需加载到内存的段(代码段、数据段)
      • DYNAMIC:动态链接信息
      • INTERP:指定动态链接器路径10



 三、ELF文件从形成到加载轮廓

1、ELF可执行文件形成过程

- step-1:将多份 C/C++ 源代码,翻译成为⽬标 .o ⽂件
- step-2:将多份 .o ⽂件section进⾏合并

   2、 可执行文件从磁盘加载到内存section的变化

  1、Section与Segment的基本关系

  ELF文件具有双器重图特性:
  

  • ‌链接视图‌:以Section为基本单位,包含.text(代码)、.data(已初始化数据)、.bss(未初始化数据)等,主要用于链接阶段
  • ‌执行视图‌:以Segment为基本单位,由多个属性相同的Section合并而成,用于运行时加载
  关键区别:
  特性SectionSegment用途链接阶段执行阶段组织结构独立功能单元合并后的内存块表结构Section Header TableProgram Header Table必要性可执行文件可选可执行文件必须  2、合并机制与内存优化

  合并过程的焦点目的是‌淘汰内存碎片‌,进步页面使用效率:
  

  • ‌为什么要合并

    • 当代系统采用分页加载机制,典型页巨细为4KB(4096字节)
    • 示例:未合并时.text(4097B)和.data(1B)占用3页(2+1),合并后仅需2页(4098B)

  • ‌合并规则‌:

    • 相同内存属性(可读/可写/可执行)的Section会被合并8
    • 必须具有相同的加载需求(必要运行时申请空间)8
    • 典型合并模式:

      • 代码段:合并.text、.rodata等只读可执行Section
      • 数据段:合并.data、.bss等可读写Section


  • ‌程序头表(Program Header Table)作用‌:

    • 每个表项(Elf32_Phdr/Elf64_Phdr)形貌一个Segment的:

      • 类型(p_type):如PT_LOAD(需加载段)
      • 标志位(p_flags):读写执行权限
      • 文件偏移(p_offset)和巨细(p_filesz)
      • 内存地点(p_vaddr)和巨细(p_memsz)
      • 对齐要求(p_align)8

    • 加载器根据这些信息建立进程内存映像

  四、明确动静态库链接和加载 

1、静态库
下面是样例代码 


我们可以通过objdump -d 命令:将代码段(.text)进⾏反汇编查看,其中callq的加载到内存的呆板码,而后面跟着的一串0代表访问的函数地点,在链接中才会填充地点,也叫做地点重定位 


静态链接就是把库中的.o进⾏合并,和上述过程⼀样
以是链接实在就是将编译之后的全部⽬标⽂件连同⽤到的⼀些静态库运⾏时库组合,拼装成⼀个独⽴的可执⾏⽂件。其中就包括我们之前提到的地点修正,当全部模块组合在⼀起之后,链接器会根据我们的.o⽂件或者静态库中的重定位表找到那些必要被重定位的函数全局变量,从⽽修正它们的地点。这实在就是静态链接的过程
研究静态链接实在就是研究不同的.o文件是怎样链接到一起的,.o类型文件也叫做可重定位目的文件
1. 动态链接焦点原理

动态链接的本质是将链接过程推迟到程序加载时完成,这一机制实现了代码共享和内存优化。当执行一个程序时,操纵系统会执行以下关键步骤:

  • ‌程序加载‌:将程序的可执行代码和依靠的动态库加载到内存
  • ‌地点分配‌:为每个动态库动态分配内存地点(ASLR技能确保地点随机化)
  • ‌地点空间映射‌:将动态库映射到进程的地点空间
  • ‌符号解析‌:解析程序对动态库中符号的引用
动态链接的两个关键阶段:


  • ‌地点空间映射‌:通过mmap系统调用将动态库映射到进程地点空间
  • ‌符号绑定‌:通过PLT/GOT机制实现函数调用跳转
2. 程序启动与动态链接流程

C/C++程序的执行并非直接从main函数开始,而是履历以下初始化过程
阶段执行内容负责组件_start设置堆栈、初始化数据段crt0.o动态链接加载共享库、符号解析ld-linux.so__libc_start_main线程初始化、信号处置处罚glibcmain用户代码执行用户程序 详细流程:

  • ‌入口点_start‌:由C运行时库提供,建立基本执行环境
  • ‌动态链接器调用‌:通过.interp段定位ld-linux.so
  • ‌库加载与重定位‌:

    • 解析DT_NEEDED条目加载依靠库
    • 处置处罚.rel.plt和.rel.dyn重定位表

  • ‌控制权转移‌:通过__libc_start_main最终调用main函数
   动态链接器:

  
◦ 动态链接器(如ld-linux.so)负责在程序运⾏时加载动态库。
◦ 当程序启动时,动态链接器会解析程序中的动态库依靠,并加载这些库到内存中。
环境变量和设置⽂件:
◦ Linux系统通过环境变量(如LD_LIBRARY_PATH)和设置⽂件(如/etc/ld.so.conf及其⼦设置⽂件)来指定动态库的搜索路径。
◦ 这些路径会被动态链接器在加载动态库时搜索。
缓存⽂件:
◦ 为了提⾼动态库的加载效率,Linux系统会维护⼀个名为/etc/ld.so.cache的缓存⽂件。
◦ 该⽂件包含了系统中全部已知动态库的路径和相关信息,动态链接器在加载动态库时会⾸先
搜索这个缓存⽂件
  1. 位置无关代码(PIC)基础原理

位置无关代码(Position Independent Code)是动态库可以或许实现多进程共享的焦点技能,其焦点特性包括:


  • ‌地点无关性‌:代码可以在内存任意位置加载执行,无需修改指令
  • ‌相对寻址‌:全部地点引用都基于当前指令指针或全局偏移表(GOT)
  • ‌重定位延迟‌:符号解析推迟到加载或运行时完成
PIC的实现主要通过两种机制:

  • ‌PC相对寻址‌:用于函数内部跳转和局部数据访问
  • ‌全局偏移表(GOT)‌:存储外部变量和函数的绝对地点,通过间接访问实现重定位
 

基本过程

  • 通过mm_struct中的变量找到有关共享区的结构体,根据内里的成员指针变量找到路径
  • 根据路径找到磁盘中的数据块加载到内存
  • 发生映射关系关联起来
  • 得到库的起始假造地点
  • 数据区会有一个名为.GOT的表纪录库函数的偏移量,映射事后,表会根据库的起始假造地点进行修改得到完整的访问共享区的地点
 --------------------------------------------------------------------------------------------------------------------------
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表