elf文件解析以及和bin文件的区别
其实是想搞嵌入式的,但是总是要补补这里的知识补点那里的知识
1.ELF的分类
现在PC平台流行的可执行文件格式(Executable)主要是Windows下的PE和Linux的ELF,他们都是COFF格式的变种
ELF文件标准里面把系统中采用ELF格式的文件归为以下4类
ELF文件类型 | 说明 | 实例 |
---|---|---|
可重定位文件(Relocatable) | 这类文件包含了代码和数据,可以用来链接成可执行文件或共享目标文件,静态链接库也属于这一类 | Linux的.o Windows的.obj |
可执行文件(Executable) | 这类文件包含了可以直接执行的程序,它的代表就是ELF可执行文件,一般没有扩展名 | 比如/bin/bash文件 Windows的.exe |
共享目标文件(Shared Object File) | 这种文件包含了代码和数据 ,可以在以下两种情况下使用。一种是链接器可以使用这种文件跟其他的可重定位文件和共享目标文件链接,产生新的目标文件。第二种是动态连接器可以将几个这种共享目标文件与可执行文件结合,作为进程映像的一部分 | Linux的.so windows的DLL |
核心转储文件(Core dump file) | 当进程意外终止时,系统可以将该进程的地址空间的内容及终止时的一些其他信息转储到核心转储文件 | linux下的Core dump |
在linux下可以使用file命令来查看
2.ELF 文件的总体结构大概是这样的:
ELF 文件头 位于最前端,它包含了整个文件的基本属性,如文件版本,目标机器型号,程序入口等等。
.text 为代码段,也是反汇编处理的部分,他们是以机器码的形式存储,没有反汇编的过程基本不会有人读懂这些二进制代码的。
.data 数据段,保存的那些已经初始化了的全局静态变量和局部静态变量。
.bss 段, 存放的是未初始化的全局变量和局部静态变量,这个很容易理解,因为在未初始化的情况下,我们单独用一个段来保存,可以不在一开始就分配空间,而是在最终连接成可执行文件的时候,再在.bss 段分配空间。
其他段, 还有一些可选的段,比如.rodata 表示这里存储只读数据, .debug 表示调试信息等等,具体遇到可以查看相关文档。
自定义段,这一块是为了实现用户特殊功能而存在的段,方便扩展,比如我们使用全局变量或者函数之前加上 attribute(section(‘name’)) 就可以吧变量或者函数放到以name 作为段名的段中。
段表,Section Header Table ,是一个重要的部分,它描述了ELF 文件包含的所有段的信息,比如每个段的段名,段长度,在文件中的偏移,读写权限和一些段的其他属性。
ELF目标文件格式的最前端是ELF文件头,包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址。紧接着的就是ELF文件各个段。其中ELF文件中与段有关的重要结构就是段表。段表描述的是ELF文件包含的所有段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限以及段的其他属性。
分段的好处??
1.其实数据和指令分段的好处有很多,一方面是当程序被装载后,数据和指令被分别映射到两个虚存。由于数据区域对于进程来说是可读写的,而指令区域对于进程来说是只读的,所以这两个虚存区域的权限可以被分别设置成可读写和只读。这样可以防止程序的指令被有意或无意的改写。
2.对于现代cpu来说,它们有着极为强大的缓存体系,现代CPU的缓存一般都被设计成数据缓存和指令缓存分离,所以程序的指令和数据被分开存放对CPU的缓存命中率的提高有好处。
3.当系统中运行多个该程序的副本的时候,由于指令都是一样的,所以内存中只要保存一份该程序的指令。比如说很多程序的带的图标、文本、资源都可以共享。在现代操作系统中,尤其是动态链接的系统中,节省了大量的内存。
2.1文件头
以64位版本的文件头结构Elf64_Ehdr为例
85 typedef struct86 {87 unsigned char e_ident[EI_NIDENT]; /* 有6个值,分别代表不同的含义*/88 Elf64_Half e_type; /* ELF文件类型,REL */89 Elf64_Half e_machine; /* cpu平台*/90 Elf64_Word e_version; /* ELF版本号,一般为1 */91 Elf64_Addr e_entry; /*入口地址,规定ELF程序的入口虚拟地址,操作系统在加载完该程序后从这个地址开始执行进程的指令。可重定位文件一般没有入口地址,则这个值为0*/92 Elf64_Off e_phoff; /* Program header table file offset */93 Elf64_Off e_shoff; /* 段表在文件中的偏移,从下一个字节开始 */94 Elf64_Word e_flags; /*ELF标志位,用来标识一些ELF文件平台相关属性,相关常量的格式一般为EF_machine_flag*/95 Elf64_Half e_ehsize; /* ELF文件头大小 */96 Elf64_Half e_phentsize; /* Program header table entry size */97 Elf64_Half e_phnum; /* Program header table entry count */98 Elf64_Half e_shentsize; /*段表描述符大小,等于sizeof(Elf64_Shdr) */99 Elf64_Half e_shnum; /* 段表描述符数量,这个值等于ELF文件中拥有的段的数量 */100 Elf64_Half e_shstrndx; /* 段表字符串所在的段在段表中的下标 */101 } Elf64_Ehdr;
要注意的是e_ident数组包含了6个成员,Magic、类别、数据、版本、OS/ABI、ABI版本
Magic中的16个字节被ELF标准规定用来标识ELF文件的平台属性,比如ELF字长(32位/64位)、字节序、ELF文件版本
最开始的4个字节 是所有ELF文件都必须相同的标识码,分别为0x7f 0x45 0x4c 0x46,第一个字节对应ASCII字符里面的DEL控制符、后面3个字节 是ELF这三个字母的ASCII码,这4个字节被称为魔数。第5个字节 标识ELF的文件类,0x01表示32位,0x02表示64位,第6位, 规定ELF文件是大端的还是小端的。第7个字节 规定了ELF文件的主版本号一般是1
2.2 段表
段表就是保存段的一些基本属性,描述了段的段名、段的长度、在文件中的偏移、读写权限以及其他属性。ELF文件的段结构是由段表决定的,编译器、链接器和装载器都是依靠段表来定位和访问各个段的属性的。段表在文件中的位置由ELF文件头的e_shoff成员决定。
下面是段描述符结构
287 typedef struct288 {289 Elf64_Word sh_name; /* 段名*/290 Elf64_Word sh_type; /* 段类型 */291 Elf64_Xword sh_flags; /* 段标志位*/292 Elf64_Addr sh_addr; /* 段虚拟地址 */293 Elf64_Off sh_offset; /* 段偏移 */294 Elf64_Xword sh_size; /* 段的长度 */295 Elf64_Word sh_link; /* 段的链接信息 */296 Elf64_Word sh_info; /* 段的链接信息*/297 Elf64_Xword sh_addralign; /* 段地址对齐 */298 Elf64_Xword sh_entsize; /* 项长度 */299 } Elf64_Shdr;
后记:段的名字对于编译器,链接器来说是有意义的,但是对于操作系统来说并没有实质的意义,对于操作系统来说,一个段如何处理取决于它的属性和权限,也就是段的类型和段的标志位这两个成员决定。
test.o段表结构
将test的所有段的位置和长度信息分析如下:空白处代表字节对齐,因为Section Table的长度为0x340,也就是832个字节,它包含了13个段描述符,每个段描述符为64个字节。
整个文件的结尾是Section Table,总长度为0x730,也就是1840个字节,也刚好是test.o的文件长度。
通过验证也确实是1840字节。
2.3 相关参数介绍
在段的结构体中:
段的类型(sh_type)
段的名字只是在链接和编译过程中有意义,但是不能真正地表示段的类型。对于编译器和链接器来说,主要决定段的属性的是段的类型(sh_type)和段的标志位(sh_flags),列举如下表
段的标志位(sh_flag)
段的标志位表示该段在进程虚拟地址空间中的属性,比如是否可写、是否可执行
对于系统中的保留段,下表也列举了段的类型和段的标志位属性,可以通过readelf -S test.o命令得到的属性进行对照
段的链接信息(sh_link、sh_info)
如果段的类型是与链接相关的(不论是动态链接还是静态链接),比如重定位表、符号表等,那么sh_link和sh_info这两个成员所包含的意义如下表所示,对于其他类型的段,这两个成员,没有意义
3.重定位表
这个也就是test.o中有一个叫做.rela.text的段和.rela.eh_frame的段,他们的类型都是SHT_RELA(其他的段类型含义可以到 /usr/include/elf.h 中查看),意思是带有添加项的重定位项,也就是说它是一个重定位表。也就是链接器在处理目标文件的时候,要对一些目标文件中某些部位进行重定位。关于重定位可以看hello.程序的编译过程
关于这里我想说的是关于eh_frame段和rela.eh_frame段查了很多资料目前还不知道存了什么,是什么意思。
一个重定位表同时也是一个ELF段,那么这个段的类型就是(sh_type)就是SHT_RELA类型,它的sh_link表示符号表的下表,它的sh_info表示它作用于哪个段。比如.rela.text作用于.text段,而.text段的下标为1,那么.rela.text的sh_info为1。
ELF和bin的区别
Gcc 编译出来的是ELF文件。通常gcc –o test test.c,生成的test文件就是ELF格式的,在linuxshell下输入 ./test就可以执行。
Bin 文件是经过压缩的可执行文件,去掉ELF格式的东西。是直接的内存映像的表示。在系统没有加载操作系统的时候可以执行。
elf(executable and link format)文件里面包含了符号表,汇编等。
BIN文件是将elf文件中的代码段,数据段,还有一些自定义的段抽取出来做成的一个内存的镜像。
在Embedded中,如果上电开始运行,没有OS系统,如果将ELF格式的文件烧写进去,包含一些ELF格式的东西,arm运行碰到这些指令,就会导致失败,如果用arm-softfloat-linux-gnu-objcopy生成纯粹的汇编 bin文件,程序就可以一步一步运行。
elf文件解析以及和bin文件的区别相关推荐
- 如何将大量图片文件合并成一个*.bin文件
文章目录 1.bin是啥 2. 首先将大量图片全都导成按你所要顺序编号的.bin文件 3.将这些.bin文件合成为一个.bin文件 4.问题它出现了(如果你没有出现问题此后内容可不看) 5.新的尝试 ...
- Keil MDK5生成bin文件时生成了*.bin文件夹
在Keil魔术棒中通过以下方式生成bin文件时,看提示命令执行成功,却生成了一个*.bin文件夹,文件夹内部是两个bin文件,当时感觉很奇怪,第一次遇到这种情况. 使用的命令:fromelf.exe ...
- java怎么xml文件解析_Java对Xml文件解析
JAVA 解析 XML 通常有两种方式,DOM 和 SAX. DOM 虽然是 W3C 的标准,提供了标准的解析方式,但它的解析效率一直不尽如人意,因为使用DOM解析XML时,解析器读入整个文档并构建一 ...
- [翻译]运用文件解析器在任意文件中使用虚拟应用路径(~)
原文出处:http://www.codeproject.com Using the FileResolver to allow virtual application paths ( ~ ) i ...
- 使用springMVC提供的CommonsMultipartResolver文件解析器,实现文件轻松上传
springMVC提供的前端控制器,可以拦截所有请求,指挥调度所有后台逻辑资源. 使用传统方式进行文件上传,需要我们手动解析request对象,获取文件上传项,再进行文件的上传. springMVC框 ...
- Keil如何生成bin文件【Keil生成Bin文件的方法】
使用过Keil的同鞋都知道,现在Keil中默认可以输出.axf的调试文件和可以通过钩选输出的.hex可执行文件,没有bin(二进制)文件的输出选项.可是偏偏某些时候需要或者习惯性的使用.bin文件来进 ...
- 服务器经过交换机传递文件丢失,H3C交换机bin文件丢失后补救方案
首先下载官方的交换机bin文件: 下载地址:http://www.h3c.com.cn/Service/Software_Download/ 下载相应的bin文件后,再下载一个TFTP上传工具: 下载 ...
- linux 显示bin 文件格式,bin文件扩展名,bin文件怎么打开?
.bin 文件类型1:Nintendo DS Binary File 文件说明:Binary file used by the Nintendo DS series portable gaming s ...
- java中 Excel文件解析及超大Excel文件读写
本文主要对Excel中数据的解析和生成进行总结 前言 在应用程序的开发过程中,我们经常要用到Excel进行数据的导入或导出.所以,在通过Java语言实现此类需求时,通常会对Excel文件进行解析或生成 ...
最新文章
- ustc小道消息20220113
- 数组中删数(只删一个)
- 规模估算失准 软件开发成空中楼阁
- 运维小姐姐说这篇Consul集群和ACL配置超给力(保姆级)
- js用函数实现输出100以内与7有关的数_走近(javascript, 函数式)
- java报错空指针异常_分析使用Spring Boot进行单元测试时,报出空指针异常
- Leetcode每日一题:48.rotate-image(旋转图像)
- 全网首发:安装Python(或其他软件)出现0x80072f7d错误的解决办法
- 目标检测之非极大值抑制(NMS)
- 基于51单片机的交通灯仿真方案原理图设计一个数码管
- Kafka原理介绍+安装+基本操作
- python画图旋转图形_python简单实现旋转图片的方法
- 【5G之道】第十四章:异构网络部署
- swiper 重新初始化
- 重磅消息:微信支付分最新开通方法!
- cocos3D 初体验
- 试用一片3-8译码器74LS138和其它必要的门电路设计一个一位全加器, 被加数为Ai, 加数为Bi, 低位来的进位为Ci-1, 本位和为Si, 本位对高位的进位为Ci
- 编写configure.ac
- 2021-04-29 微信登录简易版
- nginx-php类似nginx-lua的扩展,nginx-php中文开发文档
热门文章
- w7虚拟机服务器管理器,Hyper - V (五) 在Win7中安装Hyper - V 管理工具远程操作虚拟机...
- 【Linux-编译器gcc/glibc升级】CentOS7.9使用NodeJS18时报错/lib64/libm.so.6: version `GLIBC_2.27‘ not found
- 量子计算和人工智能:应该知道的10件事
- win8的几种关机方法。
- SpringMVC与Mybatis集合实现调用存储过程、事务控制
- OpenCV~图像深度
- 4399枪神传说服务器维护,电脑连4399枪神传说都卡?
- php报纸排版,校园文化节之网页设计暨报纸排版大赛
- 不去拼,你活着干啥?
- Oracle 11.2.0.4打PSU 11.2.0.4.161018