ELF文件格式入门

简介: ELF(Executable and Linking Format),即“可执行可连接格式”,最初由 UNIX系统实验室做为应用程序二进制接口(ABI)的一部分而制定和发布。简单说就是一种文件格式。

什么是ELF

ELF(Executable and Linking Format),即“可执行可连接格式”,最初由 UNIX系统实验室做为应用程序二进制接口(ABI)的一部分而制定和发布。简单说就是一种文件格式。


ELF文件类型

(1)可重定位文件, 一般就是源文件编译生成的".o"文件,这些文件用于与其它目标文件进行链接生成可执行文件或动态链接库。

(2)共享目标文件, 即动态链接库文件, 就是".so"文件。

(3)可执行文件, 经过链接的,可以执行的程序文件。


ELF文件格式

dcf492e4d9235f21b2ebe54125b87483.png

因为ELF格式的文件有些是用来连接的,有些是可以执行的。所以上面中从“连接”和“运行”两个视角来看ELF文件的格式。

ELF文件主要由四部分组成:

(1)ELF文件头

(2)程序头表

(3)节(Section)或段

(4)节头表或段头表


1、ELF文件头

描述文件的主要特性:类型,CPU架构,入口地址,现有部分的大小和偏移等。

文件头数据结构如下:

#define EI_NIDENT  16typedefstructelf64_hdr {
unsignedchare_ident[EI_NIDENT]; //魔术字,用来确认文件是否是一个ELF文件Elf64_Halfe_type;  //文件类型,比如可重定位文件,可执行文件等Elf64_Halfe_machine; //处理器架构Elf64_Worde_version; //ELF文件格式的版本Elf64_Addre_entry;   //程序入口的虚拟地址Elf64_Offe_phoff;    //程序头表开始处在文件中的偏移量Elf64_Offe_shoff;   //节头表开始处在文件中的偏移量Elf64_Worde_flags;  //处理器特定的标志位Elf64_Halfe_ehsize; //ELF文件头的大小Elf64_Halfe_phentsize; //在程序头表中每一个表项的大小Elf64_Halfe_phnum; //程序头表中总共有多少个表项Elf64_Halfe_shentsize; //节头表中每一个表项的大小Elf64_Halfe_shnum;  //节头表中每一个表项的大小Elf64_Halfe_shstrndx; //节头表中与节名字表相对应的表项的索引} Elf64_Ehdr;


2、程序头表

程序头表就是一个数组,里面的每个元素都是一个程序头。每一个程序头描述了一个“段(segment)”。一个“段(segment)”包含一个或者多个“节(section)”。

程序头的数据结构如下:

