您的位置 首页 设计

ARM开发各种烧写文件格局阐明(ELF、HEX、BIN)

一、ELFExecutableandlinkingformat(ELF)文件是x86Linux系统下的一种常用目标文件(objectfile)格式,有三种主要类型:(1)适于…

一、ELF

Executable and linking format(ELF)文件是x86Linux体系下的一种常用方针文件(object file)格局,有三种首要类型:
(1)适于衔接的可重定位文件(relocatable file),可与其它方针文件一同创立可履行文件和同享方针文件。
(2)适于履行的可履行文件(executable file),用于供给程序的进程映像,加载的内存履行。
(3)同享方针文件(shared object file),衔接器可将它与其它可重定位文件和同享方针文件衔接成其它的方针文件,动态衔接器又可将它与可履行文件和其它同享方针文件结合起来创立一个进程映像。
ELF文件格局比较复杂。

二、HEX

Intel HEX文件是记载文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记载,由十六进制数组成的机器码或许数据常量,Intel HEX文件经常被用于将程序或数据传输
存储到ROM、EPROM,大多数编程器和模拟器运用Intel HEX文件。
记载格局
一个Intel HEX文件能够包含恣意多的十六进制记载,每条记载有五个域,下面是一个记载的格局。
: llaaaatt[dd。。。]cc
每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描绘。
: 冒号 是每一条Intel HEX记载的开端
ll 是这条记载的长度域,他表明数据(dd)的字节数目。
aaaa 是地址域,他表明数据的开端地址
tt 这个域表明这条HEX记载的类型,他有或许是下面这几种类型
00 —-数据记载
01 —-文件完毕记载
02 —-扩展段地址记载
04 —-扩展线性地址记载
dd 是数据域,表明一个字节的数据,一个记载或许有多个数据字节,字节数目能够
检查ll域的阐明
cc 是效验和域,表明记载的效验和,计算方法是将本条记载冒号开端的一切字母对
所表明的十六进制数字
都加起来然后模除256得到的余数终究求出余数的补码便是本效验字节cc。
: 0300000002005E9D
cc=0×01+NOT((0×03+0×00+0×00+0×00+0×02+0×00+0×5E)%0×100)=0×01+0×9C=0×9D >
数据记载
Intel HEX文件由若干个数据记载组成,一个数据记载以一个回车和一个换行完毕
比方下面的一条数据记载
: 10246200464C5549442050524F46494C4500464C33
10 是此行记载数据的字节数目
2462 是数据在内存中的开端地址
00 是记载类型00(是一个数据记载)
464C 到 464C 是数据
33 是此行记载的效验和

三、BIN

BIN文件便是直接的二进制文件,内部没有地址符号。一般用编程器烧写时从00开端,而假如下载运转,则下载到编译时的地址即可。

总结:能够由ELF文件转化为其它两种文件,HEX也能够直接转换为BIN文件,可是BIN要转化为HEX文件有必要要给定一个基地址。而HEX和BIN不能转化为elf文件,因为ELF的信息量要大。其他还有一种ads的调试文件axf,
它能够转化为BIN文件,用以下指令 fromelf -nodebug xx。axf -bin xx。bin即可。

