【ELF系列】一文手撕ELF文件

news/2024/11/15 14:06:07/文章来源:https://www.cnblogs.com/o-O-oO/p/18394327
一、ELF文件是什么二、ELF可重定位文件2.1 .shstrtab和.strtab2.2 .rel.text和.symtab2.3 .text节三、ELF可执行文件四、 参考

原创 嵌入一下? 谦益行

在一文了解ECU软件刷写文件HEX和S19格式 (qq.com)中介绍汽车控制器的刷写软件的格式,不管是编译生成的目标软件格式是哪种,同时都会生成ELF文件,ELF文件是什么?下文将进行详细介绍:

一、ELF文件是什么

ELF(Executable Linkble Format)是一种Unix-like系统上的二进制文件格式标准。
ELF标准中定义的采用 ELF 格式的文件分为4类:

ELF文件格式提供了两种不同的视角,在汇编器和链接器看来,ELF文件是由Section Header Table描述的一系列Section的集合;而执行一个ELF文件时,在加载器(Loader)看来,它是由Program Header Table描述的一系列Segment的集合 ,如下所示:

左边是从汇编器和链接器的视角来看这个文件,开头的 ELF Header 描述了体系结构和操作系统等基本信息,并指出 Section Header Table 和 Program Header Table 在文件中的什么位置,Program Header Table在汇编和链接过程中没有用到,所以是可有可无的,Section Header Table 中保存了所有 Section 的描述信息。

右边是从加载器的视角来看这个文件,开头是 ELF Header,Program Header Table 中保存了所有 Segment 的描述信息,Section Header Table 在加载过程中没有用到,所以是可有可无的。注意 Section Header Table 和 Program Header Table 并不是一定要位于文件开头和结尾的,其位置由 ELF Header 指出,上图这么画只是为了清晰。

我们在汇编程序中用 .section 声明的 Section 会成为目标文件中的Section,此外汇编器还会自动添加一些 Section(比如符号表)。

Segment 是指在程序运行时加载到内存的具有相同属性的区域,由一个或多个 Section 组成,比如有两个 Section 都要求加载到内存后可读可写,就属于同一个 Segment。有些 Section 只对汇编器和链接器有意义,在运行时用不到,也不需要加载到内存,那么就不属于任何Segment。

目标文件需要链接器做进一步处理,所以一定有 Section Header Table;可执行文件需要加载运行,所以一定有 Program Header Table;而共享库既要加载运行,又要在加载时做动态链接,所以既有Section Header Table 又有 Program Header Table。

二、ELF可重定位文件

下面用 readelf 工具读出目标文件 max.o 的 ELF Header 和 Section Header Table,然后我们逐段分析。

接下来我们来看 Section Header Table 格式

从 Section Header 中读出各 Section 的描述信息,其中:

.text 和 .data 是我们在汇编程序中声明的 Section,而其它 Section 是汇编器自动添加的。

Addr是这些段加载到内存中的地址(我们讲过程序中的地址都是虚拟地址),加载地址要在链接时填写,现在空缺,所以是全0。

Off和Size两列指出了各Section的文件地址,比如.data从文件地址0x60开始,一共0x38个字节,回去翻一下程序,.data中定义了14个4字节的整数,一共是56个字节,也就是0x38个。

根据以上信息可以描绘出整个目标文件的布局。

这个文件不大,我们直接用hexdump或者使用010 Editor工具把目标文件的字节全部打印出来看,如下所示:

2.1 .shstrtab和.strtab

.shstrtab.strtab 这两个 Section 中存放的都是 ASCII 码:

可见 .shstrtab中保存着各Section的名字, .strtab中保存着程序中用到的符号的名字 。每个名字都是以’\0’结尾的字符串。
我们知道,C语言的全局变量如果在代码中没有初始化,就会在程序加载时用0初始化。这种数据属于.bss段,在加载时它和.data段一样都是可读可写的数据,但是在ELF文件中 .data 段需要占用一部分空间保存初始值,而 .bss 段则不需要。
也就是说,.bss 段在文件中只占一个 Section Header 而没有对应的 Section,程序加载时 .bss 段占多大内存空间在 Section Header 中描述。在我们这个例子中没有用到 .bss 段,以后我们会看到这样的例子。

