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

Linux中ELF区域与文件偏移量的关系

        ELF(Executable and Linkable Format)是Linux系统中可执行文件、目标文件和共享库的标准格式。理解ELF文件中各个区域与文件偏移量之间的关系对于程序分析、调试和逆向工程至关重要。

目录

一、ELF文件基本结构

二、关键概念:虚拟地址(VMA) vs 文件偏移量(Offset)

三、ELF头与文件偏移量

四、程序头表与段(Segments)

五、节头表与节(Sections)

六、常见节区及其偏移量关系

七、地址转换示例

八、使用工具查看ELF信息

九、实际应用场景


一、ELF文件基本结构

ELF文件由以下几部分组成:

  1. ELF头(ELF Header)

  2. 程序头表(Program Header Table) - 用于程序加载

  3. 节头表(Section Header Table) - 用于链接和调试

  4. 各种节(Sections)和段(Segments)


二、关键概念:虚拟地址(VMA) vs 文件偏移量(Offset)

  • 文件偏移量(Offset): 指数据在ELF文件中的物理位置,从文件开始计算的字节数

  • 虚拟地址(VMA, Virtual Memory Address): 指该数据在进程虚拟地址空间中的位置

  • 加载地址(LMA, Load Memory Address): 指数据在物理内存中的位置(通常与VMA相同)


三、ELF头与文件偏移量

ELF头总是位于文件的起始位置(偏移量0),包含以下关键信息:

#define EI_NIDENT 16typedef struct {unsigned char e_ident[EI_NIDENT];Elf32_Half    e_type;Elf32_Half    e_machine;Elf32_Word    e_version;Elf32_Addr    e_entry;Elf32_Off     e_phoff;    // 程序头表文件偏移量Elf32_Off     e_shoff;    // 节头表文件偏移量Elf32_Word    e_flags;Elf32_Half    e_ehsize;Elf32_Half    e_phentsize;Elf32_Half    e_phnum;Elf32_Half    e_shentsize;Elf32_Half    e_shnum;Elf32_Half    e_shstrndx;
} Elf32_Ehdr;
  • e_phoff: 程序头表在文件中的偏移量

  • e_shoff: 节头表在文件中的偏移量


四、程序头表与段(Segments)

程序头表描述了如何将文件映射到进程地址空间,每个条目(程序头)描述一个段:

typedef struct {Elf32_Word p_type;   // 段类型Elf32_Off  p_offset; // 段在文件中的偏移量Elf32_Addr p_vaddr;  // 段的虚拟地址Elf32_Addr p_paddr;  // 段的物理地址Elf32_Word p_filesz; // 段在文件中的大小Elf32_Word p_memsz;  // 段在内存中的大小Elf32_Word p_flags;  // 段权限标志Elf32_Word p_align;  // 段对齐方式
} Elf32_Phdr;

关键字段关系:

  • p_offset → 文件偏移量

  • p_vaddr → 虚拟地址

  • 运行时加载器会将p_offset处的p_filesz字节数据映射到p_vaddr地址


五、节头表与节(Sections)

节头表描述了文件中的各个节,主要用于链接和调试:

typedef struct {Elf32_Word sh_name;      // 节名称字符串表索引Elf32_Word sh_type;      // 节类型Elf32_Word sh_flags;     // 节标志Elf32_Addr sh_addr;      // 节在内存中的地址Elf32_Off  sh_offset;    // 节在文件中的偏移量Elf32_Word sh_size;      // 节大小Elf32_Word sh_link;      // 链接到其他节Elf32_Word sh_info;      // 附加信息Elf32_Word sh_addralign; // 节对齐要求Elf32_Word sh_entsize;   // 条目大小(如果有)
} Elf32_Shdr;

关键字段关系:

  • sh_offset → 文件偏移量

  • sh_addr → 虚拟地址(如果该节会被加载到内存)


六、常见节区及其偏移量关系

