《程序员的自我修养》--目标文件有什么和ELF文件格式简述
来源:互联网 发布:他知而自不知的我属于 编辑:程序博客网 时间:2024/06/05 11:27
A.目标文件的格式
目标文件定义
源码经过编译之后但是没有经过链接的中间文件。
理解:
目标文件和可执行文件的结构相似,所以和可执行文件采用一种格式存储。可执行文件的格式,主要有PE(Portable Executable )和ELF(Executable Linkable Format)。目标文件和可执行文件可以看成一种类型的文件。同理,动态链接库和静态链接库也是按照可执行文件的格式存储的。
以后这里主要说的是Linux下的ELF存储格式。
几个例子:
B.目标文件的内容
段:目标文件的不同信息放在不同的段里。
#include <stdio.h>#include <stdlib.h>int global_var1 = 66; //全局变量1放在.data段int global_var2; //全局变量2放在.bss段int func(int temp){ return temp;} //func函数放在.text段int main(int argc, char *argv[]){ static int s_var1 = 77; //局部静态变量放在.data段 static int s_var2 = 0; //局部静态变量放在.bss段 int a = 1; //局部变量放在.text段 int b; //局部变量放在.text段 printf(" %d \n",func(a)); return 0;}
额外的解释:
段表:
一个描述文件中各个段的数组,它描述了段的属性,每个段在文件中的偏移等。
为什么数据和指令要分开?
1.代码安全。数据可读写,但是指令一定是只读,,如果把他们映射到两个虚存区域,则这两个虚存区域的权限可以设置成可读写和只读。
2.提高程序的局部性。
3.节省空间。指令只读就可以在内存中只留一份这样的指令(程序共享指令),可以节省空间。
C.再看目标文件的段们
源代码是这样的:
#include <stdio.h>#include <stdlib.h>int global_var1 = 66; //全局变量1放在.data段int global_var2; //全局变量2放在.bss段int func(int temp){ return temp;} //func函数放在.text段int main(int argc, char *argv[]){ static int s_var1 = 77; //局部静态变量放在.data段 static int s_var2 = 0; //局部静态变量放在.bss段 int a = 1; //局部变量放在.text段 int b; //局部变量放在.text段 printf(" %d \n",func(a)); return 0;}
它的目标文件是这样的:
(命令:objdump -h test.o)
.rodatal : 只读数据段
.comment : 注释信息段
.note.GNU-stack : 堆栈提示段
eh_frame: 异常调试段
查看源文件和目标文件数据的对应:
(命令:size test.o)
代码段:
数据段和只读数据段
bss段
其他段
D.说ELF文件结构
文件头:
第一个02:64位
第一个01:小端
第二个01:ELF版本号
**文件头结构**typedef struct{ unsigned char e_ident[16]; Elf32_Half e_type; Elf32_Half e_machine; Elf32_Word e_version; Elf32_Addr e_entry; Elf32_Off e_phoff; Elf32_Off e_shoff; Elf32_Word e_flags; Elf32_Half e_ephsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndex; } Elf32_Ehdr;
成员 readelf输出结果与含义
e_ident Magic:7f 454c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2’s complement, little endian
Version: 1 (current)
OS/ABI: UNIX-System V
ABI Version: 0
e_type Type: EXEC (executable file)
ELF文件类型
e_machine Machine: Intel 80386
ELF文件的CPU平台属性
e_version Version:0x1
ELF版本号:
一般为常数1
e_entry Entry point address: 0x8048320
入口地址
规定ELF程序的入口虚拟地址,操作系统在加载完成该程序后,从这个地址开始执行进程的指令。可重定位文件一般没有入口地址,则这个值为0
e_phoff Start of program headers: 52(bytes into file)
程序头表的偏移。参考下文的“连接视图和执行视图”
e_shoff Start of section headers: 4472(bytes into file)
段表在文件中的偏移,也就是从文件的4473个字节开始是段表内容
e_word Flags: 0x0
ELF标志位
用来标志一些ELF文件平台相关的属性。
e_ehsize Size of this header: 52(bytes)
ELF文件头本身的大小
e_phentsize Size of program headers: 32(bytes)
程序头大小
e_phnum Number of program headers:9
在执行视图中,Segments的数量
e_shentsize Size of section headers:40(bytes)
段表描述符大小
e_shnum Number of section headers:30
段表描述符的数量
这个值等于ELF文件中拥有的段(section)的数量。
e_shstrndx Section header string table index:
段表字符串表所在的段在段表中的下标。
段表
我的:
符号(链接的接口)
符号:函数和变量
符号名:函数名和变量名
ELF符号表结构体
typedef struct {Elf32_Word st_name; //该符号名在字符串表中的下标。Elf32_Addr st_value; //符号相对应的值。Elf32_Word st_size; //符号大小。对于包含数据的符号,这个值是该数据类型的大小unsigned char st_info; //符号类型和绑定信息。unsigned char st_other; //该成员目前为0,没用。Elf32_Half st_shndx; //符号所在的段。}Elf32_Sym;st_name符号名。这个成员包含了该符号名在字符串表中的下标(还记得字符串表吧?)st_value符号相对应的值。这个值跟符号有关,可能是一个绝对值,也可能是一个地址等,不同的符号,它所对应的值含义不同,见下文“符号值”st_size符号大小。对于包含数据的符号,这个值是该数据类型的大小。比如一个double型的符号它占用8个字节。如果该值为0,则表示该符号大小为0或未知st_info符号类型和绑定信息,见下文“符号类型与绑定信息”st_other该成员目前为0,没用st_shndx符号所在的段,见下文“符号所在段”
几个特殊符号
_executable_start 程序起始地址
_etext 代码段结束地址
edata 数据段结束地址
_end 程序结束地址
E.强弱符号和符号多次定义
出现原因
一个符号可能被多次重复定义。那么编译时候需要归并这些相同的符号。
强弱符号规则
1.不允许强符号多次被定义。
2.一个符号在a文件是强符号,b文件是弱符号,则选择强符号
3.都是弱符号,以占用空间最大的那个为准。
That is all.
- 《程序员的自我修养》--目标文件有什么和ELF文件格式简述
- 程序员的自我修养<3.目标文件有什么>
- 《程序员的自我修养》读书笔记2 -- ELF目标文件和静态链接和装载
- 【程序员的自我修养】第3章 目标文件里有什么?
- 程序员的自我修养——3、目标文件里有什么
- 目标文件、ELF文件的一点小总结 《程序员的自我修养》·笔记
- 程序员自我修养-目标文件的结构
- 程序员的自我修养 ch3 目标文件
- 程序员的自我修养:(1)目标文件
- 《程序员的自我修养——链接、装在与库》第三章《目标文件里有什么》读书笔记
- 自我修养——目标文件.o有什么
- elf文件分析-程序员的自我修养第三章学习
- 程序员自我修养--ELF文件结构
- 《程序员的自我修养》读书笔记----ELF格式
- 程序员的自我修养: 目标文件的本质
- 《程序员的自我修养》笔记--目标文件详解
- 程序员的自我修养——目标文件
- 学习程序员的自我修养之目标文件
- Java集合框架综述
- c语言基本数据类型short、int、long、char、float、double
- Java的反射
- 七天使的通讯(angelus)
- strcpy()源代码
- 《程序员的自我修养》--目标文件有什么和ELF文件格式简述
- Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)
- 顺序表和链表的比较
- c++优先队列用法
- Google C++单元测试框架---Gtest框架简介(译文)
- 问题四十五:怎么画ray tracing图形中的blending and joining surface
- Redis 源码解析 string内部实现原理之简单动态字符串SDS
- peak 选择何种数组
- Qt音频利用Phonon实现简单的音频播放