ELF file basic structure

本文介绍了Linux系统中目标文件的格式ELF(Executable and Linkable Format),包括可重定位文件、可执行文件和共享目标文件。同时,还详细解释了链接的概念及其不同阶段:编译时、加载时和运行时。

简介

ELF (Executable and Linkable Format)文件,也就是在 Linux 中的目标文件格式,主要有以下三种类型

可重定位文件(Relocatable File),包含由编译器生成的代码以及数据。链接器会将它与其它目标文件链接起来从而创建可执行文件或者共享目标文件。在 Linux 系统中,这种文件的后缀一般为 .o 。

可执行文件(Executable File),就是我们通常在 Linux 中执行的程序。

共享目标文件(Shared Object File),包含代码和数据,这种文件是我们所称的库文件,一般以 .so 结尾。一般情况下,它有以下两种使用情景:

链接器(Link eDitor, ld)可能会处理它和其它可重定位文件以及共享目标文件,生成另外一个目标文件。
动态链接器(Dynamic Linker)将它与可执行文件以及其它共享目标组合在一起生成进程镜像。

目标文件由汇编器和链接器创建(这里涉及到编译器驱动程序),是文本程序的二进制形式,可以直接在处理器上运行。那些需要虚拟机才能够执行的程序 (Java) 不属于这一范围。

链接

链接(linking)是将各种代码和数据片段收集并组合成为一个单一文件的过程,这个文件可被加载(复制)到内存并执行。

链接可以执行于编译时(compile time),也就是在源代码被编译成机器码时;
也可以执行于加载时(load time),也就是在程序被加载器(loader)加载到内存并执行时;
甚至执行于运行时(run time),也就是由应用程序来执行。

在早期的计算机系统中,链接是手动执行的,而在现代系统中,链接的工作通常是由链接器来默默地处理,这一角色使得分离编译(separate compilation)成为可能。

编译器驱动程序

源程序文件都需要使用编译系统翻译成机器代码后,才能在处理机上运行。大多数编译系统提供编译器驱动程序(complier driver),它代表用户在需要时调用语言预处理器、编译器、汇编器和链接器。

静态链接|链接器将可重定位目标文件组合起来,形成一个可执行目标文件prog

上图概括了驱动程序在将main.c从ASCII码源文件翻译成可执行目标文件时的行为

驱动程序首先运行C预处理器(cpp),它将C的源程序main.c翻译成一个ASCII码的中间文件main.i:

cpp [other arguments] main.c /tmp/main.i

接下来,驱动程序运行C编译器(ccl),它将main.i翻译成一个ASCII汇编语言文件main.s:

ccl /tmp/main.i -0g [other arguments] -o /tmp/main.s

然后,驱动程序运行汇编器(as),将main.s翻译成一个可重定位目标文件(relocatable object file)main.o:

as [other arguments] -o /tmp/main.o /tmp/main.s

other arguments:其他参数

最后,运行链接器程序ld,将main.o及一些必要的系统目标文件组合起来,创建一个可执行目标文件(executable object file)prog;

ld  -o prog [system object files and args]  /tmp/main.o 

运行可执行文件

linux> ./prog

shell调用操作系统中一个叫做加载器(loader)的函数,可将可执行文件prog中的代码和数据复制到内存,然后将控制转移到这个程序的开头

文件格式

目标文件既会参与程序链接又会参与程序执行。出于方便性和效率考虑,根据过程的不同,目标文件格式提供了其内容的两种并行视图,如下

object_file_format.png

转载于:https://www.cnblogs.com/qymua/p/11206485.html