以下是典型ELF文件中的常见节区及其与文件偏移量的关系:

  1. .text节: 包含可执行代码

    • sh_offset: 代码在文件中的位置

    • sh_addr: 代码在内存中的虚拟地址

  2. .data节: 包含已初始化的全局变量

    • sh_offset: 数据在文件中的位置

    • sh_addr: 数据在内存中的虚拟地址

  3. .bss节: 包含未初始化的全局变量

    • sh_offset: 通常为0(因为.bss不占用文件空间)

    • sh_addr: 内存中的虚拟地址

    • sh_size: 需要在内存中分配的大小

  4. .rodata节: 只读数据

    • sh_offset: 只读数据在文件中的位置

    • sh_addr: 只读数据在内存中的虚拟地址

  5. .symtab/.strtab节: 符号表和字符串表

    • sh_offset: 符号信息在文件中的位置

    • sh_addr: 通常为0(这些节不会被加载到内存)


七、地址转换示例

假设一个简单的ELF文件布局:

文件偏移量   内容
0x000       ELF头
0x034       程序头表
0x100       .text节 (文件大小0x200)
0x300       .data节 (文件大小0x100)
0x400       节头表

对应的程序头可能如下:

p_type=PT_LOAD, p_offset=0x100, p_vaddr=0x08048000, p_filesz=0x200, p_memsz=0x200
p_type=PT_LOAD, p_offset=0x300, p_vaddr=0x08049000, p_filesz=0x100, p_memsz=0x120

地址转换关系:

  • 文件偏移0x100处的代码 → 虚拟地址0x08048000

  • 文件偏移0x300处的数据 → 虚拟地址0x08049000


八、使用工具查看ELF信息

  1. readelf: 查看ELF文件结构

    readelf -h file    # 查看ELF头
    readelf -l file    # 查看程序头
    readelf -S file    # 查看节头
  2. objdump: 反汇编和查看节信息

    objdump -h file    # 查看节信息
    objdump -d file    # 反汇编代码
  3. nm: 查看符号表

    nm file

九、实际应用场景

  1. 调试器使用: 调试器需要将虚拟地址转换为文件偏移量来定位源代码

  2. 二进制补丁: 修改文件时需要知道要修改的数据在文件中的位置

  3. 动态链接: 动态链接器需要解析重定位信息,涉及地址计算

  4. 核心转储分析: 将核心文件中的地址映射回原始文件位置

        理解ELF区域与文件偏移量之间的关系是Linux系统编程和逆向工程的基础知识,对于深入理解程序加载和执行过程至关重要。

http://www.xdnf.cn/news/1165249.html

相关文章:

  • 【牛客算法】小美的排列询问
  • DL00691-基于深度学习的轴承表面缺陷目标检测含源码python
  • Python可迭代归约函数深度解析:从all到sorted的进阶指南
  • scratch音乐会开幕倒计时 2025年6月中国电子学会图形化编程 少儿编程 scratch编程等级考试一级真题和答案解析
  • docker 软件bug 误导他人 笔记
  • Linux网络信息(含ssh服务和rsync)
  • 微信二维码扫描登录流程详解
  • 网络编程之 UDP:用户数据报协议详解与实战
  • 嵌入式八股文之 struct 和 union 的区别、大厂真题1、头文件中的#ifdef/#define/#endif作用是什么?
  • React探索高性能Tree树组件实现——react-window、react-vtree
  • Kafka 如何优雅实现 Varint 和 ZigZag 编码
  • AXI接口学习
  • 在github上搭建自己主页
  • Spring Boot 3核心技术面试指南:从迁移升级到云原生实战,9轮技术攻防(含架构解析)
  • 添加状态信息
  • Linux find命令:强大的文件搜索工具
  • 代码审计Tabby安装教程
  • 神经网络——归一化层
  • nextjs编程式跳转
  • LinkedList的模拟实现(双向链表Java)
  • Java注解家族--`@ResponseBody`
  • 神经网络——线性层
  • 【c++】leetcode5 最长回文子串
  • 蚂蚁数科AI数据产业基地正式投产,携手苏州推进AI产业落地
  • 奥比中光深度相机开发
  • 感知机-梯度下降法
  • 141 个 LangChain4j Maven 组件分类解析、多场景实战攻略
  • 一个月掌握数据结构与算法:高效学习计划
  • hot100回归复习(算法总结1-38)
  • 零拷贝技术(Zero-Copy)