typedefstructelf64_phdr {
Elf64_Wordp_type;   //段的类型Elf64_Wordp_flags;  //段属性,处理器特定的标志位Elf64_Offp_offset;  //段内容在文件中的位置Elf64_Addrp_vaddr;  //段内容的开始位置在进程空间中的虚拟地址Elf64_Addrp_paddr;  //段内容的开始位置在进程空间中的物理地址Elf64_Xwordp_filesz;//段内容在文件中的大小Elf64_Xwordp_memsz; //段内容在内存中的大小Elf64_Xwordp_align; //段对齐} Elf64_Phdr;

*注意: 程序头只对可执行文件或共享目标文件有意义,对于其它类型的目标文件,该信息可以忽略。


3、节头表

节头表也是一个数组。节头表的每一个表项描述了节的信息,通过每一个表项可以定位到对应的节。

节头的数据结构如下:

typedefstructelf64_shdr {
Elf64_Wordsh_name; //节的名称Elf64_Wordsh_type; //节的类型Elf64_Xwordsh_flags;//节的属性Elf64_Addrsh_addr; //执行时节的虚拟地址Elf64_Offsh_offset;//节在文件中的位置Elf64_Xwordsh_size;//节的大小Elf64_Wordsh_link; //索引值,指向节头表中本节所对应的位置Elf64_Wordsh_info; //节的附加信息Elf64_Xwordsh_addralign;//节对齐Elf64_Xwordsh_entsize;  //有一些节的内容是一张表,//其中每一个表项的大小是固定的,比如符号表。//对于这种表来说,本成员指定其每一个表项的大小。} Elf64_Shdr;


4.节(Section)

节里面就是代码和数据。比如".text", “.data” , ".rodata"等。如下图:

ed151d35f347f011535f9f44f5438e33.png

  • text : 就是存放代码的节
  • .rodata: 存放只读数据的节
  • .data: 存放读写数据的节


在 ELF文件中有一些特定的节是预定义好的,其内容是指令代码或者控制信息。比如:“.text”, “.bss”, ".data"等都是预定义的节。


应用程序也可以构造自己的段,但最好不要取与上述系统已定义的节相同的名字,也不要取以点号开头的名字,以避免潜在的冲突。


更多定义可参考下面文档:

https://paper.seebug.org/papers/Archive/refs/elf/Understanding_ELF.pdf


实例分析

我们自己写一个应用程序,然后通过readelf命令来分析elf文件。

(1)读取可执行文件的ELF文件头

readelf -h timer

06cc3b73c7d88ea5c972a3bb831fb8af.png

这些解析完的参数就是对应上面的ELF文件头的结构体。

上面的文件类型就是可执行文件。

(2)读取.o文件的ELF文件头

readelf -h timer.o

cef88e1b9d3974c72132405dacb5fb07.png

上面的文件类型为可重定位文件。

(3)读取可执行文件的程序头

readelf -l timer

590ee1b5ce12fbcd478b9100df0a7aac.png

从上面可以看到总共有9个程序头,也就有9个段。这9个段和节之间的映射关系如下:

d03be6021b70e74a0be26857f7a44c1c.png


总结

看完这些是不是觉得没什么用,好像开发中也很少用到。但如果有一天你的项目需要你写链接脚本时,可能会从中找到一些有用的东西!

相关文章
|
数据安全/隐私保护
centos8 Root用户忘记密码
centos8 Root用户忘记密码
459 0
|
C++ 开发者 编译器
C/C++经典面试50题(挑重点整理)下
重点整理了C/C++经典面试题
23538 0
|
数据安全/隐私保护 Python
Python hashlib 加密方法(MD5、SHA1、SHA256、SHA52)
Python hashlib 加密方法(MD5、SHA1、SHA256、SHA52)
787 0
|
7月前
|
关系型数据库 数据库 Docker
Docker Compose 实战指南:多容器应用的一站式部署解决方案
大家好,我是D枫。随着容器化普及,单个Docker已难满足复杂应用需求。Docker Compose通过一个YAML文件定义多容器服务,实现一键启动、停止与配置管理,彻底解决环境不一致、操作繁琐和依赖混乱问题。本文带你深入理解其核心原理,实战搭建Flask+MySQL应用,掌握高效开发利器。
939 1
|
测试技术
软件复杂度量化:McCabe度量法及其环路复杂度的计算方法
McCabe度量法(McCabe's Cyclomatic Complexity)是一种经典的方法,用于度量软件程序的复杂度。通过计算程序中独立路径的数量,帮助开发人员评估代码的维护难度和测试覆盖率。本文详细介绍了McCabe度量法的原理、计算方法及其在实际应用中的作用。
3320 0
|
测试技术 开发工具 文件存储
Git Stash
【8月更文挑战第27天】
888 6
go配置镜像(阿里云、七牛)
go配置镜像(阿里云、七牛)
2146 1
|
机器学习/深度学习 自然语言处理 机器人
【RAG实践】Rerank,让RAG更近一步
本文主要关注在Rerank,本文中,Rerank可以在不牺牲准确性的情况下加速LLM的查询(实际上可能提高准确率),Rerank通过从上下文中删除不相关的节点,重新排序相关节点来实现这一点。
增强现实(AR)技术在文化遗产保护与传承中的应用创新
增强现实(AR)技术在文化遗产保护与传承中的应用创新