这儿所说的ARM体系根本文件格局,都是在依据ARM的嵌入式体系开发中常会碰到的文件格局。
ARM体系根本文件格局有三种:
1)BIN,平板式二进制格局,一般用于直接烧写到Flash中,也能够用于加载到monitor程序中。
2)ELF,EXECUTABLEANDLINKABLEFORMAT,一种通用的OBJECT文件格局,一般由GNUCOMPILERCOLLECTION(GCC)发生。
3)AXF,BIN格局的扩展版,主体部分同BIN,在文件头和尾参加了调试用的信息,用于AXD。
本文首要评论BIN与ELF。
首要阐明,ELF格局是一种OBJECT文件格局。一般OBJECT文件都能够分红三类:可重定位OBJECT文件,可履行OBJECT文件,同享OBJECT文件。ELF格局文件也能够分红这三种。
首要说说可重定位OBJECT文件。这种OBJECT文件一般由GCC中的ASSEMBLER(as)发生(请不要以为GCC仅仅编译器),里边除了二进制的机器代码,还有一些可用于进行重定位的信息。它首要是作为LINKER(ld)的输入,LINKER将跟据这些信息,将需求重定位的符号重定位,然后发生可履行的OBJECT文件。ELF格局的可重定位OBJECT文件由header与section组成。
Header包含ELFheader与sectionheader.ELFheader坐落文件的头部,用于存储方针机器的架构,巨细端装备,ELFheader巨细,object文件类型,sectionheader在文件中的偏移,sectionheader的巨细,sectionheader中的项目数等信息。Sectionheader则界说了文件中每个section的类型,方位,巨细等信息。Linker便是经过查找ELFheader,找到sectionheader的进口,再在sectionheader中找到相应的section进口,然后定位到方针section的。
Section包含
.text:经过编译的机器代码。
.rodata:只读的数据,例如printf(“hello!”)中的字符串hello。
.data:已初始化的大局变量,局部变量将在运转时被寄存在仓库中,不会在.data或.bss段中呈现。
.bss:未初始化的大局变量,在这儿仅仅一个占位符,在object文件中并没有实践的存储空间。
.symtab:符号表,用于寄存程序中被界说的或被引证到的大局变量和函数的信息。
.rel.text:一个保存着一系列在.text中的方位的列表。这些方位将在linker把这个文件与其它object文件兼并时被修正,一般来说,这些方位都是保存着一些引证到大局变量或许外部函数的指令。引证局部变量或许本地函数的指令是不需求被修正的,因为局部变量和本地函数的地址一般都是运用PC相对偏移地址的。需求留意的是,这个section和下面的.rel.data在运转时并不需求,生成可履行的ELFobject文件时会去掉这个section。
.rel.data:保存大局变量的重定位信息。一般来说,假如一个大局变量它的初始化值是另一个大局变量的地址,或许是外部函数的地址,那么它就需求被重定位。
.debug:保存debug信息。
.strtab:一个字符串表,保存着.symtab和.debug,和各个section的姓名。.symtab,.debug和sectiontable里边,但凡保存name的域,其实都是保存了一个偏移值,经过这个偏移值在这个字符串表里边能够找到相应得字符串。
下面细心评论一下.symtab:
每一个可重定位的object文件,都会有一个.symtab。这个符号表保存了在这个object文件中一切被界说的和被引证的符号。当源程序是C言语程序时,.symtab中的符号直接来源于C编译器(cc1)。这儿所说的符号首要有三种:
1)在这个object文件中被界说的能够被其他object文件大局符号。在C言语源程序中,首要便是那些非静态(没有static润饰的)的大局变量和非静态的函数。在ARM汇编言语中,便是那些被EXPORT指令导出的变量。
2)在这个object文件中引证到,可是在其他文件中界说的大局变量。在ARM汇编言语中便是经过IMPORT指令引进的变量
3)本地变量。本地变量只在本object文件内可见。这儿的本地变量指的是衔接器本地变量,应该和一般的程序本地变量作差异。这儿所指的本地变量,包含用static润饰的大局变量,object文件中section称号,源代码文件称号。一般意义上的本地变量,是在运转时由体系的运转时环境管理的,linker并不关怀。
每个契合上面条件的符号在.symtab文件中都会有一个数据项。这个数据项的数据结构是:

Typedefstruct{
intname;//符号称号,其实便是.strtab的偏移值
intvalue;//在section中的方位,以相对section地址的偏移表明
intsize;//巨细
chartype;//类型,一般是数据或函数
charbinding;//是本地变量仍是大局变量
charreserved;//保存的位
charsection;//符号所属的section。可选有:.text(用数字1代表),.data(用数
//3代表),ABS(不该被重定位的符号),UND(在本object文件
//中未界说的符号,或许在其他文件中界说),COM(一般的未初//始化的变量符号)。
}ELF_sym

现在假定组成运用的各个模块都现已被汇编,构建出了可重定位的object文件。这些object的结构都是相同的,有各自的.text,.datasection,有各自的.symtab.GCC下一步要做的便是运用linker(ld),把这些object文件,加上必要的库衔接成具有肯定运转时地址的可履行文件,便是可履行的ELF格局的文件。
Linker的衔接动作能够分为两部分:
1)符号解析。确认引证符号的指向。
2)符号重定位。兼并section,分配运转时环境地址,引证符号重定位。
符号解析:
在一个object文件中,有指令界说了符号,也有指令引证了符号。或许存在这样一种状况,一个被引证到的符号,有多重的界说。符号解析的效果便是确认,在这个object文件中,一个符号引证实在引证的是哪个符号。
在编译的时分,除了在本文件中界说的大局变量会由编译器生成一个符号表项之外,当发现一个被引证到的符号在本文件中并没有被界说,编译器也会主动发生一个符号表项,把确认这些引证的作业留给linker。汇编器在汇编时将读取这些符号表项,生成.symtab。在读取的进程中,假如发现有在无法确认的符号引证项,汇编器会为这些符号额定生成一个数据项,称作重定位数据项,寄存于rel.text或rel.datasection中,交由linker确认。下面是重定位数据项(relocationentry)的数据结构:

