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

ELF 文件操作手册

目录

一、ELF 文件结构概述

二、查看 ELF 文件头信息

1、命令选项

2、示例输出

3、内核数据结构

三、ELF 程序头表

1、命令选项

2、示例输出

3、关键说明

4、内核数据结构

四、ELF 节头表详解

查看节头表信息

1、命令选项

2、示例输出

3、标志说明

4、重要节说明

5、内核数据结构

五、查看节内容

1、反汇编节内容

2、查看目标文件节内容

关键说明


一、ELF 文件结构概述

        ELF (Executable and Linkable Format) 是 Unix/Linux 系统中可执行文件、目标文件和共享库的标准文件格式。


二、查看 ELF 文件头信息

1、命令选项

-h 或 --file-header:显示 ELF 文件的文件头信息。文件头包含了 ELF 文件的基本信息,包括:

  • 文件类型

  • 机器类型

  • 版本信息

  • 入口点地址

  • 程序头表和节头表的位置和大小等

2、示例输出

$ readelf -h mainELF Header:Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class:                             ELF64Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              EXEC (Executable file)Machine:                           Advanced Micro Devices X86-64Version:                           0x1Entry point address:               0x400640Start of program headers:          64 (bytes into file)Start of section headers:          7048 (bytes into file)Flags:                             0x0Size of this header:               64 (bytes)Size of program headers:           56 (bytes)Number of program headers:         9Size of section headers:           64 (bytes)Number of section headers:         31Section header string table index: 30

3、内核数据结构

Linux 内核中 ELF 头部的相关定义(位于 /linux/include/elf.h):