2.2 .rel.text和.symtab

我们继续分析 readelf 输出的最后一部分,是从 .rel.text .symtab 这两个 Section 中读出的信息。

.rel.text 告诉链接器指令中的哪些地方需要重定位,我们在下一节讨论。

.symtab 是符号表。Ndx 列是每个符号所在的 Section 编号,例如 data_items 在第 3 个 Section 里(也就是 .data ),各 Section 的编号见 Section Header Table 。Value 列是每个符号所代表的地址,在目标文件中,符号地址都是相对于该符号所在Section的相对地址,比如 data_items 位于 .data 段的开头,所以地址是0,_start 位于 .text 段的开头,所以地址也是0,但是 start_loop 和 loop_exit 相对于 .text 段的地址就不是0了。从 Bind 这一列可以看出 _start 这个符号是 GLOBAL 的,而其它符号是 LOCAL 的,GLOBAL 符号是在汇编程序中用 .globl 指示声明过的符号。

2.3 .text节

通过使用 objdump 工具可以把程序中的机器指令进行反汇编(Disassemble),得到其汇编代码,如下所示:

三、ELF可执行文件

先看可执行文件header的变化:

在看section header的变化:

.text和.data的加载地址分别改成了 0x08048074 和 0x080490a0 。

.bss段没有用到,所以被删掉了。

.rel.text段就是用于链接过程的,链接完了就没用了,所以也删掉了。

在看多出来的两个program header

多出来的Program Header Table描述了两个Segment的信息。

.text段和前面的 ELFHeader、Program Header Table 一起组成一个 Segment(FileSiz指出总长度是0x9e);

.data段组成另一个Segment(总长度是0x38)。

VirtAddr列指出第一个Segment加载到虚拟地址0x0804 8000(注意在x86平台上后面的PhysAddr列是没有意义的),第二个Segment加载到地址0x0804 90a0。

Flg列指出第一个Segment的访问权限是可读可执行,第二个Segment的访问权限是可读可写。

最后一列Align的值0x1000(4K)是x86平台的内存页面大小。在加载时要求文件中的一页对应内存中的一页,对应关系如下图所示。

这个可执行文件很小,总共也不超过一页大小,但是两个Segment 必须加载到内存中两个不同的页面,因为 MMU 的权限保护机制是以页为单位的,一个页面只能设置一种权限。

此外还规定每个Segment在文件页面内偏移多少加载到内存页面仍然偏移多少,比如第二个Segment在文件中的偏移是0xa0,在内存页面0x0804 9000中的偏移仍然是0xa0,所以是从0x0804 90a0开始,这样规定是为了简化链接器和加载器的实现。

从上图也可以看出.text段的加载地址应该是0x0804 8074,也正是_start符号的地址和程序的入口地址。

原来目标文件符号表中的Value都是相对地址,现在都改成绝对地址了。此外还多了三个符号 __bss_start _edata_end,这些是在链接过程中添进去的,加载器可以利用这些信息把 .bss段初始化为0
再看一下反汇编的结果:

四、 参考

[1] ELF文件详解—初步认识_code&poetry的博客-CSDN博客
[2] 词法分析、语法分析、语义分析 - JackYang - 博客园 (cnblogs.com)

本文引自:C编译过程 以及 ELF文件(学习笔记),作者: 嵌入一下?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/791759.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

wsl2+arch+个人向美化

也算是入教arch了,本来想物理机的,但是又舍不得把笔记本上的环境,刚好想着玩玩wsl2。到处缝缝补补也算是弄了个感觉能看的 最终效果图 图一内置主题图二p10k使用材料 终端直接用的是win的terminal,不是因为他善,只是我懒。喜欢捣鼓可以拿wezterm来 shell用的是on my zsh +…

Python复杂网络社区检测:并行谱聚类算法设计与多种算法应用实战研究

