gcc生成可执行文件的过程是生成:源文件*.c文件(对象文件(*.o文件) );
链接程序ld,将对象文件*.o文件链接到可执行程序。
因此,要完全理解链接的过程,必须了解目标文件*.o的组织方式。
用一个简单的例子来说明:吧
#includeint global_var=5; extern int other_file_var; int main () { int a=1;
int b=a other_file_var; 返回0;
}gcc -c test.c -o test.o生成test.o;
查看test.o内容(vim test.o ) :
图1
看到的是乱码的山。 由于观点错误,因此目标文件(*.o )必须为elf格式,并使用objdump、readelf工具进行查看,就像mp3格式的文件必须在音乐播放器中播放一样。
从elf格式的官方文档中,可以看出elf格式的文件结构如下图所示为:
图2
分析一下每一个部分吧。
1. ELF文件头(头)分析
显示readelf-htest.oelf文件的标头信息
主要字段的含义如图所示。
根据Size of this headers,头部占64字节;
在hexdump -n 64 test.o中查看头部64字节的数据内容(十六进制格式); 图中的红框数据作为test.o文件的前64个字节(即elf头部),与前两个图相比,(图1 )的魔数7f454c4602010100000000000正好是图2 )的前16个字节)短语代码
头部信息结构参照/usr/include/elf.h中的ELf64_Ehdr,32位的是ELf32_Ehdr结构typedefstruct{
unsignedchare_ident[EI_NIDENT]; /*Magicnumberandotherinfo*/
Elf64_Halfe_type; /*Objectfiletype*/
Elf64_Halfe_machine;/*架构* /
Elf64_Worde_version;/*对象文件版本* /
Elf64_Addre_entry; /*Entrypointvirtualaddress*/
Elf64_Offe_phoff;/* programheadertablefileoffset * /
Elf64_Offe_shoff;/* sectionheadertablefileoffset * /
Elf64_Worde_flags;/*处理器-特殊标志* /
Elf64_Halfe_ehsize; /*ELFheadersizeinbytes*/
Elf64_Halfe_phentsize;/* programheadertableentrysize * /
Elf64_Halfe_phnum;/* programheadertableentrycount * /
Elf64_Halfe_shentsize;/* sectionheadertableentrysize * /
Elf64_Halfe_shnum;/* sectionheadertableentrycount * /
Elf64_Halfe_shstrndx;/* sectionheaderstringtableindex */} El f64 _ ehdr; 根据Start Of Section Header字段,test.o文件的656个字节包含“段标题表”。
2. ELF段头表(Section Header )分析
当在readelf -S test.o中查看“段的开头表”时,该表保存了文件中所有段的属性信息,例如段的名称、段的文件的开始位置、段的长度等:
图4
从图中可以看出,主要字段的含义从图中识别出来。
段表中的数据与文件开头0x290处的ELF Header Start Of Section Header字段相匹配。
该段共有12项,不同项描述了不同段落的属性;
2.1文本段
text段距离test.o文件的开头0x40字节,长度为0x20字节。 在hexdump -s0x40 -n0x20 test.o中查看文本段的十六进制内容。
图5
objdump -d test.o打印程序的反汇编代码,
图6
从上面的两个图可以看出,text部分的数据正好是main函数的机器代码,即text段中保存的是代码段。
2.2数据段
data段距离test.o文件的开头0x60字节,长度为04字节。 使用hexdump -s0x60 -n0x4 test.o查看data段的十六进制内容。
图7
4字节正好是int的长度,其中保存的数值是5,也就是全局变量global_var的值,验证了初始化的全局变量保存在data段中。
2.3 bss段
2.4.Rela.text(text的重新定位段) )。
main函数中的global_var是在另一个文件中定义的,后面的链接必须根据另一个文件确定其虚拟内存地址。 包含. rela.text段,因为text具有需要重新定位的变量。 readelf -r test.o
图8
offset列表示需要重新定位的符号段内的偏移。 这里表示从text段0xd的偏移。
info列的前四个字节是. symtab符号的索引。 请参阅下图。
图9
2.5 .symtab符号表
图9
ndx列是段表中符号的索引。 (1)例如,global_var的索引是3,图4中的索引3表示数据段,
也就是说,global_var这个符号位于data段; )2) UND )的情况下,表示该符号被定义在其他文件中,需要重新配置。 再配置信息参考“2.4 .rela.text”。
图10