/* 32位 ELF 头 */
typedef struct elf32_hdr {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;/* 64位 ELF 头 */
typedef struct elf64_hdr {unsigned char e_ident[EI_NIDENT]; /* ELF 魔数 */Elf64_Half e_type;Elf64_Half e_machine;Elf64_Word e_version;Elf64_Addr e_entry;   /* 入口点虚拟地址 */Elf64_Off e_phoff;    /* 程序头表文件偏移 */Elf64_Off e_shoff;    /* 节头表文件偏移 */Elf64_Word e_flags;Elf64_Half e_ehsize;Elf64_Half e_phentsize;Elf64_Half e_phnum;Elf64_Half e_shentsize;Elf64_Half e_shnum;Elf64_Half e_shstrndx;
} Elf64_Ehdr;

三、ELF 程序头表

1、命令选项

    -l 或 --program-headers:显示 ELF 文件的程序头部(段头)信息。这些信息对于理解可执行文件在内存中的布局和加载过程非常重要。

2、示例输出

$ readelf -l mainElf file type is EXEC (Executable file)
Entry point 0x400640
There are 9 program headers, starting at offset 64Program Headers:Type           Offset             VirtAddr           PhysAddrFileSiz            MemSiz              Flags  AlignPHDR           0x0000000000000040 0x0000000000400040 0x00000000004000400x00000000000001f8 0x00000000000001f8  R E    8INTERP         0x0000000000000238 0x0000000000400238 0x00000000004002380x000000000000001c 0x000000000000001c  R      1[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]LOAD           0x0000000000000000 0x0000000000400000 0x00000000004000000x0000000000000d24 0x0000000000000d24  R E    200000LOAD           0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x0000000000000254 0x0000000000000258  RW     200000DYNAMIC        0x0000000000000e28 0x0000000000600e28 0x0000000000600e280x00000000000001d0 0x00000000000001d0  RW     8NOTE           0x0000000000000254 0x0000000000400254 0x00000000004002540x0000000000000044 0x0000000000000044  R      4GNU_EH_FRAME   0x0000000000000b34 0x0000000000400b34 0x0000000000400b340x000000000000005c 0x000000000000005c  R      4GNU_STACK      0x0000000000000000 0x0000000000000000 0x00000000000000000x0000000000000000 0x0000000000000000  RW     10GNU_RELRO      0x0000000000000e10 0x0000000000600e10 0x0000000000600e100x00000000000001f0 0x00000000000001f0  R      1Section to Segment mapping:Segment Sections...00     01     .interp 02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 04     .dynamic 05     .note.ABI-tag .note.gnu.build-id 06     .eh_frame_hdr 07     08     .init_array .fini_array .jcr .dynamic .got

3、关键说明

  1. PhysAddr:在现代操作系统中,物理地址字段通常可以忽略

  2. LOAD:并非所有的节(section)都需要加载到内存,只有标记为 LOAD 的段(segment)才会被加载

4、内核数据结构

/* 32位程序头 */
typedef struct elf32_phdr {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;/* 64位程序头 */
typedef struct elf64_phdr {Elf64_Word p_type;Elf64_Word p_flags;Elf64_Off p_offset;   /* 段在文件中的偏移 */Elf64_Addr p_vaddr;   /* 段虚拟地址 */Elf64_Addr p_paddr;   /* 段物理地址 */Elf64_Xword p_filesz; /* 段在文件中的大小 */Elf64_Xword p_memsz;  /* 段在内存中的大小 */Elf64_Xword p_align;  /* 段对齐方式 */
} Elf64_Phdr;

四、ELF 节头表详解

查看节头表信息

1、命令选项

    -S 或 --section-headers:显示 ELF 文件的节头信息,包括各节的起始地址、大小、标志等重要属性。

2、示例输出

$ readelf -S mainThere are 31 section headers, starting at offset 0x1b88:Section Headers:[Nr] Name              Type            Address          OffsetSize              EntSize          Flags  Link  Info  Align[ 0]                   NULL            0000000000000000  000000000000000000000000  0000000000000000           0     0     0[ 1] .interp           PROGBITS        0000000000400238  00000238000000000000001c  0000000000000000   A       0     0     1[ 2] .note.ABI-tag     NOTE            0000000000400254  000002540000000000000020  0000000000000000   A       0     0     4[ 3] .note.gnu.build-i NOTE            0000000000400274  000002740000000000000024  0000000000000000   A       0     0     4[ 4] .gnu.hash         GNU_HASH        0000000000400298  00000298000000000000001c  0000000000000000   A       5     0     8[ 5] .dynsym           DYNSYM          00000000004002b8  000002b80000000000000108  0000000000000018   A       6     1     8[ 6] .dynstr           STRTAB          00000000004003c0  000003c00000000000000076  0000000000000000   A       0     0     1[ 7] .gnu.version      VERSYM          0000000000400436  000004360000000000000016  0000000000000002   A       5     0     2[ 8] .gnu.version_r    VERNEED         0000000000400450  000004500000000000000030  0000000000000000   A       6     1     8[ 9] .rela.dyn         RELA            0000000000400480  000004800000000000000018  0000000000000018   A       5     0     8[10] .rela.plt         RELA            0000000000400498  0000049800000000000000d8  0000000000000018  AI       5    24     8[11] .init             PROGBITS        0000000000400570  00000570000000000000001a  0000000000000000  AX       0     0     4[12] .plt              PROGBITS        0000000000400590  0000059000000000000000a0  0000000000000010  AX       0     0     16[13] .plt.got          PROGBITS        0000000000400630  000006300000000000000008  0000000000000000  AX       0     0     8[14] .text             PROGBITS        0000000000400640  0000064000000000000004b2  0000000000000000  AX       0     0     16[15] .fini             PROGBITS        0000000000400af4  00000af40000000000000009  0000000000000000  AX       0     0     4[16] .rodata           PROGBITS        0000000000400b00  00000b000000000000000032  0000000000000000   A       0     0     8[17] .eh_frame_hdr     PROGBITS        0000000000400b34  00000b34000000000000005c  0000000000000000   A       0     0     4[18] .eh_frame         PROGBITS        0000000000400b90  00000b900000000000000194  0000000000000000   A       0     0     8[19] .init_array       INIT_ARRAY      0000000000600e10  00000e100000000000000008  0000000000000008  WA       0     0     8[20] .fini_array       FINI_ARRAY      0000000000600e18  00000e180000000000000008  0000000000000008  WA       0     0     8[21] .jcr              PROGBITS        0000000000600e20  00000e200000000000000008  0000000000000000  WA       0     0     8[22] .dynamic          DYNAMIC         0000000000600e28  00000e2800000000000001d0  0000000000000010  WA       6     0     8[23] .got              PROGBITS        0000000000600ff8  00000ff80000000000000008  0000000000000008  WA       0     0     8[24] .got.plt          PROGBITS        0000000000601000  000010000000000000000060  0000000000000008  WA       0     0     8[25] .data             PROGBITS        0000000000601060  000010600000000000000004  0000000000000000  WA       0     0     1[26] .bss              NOBITS          0000000000601064  000010640000000000000004  0000000000000000  WA       0     0     1[27] .comment          PROGBITS        0000000000000000  00001064000000000000002d  0000000000000001  MS       0     0     1[28] .symtab           SYMTAB          0000000000000000  000010980000000000000750  0000000000000018          29    49     8[29] .strtab           STRTAB          0000000000000000  000017e80000000000000291  0000000000000000           0     0     1[30] .shstrtab         STRTAB          0000000000000000  00001a79000000000000010c  0000000000000000           0     0     1

3、标志说明

  • W (write)    - 可写
  • A (alloc)    - 运行时分配内存
  • X (execute)  - 可执行
  • M (merge)    - 可合并
  • S (strings)  - 包含字符串
  • I (info)     - 额外信息
  • L (link order) - 保留链接顺序
  • O (extra OS processing required) - 需要特殊处理
  • G (group)    - 组成员
  • T (TLS)      - 线程局部存储
  • C (compressed) - 压缩数据
  • x (unknown)  - 未知
  • o (OS specific) - 操作系统特定
  • E (exclude)  - 排除
  • l (large)    - 大型节
  • p (processor specific) - 处理器特定

4、重要节说明

  • .got:全局偏移表(Global Offset Table),用于动态链接

  • .plt:过程链接表(Procedure Linkage Table),支持延迟绑定

  • .text:包含程序的可执行指令

  • .data:包含初始化的全局变量

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

5、内核数据结构

/* 32位节头 */
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;/* 64位节头 */
typedef struct elf64_shdr {Elf64_Word  sh_name;      /* 节名称索引 */Elf64_Word  sh_type;      /* 节类型 */Elf64_Xword sh_flags;     /* 节标志 */Elf64_Addr  sh_addr;      /* 节虚拟地址 */Elf64_Off   sh_offset;    /* 节文件偏移 */Elf64_Xword sh_size;      /* 节大小 */Elf64_Word  sh_link;      /* 相关节索引 */Elf64_Word  sh_info;      /* 附加信息 */Elf64_Xword sh_addralign; /* 节对齐要求 */Elf64_Xword sh_entsize;   /* 表项大小(如有) */
} Elf64_Shdr;

五、查看节内容

1、反汇编节内容

$ objdump -S mainmain:     file format elf64-x86-64Disassembly of section .init:0000000000400570 <_init>:400570:       48 83 ec 08             sub    $0x8,%rsp400574:       48 8b 05 7d 0a 20 00    mov    0x200a7d(%rip),%rax        # 600ff8 <__gmon_start__>40057b:       48 85 c0                test   %rax,%rax40057e:       74 05                   je     400585 <_init+0x15>400580:       e8 ab 00 00 00          callq  400630 <.plt.got>400585:       48 83 c4 08             add    $0x8,%rsp400589:       c3                      retqDisassembly of section .plt:0000000000400590 <.plt>:400590:       ff 35 72 0a 20 00       pushq  0x200a72(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x8>400596:       ff 25 74 0a 20 00       jmpq   *0x200a74(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x10>40059c:       0f 1f 40 00             nopl   0x0(%rax)00000000004005a0 <write@plt>:4005a0:       ff 25 72 0a 20 00       jmpq   *0x200a72(%rip)        # 601018 <write@GLIBC_2.2.5>4005a6:       68 00 00 00 00          pushq  $0x04005ab:       e9 e0 ff ff ff          jmpq   400590 <.plt>00000000004005b0 <printf@plt>:4005b0:       ff 25 6a 0a 20 00       jmpq   *0x200a6a(%rip)        # 601020 <printf@GLIBC_2.2.5>4005b6:       68 01 00 00 00          pushq  $0x14005bb:       e9 d0 ff ff ff          jmpq   400590 <.plt>00000000004005c0 <close@plt>:4005c0:       ff 25 62 0a 20 00       jmpq   *0x200a62(%rip)        # 601028 <close@GLIBC_2.2.5>4005c6:       68 02 00 00 00          pushq  $0x24005cb:       e9 c0 ff ff ff          jmpq   400590 <.plt>00000000004005d0 <__libc_start_main@plt>:4005d0:       ff 25 5a 0a 20 00       jmpq   *0x200a5a(%rip)        # 601030 <__libc_start_main@GLIBC_2.2.5>4005d6:       68 03 00 00 00          pushq  $0x34005db:       e9 b0 ff ff ff          jmpq   400590 <.plt>

2、查看目标文件节内容

$ objdump -d hello.ohello.o:     file format elf64-x86-64Disassembly of section .text:0000000000000000 <main>:0:   55                      push   %rbp1:   48 89 e5                mov    %rsp,%rbp4:   bf 00 00 00 00          mov    $0x0,%edi9:   e8 00 00 00 00          callq  e <main+0xe>e:   b8 00 00 00 00          mov    $0x0,%eax13:   e8 00 00 00 00          callq  18 <main+0x18>18:   b8 00 00 00 00          mov    $0x0,%eax1d:   5d                      pop    %rbp1e:   c3                      retq

关键说明

  1. .init:程序初始化代码

  2. .plt:动态链接跳转表

  3. .text:主程序代码

  4. 目标文件中的地址在链接前为0,链接后会填充实际地址

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

相关文章:

  • Java 动态导出 Word 登记表:多人员、分页、动态表格的最佳实践
  • C++11--锁分析
  • ospf技术
  • 【SpringAI实战】实现仿DeepSeek页面对话机器人
  • Jiasou TideFlow AIGC SEO Agent:全自动外链构建技术重构智能营销新标准
  • 技术与情感交织的一生 (十)
  • Spring处理器和Bean的生命周期
  • LinkedList与链表(单向)(Java实现)
  • 【2025/07/21】GitHub 今日热门项目
  • WinForm-免费,可商用的WinForm UI框架推荐
  • Linux 命令大全
  • Three.js实现银河流光粒子星空特效原理与实践
  • 【Android】交叉编译faiss库 | 问题解决
  • 【HarmonyOS】ArkTS语法详细解析
  • C++ <继承> 详解
  • Java IO流体系详解:字节流、字符流与NIO/BIO对比及文件拷贝实践
  • kafka 生产和消费 性能测试工具 kafka-producer-perf-test.sh kafka-consumer-perf-test.sh
  • 安装docker可视化工具 Portainer中文版(ubuntu上演示,所有docker通用) 支持控制各种容器,容器操作简单化 降低容器门槛
  • 2025最新版IntelliJ IDEA Ultimate for Mac专业版安装使用指南
  • C#最佳实践:为何应尽量减少静态类的使用
  • 【PTA数据结构 | C语言版】旅游规划
  • WSL如何安装docker?
  • 基于ArcFace损失函数训练的人脸特征提取模型
  • nextjs+react接口会请求两次?
  • UART串口
  • 【Git#6】多人协作 企业级开发模型
  • 多线程Python爬虫:加速大规模学术文献采集
  • 前端之学习后端java小白(一)之SDKMAN及helloword
  • 【深度学习新浪潮】如何系统性地学习扩散模型?
  • 影刀 RPA:批量修改 Word 文档格式,高效便捷省时省力