Typedefstruct{
intoffset;//指明需求被重定位的引证在object中的偏移,实践上便是需求被重定位的引证
//在object中的实践方位
intsymbol;//这个被重定位的引证实在指向的符号
inttype;//重定位类型:R_ARM_PC24:运用24bit的PC相对地址重定位引证
//R_ARM_ABS32:运用32bit肯定地址重定位引证
}Elf32_Rel

Linker需求解析的,便是那些被生成了重定位数据项的引证。Linker将依据C言语界说的规矩,关于每一个重定位数据项,在输入的各个object文件中查找合适的符号,把这个符号填入symbol项中。可是因为还不知道这个符号的实在地址,所以现在就算知道了引证的实在指向,但咱们仍是不能确认这个引证指向的地址。
符号重定位:
符号重定位用来处理上面的问题。Linker首要进行section的兼并。Linker兼并object文件的进程很简单,一般便是相同特点的section兼并,例如不同object文件的.textsection将被兼并成一个.text。相同,.symtabsection也被兼并成一个.symtab。这儿面涉及到两个问题:
1)各个object文件兼并的次序。这个问题涉及到终究指令和符号的运转地址。最为重要的是,究竟是哪个section排在最前头?在ARMRAW体系得开发进程中,这个最为重要。ARM体系CPU上电后,体系会主动的从0x00000000地址取指令并履行,这个地址上映射着存储器。这个动作是不可编程的。所以排在最前面的section一定要包含有程序的进口点,不然体系无法正常运转。
2)输入段与输出端之间的对应联系。理论上,任何section,都能够被随意的映射到一个输出段中。一个.datasection是能够与一个.textsection组成输出一个.text的。当然这样的动作毫无意义。咱们有必要告知linker运用那些section作为输入,发生一个输出section.
以上这两个问题,都是经过一个称为衔接脚本的文件操控的。Linker经过读取衔接脚本,来决议section从输入到输出的映射,设置程序的进口点,设置哪个section应该在整个可履行文件的头部等问题。
衔接脚本还有其他一个效果,那便是指定每个section的地址。在section兼并完结后,linker将跟据.symtab,对符号进行一致的编址,分配一个肯定的运转时地址。这个地址是以section地址作为基地址的。假定.textsection的地址是0x00000000,那么.text里边的符号将以0x00000000这个地址作为基准地址。指定section地址的作业也是由衔接脚本完结。在嵌入式开发中常见的在编译工程时需指定的text_base,data_base等参数,终究会被参加到衔接脚本中,然后完结section的地址分配。
以上两步完结后,linker履行引证符号重定位操作。Linker遍历.relsection(包含.reltext和.reldata),关于其间的每个数据项,依据symbol域到.symtab中查出相应的引证的实在地址(经过上面的地址分配,现在.symtab里边的符号都具有肯定的运转地址),再依据offset域供给的偏移,将这个地址填入相应的方位上。
至此,符号重定位作业悉数完结。Linker删去用于保存重定位信息的rel.text和rel.datasection,参加一个segmentheader和一个.initsection。生成可履行的ELF格局的object文件。
Segmentheader保存了用于操作体系内存映射的信息。.initsection包含了一个_init的函数。程序加载时,操作体系的程序加载器经过读取segmentheader,将程序加载到用户内存空间,并依据segmentheader里边映射信息,分别将.text段和.data段映射到恰当的地址上。然后再调用.init中的_init函数,完结初始化作业。
因为ELF文件具有通用性强的长处,现在盛行的开发形式是,先经过编译东西生成ELF文件格局的可履行文件,在运用外部东西,抽离出ELF文件中的相应部分,生成BIN文件。例如闻名的GNUbootloaderU-Boot,就采用了这种做法,编译器东西集是GCC,BIN生成东西是elf2bin。ARM公司闻名的开发环境ADS,尽管运用的是自家的armcc,和armcpp编译器,但他们的作业方式却是与GNUGCC千篇一律。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/ziliao/sheji/275112.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部