<think>我们正在讨论ELF文件(Executable and Linkable Format),这是一种用于可执行文件、目标代码、共享库和核心转储的标准文件格式。它常见于Unix和类Unix系统,如Linux。ELF文件的设计使得它既灵活又高效,能够支持不同的处理器架构、操作系统和硬件平台。 ELF文件由以下几部分组成: 1. **ELF头(ELF Header)**:位于文件开头,包含描述文件结构的基本信息,如文件类型(可执行文件、目标文件等)、目标架构、程序入口点地址以及程序头表和节区头表的位置和大小。 2. **程序头表(Program Header Table)**:描述如何将文件映射到进程的虚拟内存中。每个表项(称为程序头)对应一个段(Segment),段是运行时加载到内存中的连续区域,包含代码、数据等。程序头表在可执行文件和共享库中必须存在。 3. **节区头表(Section Header Table)**:描述文件中的节区(Sections)。节区是链接视图中的最小组织单元,包含代码、数据、符号表、重定位信息等。每个表项描述一个节区的名称、类型、地址、偏移量、大小等。节区头表在链接过程中非常重要,但在运行时可以不存在(可执行文件通常不包含节区头表)。 4. **节区数据(Section Data)**:实际存储节区内容的部分,如代码段(.text)、数据段(.data)、只读数据段(.rodata)、符号表(.symtab)、字符串表(.strtab)等。 在运行时,加载器(Loader)根据程序头表将ELF文件的各个段映射到内存中,然后执行程序。在链接时,链接器(Linker)根据节区头表将多个目标文件合并成一个可执行文件或共享库。 ELF文件的主要优点包括: - 支持动态链接(Dynamic Linking),即在程序运行时加载共享库。 - 支持位置无关代码(Position Independent Code, PIC),使共享库可以被加载到任意内存地址。 - 支持多种处理器架构(如x86, ARM, MIPS等)。 在开发过程中,我们可能会使用工具(如`readelf`, `objdump`)来查看ELF文件的结构和内容。例如,使用`readelf -h`查看ELF头,`readelf -l`查看程序头表,`readelf -S`查看节区头表。 参考引用[2]中的描述:".text的Offset是0,FileSiz是0x0,MemSiz是0xbc, VirtAddr是0x400000,Flags是R E",这表示.text段(代码段)在文件中的偏移为0,但文件大小(FileSiz)为0,这可能是描述有误。通常,代码段在文件中是有实际内容的,其文件大小(FileSiz)和内存大小(MemSiz)可能相同,也可能不同(例如,对于.bss段,内存大小大于文件大小,因为.bss段在文件中不占空间,但在内存中需要初始化为0)。 另外,引用[1]提供了一个使用Python的`pyelftools`库解析ELF文件的示例代码,它可以读取ELF文件头、程序头表和节区头表等信息。 引用[3]提到了一个错误:在下载程序时,J-Link工具找不到flash算法ELF文件。这通常是因为缺少对应芯片的下载算法文件或者路径配置不正确。需要检查J-Link的安装目录下的`Devices`目录和`JLinkDevices.xml`配置文件。 综上所述,ELF文件是类Unix系统中用于可执行文件、目标文件、共享库等的标准格式,它包含文件头、程序头表、节区头表和实际的数据(如代码、数据等)。理解ELF文件结构对于程序开发、调试和系统编程都非常重要。 §§相关问题§§ 1. ELF文件中的程序头表和节区头表有什么区别? 2. 如何查看ELF文件的具体内容? 3. ELF文件如何支持动态链接? 4. 在嵌入式开发中,为什么下载程序时需要flash算法ELF文件?</think>### ELF 文件详解 ELF(Executable and Linkable Format)是可执行与可链接格式的简称,是 Unix/Linux 系统下的标准二进制文件格式。它包含程序执行所需的所有信息,如机器指令、数据、内存布局等。ELF 文件主要有三种类型: 1. **可执行文件**(如 `/bin/ls`) 2. **共享库**(如 `.so` 文件) 3. **目标文件**(如 `.o` 文件) #### 核心结构 ELF 文件由四个关键部分组成: 1. **ELF 头(ELF Header)** 位于文件起始位置,包含文件类型、目标架构、入口地址等元数据。通过 `readelf -h` 可查看。 2. **程序头表(Program Header Table)** 描述 **运行时** 的内存布局(段/Segment),每个表项对应一个段(如代码段、数据段)。 - 例如:`.text` 段存储代码,`.data` 段存储初始化全局变量 - 加载器根据此表将文件映射到内存[^2] 3. **节区头表(Section Header Table)** 描述 **链接时** 的文件组织(节/Section),如: - `.text`:可执行代码 - `.rodata`:只读数据 - `.symtab`:符号表 - `.strtab`:字符串表 - 通过 `readelf -S` 查看 4. **节区数据(Section Data)** 实际存储代码、数据等内容。 #### 关键特性 1. **内存映射示例** 如引用[2]所述:若 `.text` 段的 `VirtAddr=0x400000`,`FileSiz=0xbc`,则加载器会将文件中 0x0~0xbc 的内容映射到内存 0x400000 处,并设置权限为可读可执行(R E)[^2]。 2. **跨平台支持** 支持 x86、ARM、RISC-V 等多种架构,通过 ELF 头中的 `e_machine` 字段标识。 3. **动态链接** 共享库(`.so`)通过动态链接在运行时加载,依赖 `.dynamic` 节和过程链接表(PLT)。 #### 常见工具 - **解析工具**: ```bash readelf -h <file> # 查看 ELF 头 objdump -d <file> # 反汇编代码段 ``` - **编程解析**: 如引用[1]所示,可用 Python 的 `pyelftools` 库解析 ELF 结构[^1]。 #### 典型问题场景 1. **开发工具报错** 如引用[3]中的 J-Link 错误 `ERROR: Error while loading flash algo ELF file`,通常因缺少芯片算法文件或路径配置错误引起[^3]。 2. **安全分析** 病毒分析中常通过修改 ELF 的入口点(`e_entry`)注入恶意代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值