原文链接: https://tecdat.cn/?p=37574 原文出处:拓端数据部落公众号 分析师:Leiyun Liao 在当今的网络科学领域,复杂网络中的社区检测成为了一个至关重要的研究课题。随着信息技术的飞速发展,各种大规模网络不断涌现,如社交网络、生物网络等。准确地识别这些网络中的社…

IEC101、IEC103、IEC104、Modbus报文解析工具

一、概述国际电工委员会第57技术委员会(IEC TC57)1995年出版IEC 60870-5-101后,得到了广泛的应用。为适应网络传输,2000年IEC TC57又出版了IEC 60870-5-104:2000《远东设备及系统 第5-104部分:传输规约-采用标准传输协议集的IEC 60807-5-1网络访问》。为规范该标准的国内…

人工智能环境与编译器安装

1. 环境与编译器安装本文是为没有Python基础的同学,学习Python相关语法知识准备的1. Python环境安装 第一步:进入【Python官网】第二步:选择你的系统,如果是Windows系统直接点击下载即可,否则选项你对应的操作系统Linux/UNIX、macOS第三步:选择合适Python版本包(一般不要…

CentOS 7 docker 部署遇到内网通,外网不同 问题

问题[root@localhost ~]# systemctl status network ● network.service - LSB: Bring up/down networkingLoaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)Active: failed (Result: exit-code) since Tue 2024-09-03 14:21:22 CST; 4min 31s agoDocs…

在 PbootCMS 模板首页调用指定栏目的名称和链接

在 PbootCMS 中,可以在模板首页调用指定栏目的名称和链接。以下是具体的实现方法和示例代码。 示例代码html{pboot:sort scode=12} <p><span>[sort:name]</span><a href="[sort:link]">+更多</a> </p> {/pboot:sort}参数说明sc…

国产RFSoC 47DR/28DR/27DR核心板

采用FDW复旦微电子FMZQ28DR- RFSoC处理器,兼容Gen1 ZU28/27、Gen3 ZU48/47DR RFSoC,拥有8个RF-ADC、8个RF-DAC通道。提供完整的应用示例源代码和性能分析工具, 主要用于小尺寸、低功耗、实时处理RF系统的快速集成与应用部署,缩短产品开发周期。主要技术指标: 核心处理器…

Java基础-学习笔记16

16 线程(基础) 1. 相关概念 进程: 进程是程序的一次执行过程,或是正在运行的一个程序。是多态过程,有它自身的产生、存在和消亡的过程。(比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存看见。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新…

Rocky9怎么把网卡名由ens33修改为eth0

环境查看``` 系统环境# cat /etc/redhat-release Rocky Linux release 9.3 (Blue Onyx) # uname -a Linux RockyTemplete 5.14.0-362.18.1.el9_3.0.1.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Feb 11 13:49:23 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux修改配置文件 修改以下配置文…

章10——面向对象编程(高级部分)——代码块

代码块/初始化块与方法的区别: 无方法名、返回、参数,仅方法体。 不用通过对象或类显示调用,加载类/创建对象时隐式调用。代码块的好处:总结:在有多个构造器的类中,可以把每个构造器中都需要有的重复语句抽取出来单独作为代码块,大大提高了程序的复用性。 public class …

7-8月月报 | Apache SeaTunnel社区进展一览

各位热爱 Apache SeaTunnel 的小伙伴们,社区 7-8 月份月报来啦!这两个月项目有了哪些进展?又有谁登上了我们社区的贡献者榜单呢?快来一睹为快吧。 Merge Stars 感谢以下小伙伴上两个月为 Apache SeaTunnel 项目和社区发展所做的精彩贡献(排名不分先后):@Hisoka-X,@xxsc0…

易基因:血液Target-BS揭示靶向DNA甲基化标记水平与患者乳腺癌风险相关|Nature子刊

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 符合遗传性乳腺癌和卵巢癌(HBOC)标准的患者中,只有不到15-20%携带致病性编码基因突变,意味着可能存在其他分子机制导致这种疾病的风险增加。外周血DNA甲基化是乳腺癌(BC)风险的潜在表观遗传标记。在分子…