1.linux中有三类目标文件
**(1)可重定位目标文件(.o或者.a):**包含二进制代码和数据,其形式可以和其他目标文件进行合并,创建一个可执行目标文件。(.a文件是由很多个.o文件的集合)(查看.a信息可以关注变量的排的段位置)
**(2)可执行目标文件(.out)(符号文件):**包含二进制代码和数据,可直接被加载器加载执行。
**(3)共享目标文件(.so):**可被动态的加载和链接(本文暂时不讨论)
由此我们可知由汇编器生成的就是可重定位目标文件,经过链接器作用后才生成可执行目标文件,链接器的作用就是以一组可重定位目标文件作为输入,生成可加载和运行的可执行目标文件,具体需要完成以下两个工作:
**Ø 符号解析:**符号解析的目的是将目标文件中每个符号(静态变量、函数、全局变量)和其定义进行关联
**Ø 重定位:**将每个符号的定义与具体在虚拟内存中的位置进行关联
最终生成可执行目标文件。
2. ELF文件格式
2.1 目标文件和ELF的关系:
目标文件 在不同的系统或平台 上具有不同的命名格式,在Unix和X86-64 Linux上称为ELF(Executable and Linkable Format, ELF)。
由上可知,.o、.a、.so均是ELF格式的,ELF文件是有结构的文件。这类文件是分段进行组织的,段的个数可通过代码控制,但通常一个程序文件至少包含以下段:
.text段、.data段、bss段。
2.2 ELF的组成
ELF文件格式提供了两种不同的视角,在汇编器和链接器看来,ELF文件是由Section Header Table描述的一系列Section的集合,而执行一个ELF文件时,在加载器(Loader)看来它是由Program Header Table描述的一系列Segment的集合。
"Section"和"Segment"是计算机中常见的术语,它们的区别如下:
(1)范围不同:
"Section"通常用于可执行文件(如ELF文件),用于描述可执行文件中的不同部分。"Segment"通常用于内存分配,用于描述内存中的不同部分。
(2)用途不同:
"Section"通常用于存储代码、数据和符号表等信息。"Segment"通常用于管理物理内存,包括代码段、数据段、堆栈段等。
(3)映像关系不同:
"Section"通常是在编译时创建的,并成为可执行文件的一部分。"Segment"则是在运行时动态分配的,根据运行程序的需要进行相应的内存分配。
总之,"Section"和"Segment"用于不同的应用场景,其在实现和使用上也有所不同。
2.3 文件头
ELF的结构声明位于系统头文件 elf.h 中,ELF格式分为32位与64位两种,除了重定位类型稍有区别,其它大致相同,为了简化描述,后续说明将省略32/64字样。
ELF Header的声明如下 :
e_machine
e_verison:文件版本,目前常见的ELF 文件版本均为EV_CURRENT(1)。
e_entry:入口虚拟地址。
e_phoff:段表文件偏移。
e_shoff:节表文件偏移。
e_flags:处理器特定的标志,一般为0。
e_ehsize:Elf_Header的大小(字节)
e_phentsize:段头(Program Header)的大小(字节)。
e_phnum:段的数量。
e_shentsize:节头(Section Header)的大小(字节)。
e_shnum:字的数量。
e_shstrndx:节字符串表的节索引
2.4 ELF文件为什么不能直接读,要使用readelf解
ELF(Executable and Linkable Format)文件是一种常用的二进制文件格式,用于存储可执行程序、共享库和目标文件等。ELF文件的内部结构相对复杂,包含了各种各样的信息,如程序入口地址、段表、符号表、重定位表等。
由于ELF文件的结构复杂,直接读取和解析其中的信息并不容易。为了方便查看和分析ELF文件的内容,可以使用专门的工具,如readelf。readelf是一个用于读取和显示ELF文件信息的命令行工具,它可以解析ELF文件的各个部分,并以易于阅读的方式显示出来。
通过使用readelf,我们可以获取ELF文件的各种信息,如文件头信息、段表信息、符号表信息等。这些信息对于调试和分析程序非常有用。
总而言之,ELF文件之所以需要使用readelf解析,是因为它的内部结构复杂,需要特定的工具来解析和显示其中的信息。
readelf -a ASIC > LOG
注意:上面的链接视图是ELF文件ASIC的文件结构,文本文件LOG是用readelf解析出来看到的。flat.bin将利用bintools工具进行构造。