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

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

目录

一、ELF文件基本结构

[二、关键概念:虚拟地址(VMA) vs 文件偏移量(Offset)](#二、关键概念:虚拟地址(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),包含以下关键信息:

cpp 复制代码
#define EI_NIDENT 16

typedef 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)

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

cpp 复制代码
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)

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

cpp 复制代码
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文件布局:

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

对应的程序头可能如下:

cpp 复制代码
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文件结构

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

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

    bash 复制代码
    nm file

九、实际应用场景

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

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

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

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

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

相关推荐
牛马工作号3 小时前
Mosquitto + ACME:从 Docker Compose 部署到 TLS 证书自动续期与加载
运维·docker·容器
强哥聊算力5 小时前
《算力江湖·英伟达传奇》第七集:ChatGPT出现前夜,英伟达发生了什么?
服务器·人工智能·算法·ai·chatgpt·gpu算力
Initialize-le5 小时前
Nginx 504 超时、499 一堆?网关排查法
运维·nginx
砚凝霜8 小时前
【软考信息安全】第二十二章 Web服务器安全分析与增强——Apache与IIS
服务器·前端·安全
Android系统攻城狮8 小时前
Linux Gstreamer深度解析之gst_audio_ring_buffer_delay调用流程与实战(七十二)
linux·运维·服务器·gstreamer音视频·音视频进阶
快乐的韭菜根根8 小时前
ubuntu 安装slurm并配置
linux·运维·ubuntu
数字新视界8 小时前
机房动环监控提升运维效率
大数据·服务器·数据库·动环监控系统·动力与环境监控系统
U-Mail邮件系统9 小时前
自建邮箱服务器有哪些软件?三款主流邮件服务器软件推荐
运维·服务器
倒头就睡的小比特10 小时前
Linux基础指令3
linux·服务器
Smoothcloud润云10 小时前
PyTorch推理服务模型热切换与失败回滚实战:降低版本更新中断
服务器·人工智能·pytorch·python·深度学习·gpu