目标文件详解

目标文件(可能篇幅较长)

什么是目标文件?

编译器编译源代码后生成的文件叫做目标文件。

目标代码是指源代码经过编译程序产生的能被cpu直接识别二进制代码。

目标文件的格式

目标文件是源代码经过编译但未链接的那些中间文件。

windows上为.obj文件,linux上为.o文件

目标文件与可执行文件的内容和结构很相似。所以在广义上来看,目标文件与可执行文件可以看成是一种文件

在windows下,可以统称为PE-COFF文件格式。
在linux下,我们可以统称为ELF文件
可执行文件格式

目前PC平台流行以下两种可执行文件格式:

windows下的PE文件,linux上的ELF文件格式
这两种均为COFF格式的变种

ELF文件的四种类型

可重定位文件:包含代码和数据,可以被用来链接成可执行文件或共享目标文件,静态链接库可以归为这一类型。

windows的.obj文件,linux的.o文件

可执行文件:包含可以直接执行的程序

windows 下的.exe文件,linux下/bin/bash文件

共享目标文件:包含代码和数据,可以在一下两种情况使用。

①链接器使用其与其他可重定位文件和共享目标文件链接,产生新的目标文件。
②动态链接器将几个这种共享目标文件与可执行文件相结合,作为进程映像的一部分。

windows下的DLL文件,linux下的.so文件

核心转储文件:当进程意外终止时,系统用来储存该进程地址空间的内容以及终止时的一些其他信息

linxu下的core dump

目标文件剖析

目标文件将其中编译后的机器指令代码、数据、符号表、调试信息、字符串等以(有的时候也叫)存储。

	代码段(.text):程序源代码编译后的机器指令存放位置
	数据段(.data):初始化不为 0 的全局和静态数据存放位置
	数据段(.bss):未初始化或初始化为 0 的全局和静态数据存放位置

目标文件详解_第1张图片

ELF段剖析

程序源代码被编译后主要分为两种段:程序指令程序数据。代码段属于程序指令,而数据段和.bss段属于程序数据。

.text代码段

代码段通常是指用来存放程序执行代码的一块内存区域。
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。
在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

.data数据段和.rodata只读数据段

.data段保存到是哪些已经初始化了的全局静态变量局部静态变量
.rodata段存放的是只读数据,一般是程序里面的只读变量(const修饰)和字符串常量。
printf(“%d\n”, x);其中的“%d\n”就存放在.rodata段中。

.bss段

.bss段存放的是未初始化的全局变量和静态局部变量。

实际上,有些编译器知识对.bss段变量预留一个未定义的全局变量符号。
实际并不占用目标文件的空间(磁盘),只有当运行时被使用到才会真正的占用空间(内存)。

其他段

其他段都是用来保存与程序相关的其他信息,知道就行,没啥大的卵用。

.rodatal:存放只读数据,跟.rodata段一样
.comment:存放编译器版本信息
.debug:	  存放调试信息
.dynamic:存放动态链接信息
.hash:	  符号哈希表
.line:	  存放调试用的行号表
.note:	  存放额外的编译器信息
.strtab: 存放ELF文件中用到的各种字符串
.symtab: 符号表
.shstrtab:段名表
.plt&.got:动态链接的跳转表和全局入口表
.init&.fini:程序初始化与终结代码段
.rel.text: 重定位表

ELF结构剖析

文件头

ELF目标文件格式的最前部就是ELF文件头。它包含了描述整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等。
以下是文件头中各个成员及其含义
目标文件详解_第2张图片
目标文件详解_第3张图片

ELF魔数:确认文件类型。我们可以看到第一个e_ident这个成员。其中前四个字节称为ELF文件的魔数(如 0x45 E,0x4c L,0x46 F 代表的就是ELF文件)。
		 几乎所有的可执行文件开始几个字节都是魔数
文件类型:e_type成员用来表示ELF文件类型,通常是一个常量。系统通过常量来判断ELF真正的文件类型,而不是文件的扩展名。

段表

段表是一个被用来保存段的的基本属性结构。
编译器、链接器和装载器都是依靠段表来定位和访问各个段的属性的。
以下是段表中各个成员及其含义
目标文件详解_第4张图片

重定位表

在其他段的介绍中,有个.rel.text的重定位表段,其中存放了符号的重定位信息。而.text段中对符号的引用都要参考重定位表来实现符号的地址无关。

字符串表

字符串表存储了字符串信息,编译器将所有字符串集中起来存放到一个表,然后使用字符串表中的偏移来引用字符串。

参考文献

[1] 俞甲子 石凡 潘爱明.程序员的自我修养.电子工业出版社,2009.4.
[2] 百度百科 https://baike.baidu.com/item/%E4%BB%A3%E7%A0%81%E6%AE%B5

你可能感兴趣的:(程序员的自我修养)